File indexing completed on 2024-04-14 14:35:56
0001 /************************************************************************ 0002 * * 0003 * This file is part of Kooka, a scanning/OCR application using * 0004 * Qt <http://www.qt.io> and KDE Frameworks <http://www.kde.org>. * 0005 * * 0006 * Copyright (C) 2003-2016 Klaas Freitag <freitag@suse.de> * 0007 * Jonathan Marten <jjm@keelhaul.me.uk> * 0008 * * 0009 * Kooka is free software; you can redistribute it and/or modify it * 0010 * under the terms of the GNU Library General Public License as * 0011 * published by the Free Software Foundation and appearing in the * 0012 * file COPYING included in the packaging of this file; either * 0013 * version 2 of the License, or (at your option) any later version. * 0014 * * 0015 * As a special exception, permission is given to link this program * 0016 * with any version of the KADMOS OCR/ICR engine (a product of * 0017 * reRecognition GmbH, Kreuzlingen), and distribute the resulting * 0018 * executable without including the source code for KADMOS in the * 0019 * source distribution. * 0020 * * 0021 * This program is distributed in the hope that it will be useful, * 0022 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0024 * GNU General Public License for more details. * 0025 * * 0026 * You should have received a copy of the GNU General Public * 0027 * License along with this program; see the file COPYING. If * 0028 * not, see <http://www.gnu.org/licenses/>. * 0029 * * 0030 ************************************************************************/ 0031 0032 #include "kookaprint.h" 0033 0034 #include <math.h> 0035 0036 #include <qpainter.h> 0037 #include <qfontmetrics.h> 0038 #include <qguiapplication.h> 0039 0040 #include <klocalizedstring.h> 0041 0042 #include "scanimage.h" 0043 0044 #include "imgprintdialog.h" 0045 #include "kookasettings.h" 0046 #include "kscandevice.h" 0047 #include "kooka_logging.h" 0048 0049 0050 #define CUT_MARGIN 5 // margin in millimetres 0051 0052 #define PRINT_ORDER_COLUMNS 0053 #define CUTMARKS_COLOURSEGS 0054 0055 0056 KookaPrint::KookaPrint() 0057 : QPrinter(QPrinter::HighResolution) 0058 { 0059 qCDebug(KOOKA_LOG); 0060 m_image = nullptr; 0061 0062 // Initial default print parameters 0063 m_scaleOption = static_cast<KookaPrint::ScaleOption>(KookaSettings::printScaleOption()); 0064 m_printSize = KookaSettings::printPrintSize(); 0065 m_maintainAspect = KookaSettings::printMaintainAspect(); 0066 m_lowResDraft = KookaSettings::printLowResDraft(); 0067 m_cutsOption = static_cast<KookaPrint::CutMarksOption>(KookaSettings::printCutsOption()); 0068 0069 setOutputFileName(KookaSettings::printFileName()); 0070 0071 m_screenResolution = -1; // set by caller 0072 m_scanResolution = -1; // taken from image 0073 m_copyMode = false; // normal print mode 0074 } 0075 0076 0077 void KookaPrint::recalculatePrintParameters() 0078 { 0079 if (m_image==nullptr) return; // no image to print 0080 0081 qCDebug(KOOKA_LOG) << "image:"; 0082 qCDebug(KOOKA_LOG) << " size (pix) =" << m_image->size(); 0083 qCDebug(KOOKA_LOG) << " dpi X =" << DPM_TO_DPI(m_image->dotsPerMeterX()); 0084 qCDebug(KOOKA_LOG) << " dpi Y =" << DPM_TO_DPI(m_image->dotsPerMeterY()); 0085 qCDebug(KOOKA_LOG) << "printer:"; 0086 qCDebug(KOOKA_LOG) << " name =" << printerName(); 0087 qCDebug(KOOKA_LOG) << " colour mode =" << colorMode(); 0088 qCDebug(KOOKA_LOG) << " full page?" << fullPage(); 0089 qCDebug(KOOKA_LOG) << " output format =" << outputFormat(); 0090 qCDebug(KOOKA_LOG) << " paper rect (mm) =" << paperRect(QPrinter::Millimeter); 0091 qCDebug(KOOKA_LOG) << " page rect (mm) =" << pageRect(QPrinter::Millimeter); 0092 qCDebug(KOOKA_LOG) << " resolution =" << resolution(); 0093 qCDebug(KOOKA_LOG) << "options:"; 0094 qCDebug(KOOKA_LOG) << " scale mode =" << m_scaleOption; 0095 qCDebug(KOOKA_LOG) << " print size (mm) =" << m_printSize; 0096 qCDebug(KOOKA_LOG) << " scan resolution =" << m_scanResolution; 0097 qCDebug(KOOKA_LOG) << " screen resolution =" << m_screenResolution; 0098 qCDebug(KOOKA_LOG) << " cuts option =" << m_cutsOption; 0099 qCDebug(KOOKA_LOG) << " maintain aspect?" << m_maintainAspect; 0100 qCDebug(KOOKA_LOG) << " low res draft?" << m_lowResDraft; 0101 0102 // Calculate the available page size, in real world units 0103 QRectF r = pageRect(QPrinter::Millimeter); 0104 mPageWidthMm = r.width(); 0105 mPageHeightMm = r.height(); 0106 0107 // Calculate the size at which the image is to be printed, 0108 // depending on the scaling option. 0109 0110 mImageWidthPix = m_image->width(); // image size in pixels 0111 mImageHeightPix = m_image->height(); 0112 0113 if (m_scaleOption==KookaPrint::ScaleScan) // Original scan size 0114 { 0115 const int imageRes = m_scanResolution!=-1 ? DPI_TO_DPM(m_scanResolution) : m_image->dotsPerMeterX(); 0116 Q_ASSERT(imageRes>0); // dots per metre 0117 mPrintWidthMm = double(mImageWidthPix)/imageRes*1000; 0118 mPrintHeightMm = double(mImageHeightPix)/imageRes*1000; 0119 } 0120 else if (m_scaleOption==KookaPrint::ScaleScreen) // Scale to screen resolution 0121 { 0122 int screenRes = DPI_TO_DPM(m_screenResolution); 0123 Q_ASSERT(screenRes>0); // dots per metre 0124 mPrintWidthMm = double(mImageWidthPix)/screenRes*1000; 0125 mPrintHeightMm = double(mImageHeightPix)/screenRes*1000; 0126 } 0127 else if (m_scaleOption==KookaPrint::ScaleCustom) // Custom size 0128 { 0129 // For this option, "Maintain aspect ratio" can be enabled in the GUI. 0130 // There is however no need to take account of it here, because the 0131 // values are already scaled/adjusted there. 0132 0133 mPrintWidthMm = double(m_printSize.width()); 0134 mPrintHeightMm = double(m_printSize.height()); 0135 Q_ASSERT(mPrintWidthMm>0 && mPrintHeightMm>0); 0136 } 0137 else if (m_scaleOption==KookaPrint::ScaleFitPage) // Fit to one page 0138 { 0139 mPrintWidthMm = mPageWidthMm; 0140 mPrintHeightMm = mPageHeightMm; 0141 0142 // If cut marks are being "always" shown, then reduce the printed 0143 // image size here to account for them. For the other cut marks 0144 // options, the image for this scale will by definition fit on one page 0145 // and so they will not be shown. 0146 0147 if (m_cutsOption==KookaPrint::CutMarksAlways) 0148 { 0149 mPrintWidthMm -= 2*CUT_MARGIN; 0150 mPrintHeightMm -= 2*CUT_MARGIN; 0151 } 0152 0153 if (m_maintainAspect) // maintain the aspect ratio 0154 { 0155 QRectF r = pageRect(QPrinter::DevicePixel); 0156 double wAspect = r.width()/mImageWidthPix; // scaling ratio image -> page 0157 double hAspect = r.height()/mImageHeightPix; 0158 0159 if (wAspect>hAspect) 0160 { 0161 // More scaling up is needed in the horizontal direction, 0162 // so reduce that to maintain the aspect ratio 0163 mPrintWidthMm *= hAspect/wAspect; 0164 } 0165 else if (hAspect>wAspect) 0166 { 0167 // More scaling up is needed in the vertical direction, 0168 // so reduce that to maintain the aspect ratio 0169 mPrintHeightMm *= wAspect/hAspect; 0170 } 0171 } 0172 } 0173 else Q_ASSERT(false); 0174 0175 qCDebug(KOOKA_LOG) << "scaled image size (mm) =" << QSizeF(mPrintWidthMm, mPrintHeightMm); 0176 0177 mPrintResolution = DPI_TO_DPM(resolution())/1000; // dots per millimetre 0178 0179 // Now that we have the image size to be printed, 0180 // see if cut marks are required. 0181 0182 mPageWidthAdjustedMm = mPageWidthMm; 0183 mPageHeightAdjustedMm = mPageHeightMm; 0184 0185 bool withCutMarks; 0186 if (m_cutsOption==KookaPrint::CutMarksMultiple) withCutMarks = !(mPrintWidthMm<=mPageWidthMm && mPrintHeightMm<=mPageHeightMm); 0187 else if (m_cutsOption==KookaPrint::CutMarksAlways) withCutMarks = true; 0188 else if (m_cutsOption==KookaPrint::CutMarksNone) withCutMarks = false; 0189 else Q_ASSERT(false); 0190 qCDebug(KOOKA_LOG) << "for cuts" << m_cutsOption << "with marks?" << withCutMarks; 0191 0192 // If cut marks are required, reduce the available page size 0193 // to allow for them. 0194 0195 mPrintLeftPix = 0; // page origin of print 0196 mPrintTopPix = 0; 0197 0198 if (withCutMarks) 0199 { 0200 mPageWidthAdjustedMm -= 2*CUT_MARGIN; 0201 mPageHeightAdjustedMm -= 2*CUT_MARGIN; 0202 qCDebug(KOOKA_LOG) << "adjusted page size (mm) =" << QSizeF(mPageWidthAdjustedMm, mPageHeightAdjustedMm); 0203 0204 mPrintLeftPix = mPrintTopPix = CUT_MARGIN*mPrintResolution; 0205 } 0206 0207 bool onOnePage = (mPrintWidthMm<=mPageWidthAdjustedMm && mPrintHeightMm<=mPageHeightAdjustedMm); 0208 qCDebug(KOOKA_LOG) << "on one page?" << onOnePage; // see if fits on one page 0209 // must be true for this 0210 if (m_scaleOption==KookaPrint::ScaleFitPage) Q_ASSERT(onOnePage); 0211 0212 // If the image fits on one page, then adjust the print margins so 0213 // that it is centered. I'm not sure whether this is the right thing 0214 // to do, but it is implied by tool tips set in ImgPrintDialog. 0215 // TODO: maybe make it an option 0216 0217 if (onOnePage) 0218 { 0219 int widthSpareMm = mPageWidthAdjustedMm-mPrintWidthMm; 0220 mPrintLeftPix += (widthSpareMm/2)*mPrintResolution; 0221 int heightSpareMm = mPageHeightAdjustedMm-mPrintHeightMm; 0222 mPrintTopPix += (heightSpareMm/2)*mPrintResolution; 0223 } 0224 0225 // Calculate how many parts (including partial parts) 0226 // the image needs to be sliced up into. 0227 0228 double ipart; 0229 double fpart = modf(mPrintWidthMm/mPageWidthAdjustedMm, &ipart); 0230 //qCDebug(KOOKA_LOG) << "for cols ipart" << ipart << "fpart" << fpart; 0231 mPrintColumns = qRound(ipart)+(fpart>0 ? 1 : 0); 0232 fpart = modf(mPrintHeightMm/mPageHeightAdjustedMm, &ipart); 0233 //qCDebug(KOOKA_LOG) << "for rows ipart" << ipart << "fpart" << fpart; 0234 mPrintRows = qRound(ipart)+(fpart>0 ? 1 : 0); 0235 0236 int totalPages = mPrintColumns*mPrintRows; 0237 qCDebug(KOOKA_LOG) << "print cols" << mPrintColumns << "rows" << mPrintRows << "pages" << totalPages; 0238 Q_ASSERT(totalPages>0); // checks for sanity 0239 if (onOnePage) Q_ASSERT(totalPages==1); 0240 0241 qCDebug(KOOKA_LOG) << "done"; 0242 } 0243 0244 0245 void KookaPrint::printImage() 0246 { 0247 if (m_image==nullptr) return; // no image to print 0248 qCDebug(KOOKA_LOG) << "starting"; 0249 QGuiApplication::setOverrideCursor(Qt::WaitCursor); // this may take some time 0250 0251 if (!m_copyMode) 0252 { 0253 // Save the print parameters used 0254 KookaSettings::setPrintScaleOption(m_scaleOption); 0255 KookaSettings::setPrintPrintSize(m_printSize); 0256 KookaSettings::setPrintMaintainAspect(m_maintainAspect); 0257 KookaSettings::setPrintLowResDraft(m_lowResDraft); 0258 KookaSettings::setPrintCutsOption(m_cutsOption); 0259 KookaSettings::setPrintFileName(outputFileName()); 0260 KookaSettings::self()->save(); 0261 } 0262 else qCDebug(KOOKA_LOG) << "copy mode, not saving print parameters"; 0263 0264 #if 1 0265 // TODO: does this work? 0266 if (m_lowResDraft) setResolution(75); 0267 #endif 0268 0269 // Create the painter after all the print parameters have been set. 0270 QPainter painter(this); 0271 painter.setRenderHint(QPainter::SmoothPixmapTransform); 0272 0273 // The image is to be printed as 'mPrintColumns' columns in 'mPrintRows' 0274 // rows. Each whole slice is 'sliceWidthPix' pixels wide and 'sliceHeightPix' 0275 // pixels high; the last slice in each row and column may be smaller. 0276 0277 int sliceWidthPix = qRound(mImageWidthPix*mPageWidthAdjustedMm/mPrintWidthMm); 0278 int sliceHeightPix = qRound(mImageHeightPix*mPageHeightAdjustedMm/mPrintHeightMm); 0279 qCDebug(KOOKA_LOG) << "slice size =" << QSize(sliceWidthPix, sliceHeightPix); 0280 0281 // Print columns and rows in this order, so that in the usual printer 0282 // and alignment case the sheets line up corresponding with the columns. 0283 0284 const int totalPages = mPrintColumns*mPrintRows; 0285 int page = 1; 0286 #ifdef PRINT_ORDER_COLUMNS 0287 for (int col = 0; col<mPrintColumns; ++col) 0288 #else 0289 for (int row = 0; row<mPrintRows; ++row) 0290 #endif 0291 { 0292 #ifdef PRINT_ORDER_COLUMNS 0293 for (int row = 0; row<mPrintRows; ++row) 0294 #else 0295 for (int col = 0; col<mPrintColumns; ++col) 0296 #endif 0297 { 0298 qCDebug(KOOKA_LOG) << "print page" << page << "col" << col << "row" << row; 0299 0300 // The slice starts at 'sliceLeftPix' and 'sliceTopPix' in the image. 0301 int sliceLeftPix = col*sliceWidthPix; 0302 int sliceTopPix = row*sliceHeightPix; 0303 0304 // Calculate the source rectangle within the image 0305 int thisWidthPix = qMin(sliceWidthPix, (mImageWidthPix-sliceLeftPix)); 0306 int thisHeightPix = qMin(sliceHeightPix, (mImageHeightPix-sliceTopPix)); 0307 const QRect sourceRect(sliceLeftPix, sliceTopPix, thisWidthPix, thisHeightPix); 0308 0309 // Calculate the target rectangle on the painter 0310 int targetWidthPix = qRound((mPageWidthAdjustedMm*mPrintResolution)*(double(thisWidthPix)/sliceWidthPix)); 0311 int targetHeightPix = qRound((mPageHeightAdjustedMm*mPrintResolution)*(double(thisHeightPix)/sliceHeightPix)); 0312 const QRect targetRect(mPrintLeftPix, mPrintTopPix, targetWidthPix, targetHeightPix); 0313 0314 qCDebug(KOOKA_LOG) << " " << sourceRect << "->" << targetRect; 0315 // The markers are drawn first so that the image will overwrite them. 0316 drawCornerMarkers(&painter, targetRect, row, col, mPrintRows, mPrintColumns); 0317 // Then the image rectangle. 0318 painter.drawImage(targetRect, *m_image, sourceRect); 0319 0320 ++page; 0321 if (page<=totalPages) newPage(); // not for the last page 0322 } 0323 } 0324 0325 QGuiApplication::restoreOverrideCursor(); 0326 qCDebug(KOOKA_LOG) << "done"; 0327 } 0328 0329 0330 // Draw a cross marker centered on that corner of the printed image. 0331 void KookaPrint::drawMarkerAroundPoint(QPainter *painter, const QPoint &p) 0332 { 0333 const int len = (CUT_MARGIN-1)*mPrintResolution; // length in device pixels 0334 0335 painter->save(); 0336 painter->setPen(QPen(QBrush(Qt::black), 0)); // cosmetic pen width 0337 painter->drawLine(p-QPoint(len, 0), p+QPoint(len, 0)); 0338 painter->drawLine(p-QPoint(0, len), p+QPoint(0, len)); 0339 painter->restore(); 0340 } 0341 0342 0343 void KookaPrint::drawCutSign(QPainter *painter, const QPoint &p, int num, Qt::Corner dir) 0344 { 0345 painter->save(); 0346 int start = 0; 0347 const int radius = (CUT_MARGIN-2)*mPrintResolution; // offset in device pixels 0348 0349 QColor brushColor(Qt::red); 0350 int toffX = 0; 0351 int toffY = 0; 0352 QString numStr = QString::number(num); 0353 0354 QFontMetrics fm = painter->fontMetrics(); 0355 int textWidth = fm.horizontalAdvance(numStr)/2; 0356 int textHeight = fm.height()/2; 0357 int textYOff = 0; 0358 int textXOff = 0; 0359 switch (dir) { 0360 case Qt::BottomLeftCorner: 0361 start = -90; 0362 brushColor = Qt::green; 0363 toffX = -1; 0364 toffY = 1; 0365 textXOff = -1 * textWidth; 0366 textYOff = textHeight; 0367 break; 0368 case Qt::TopLeftCorner: 0369 start = -180; 0370 brushColor = Qt::blue; 0371 toffX = -1; 0372 toffY = -1; 0373 textXOff = -1 * textWidth; 0374 textYOff = textHeight; 0375 break; 0376 case Qt::TopRightCorner: 0377 start = -270; 0378 brushColor = Qt::yellow; 0379 toffX = 1; 0380 toffY = -1; 0381 textXOff = -1 * textWidth; 0382 textYOff = textHeight; 0383 break; 0384 case Qt::BottomRightCorner: 0385 start = 0; 0386 brushColor = Qt::magenta; 0387 toffX = 1; 0388 toffY = 1; 0389 textXOff = -1 * textWidth; 0390 textYOff = textHeight; 0391 break; 0392 default: 0393 start = 0; 0394 } 0395 0396 /* to draw around the point p, subtraction of the half radius is needed */ 0397 int x = p.x() - radius / 2; 0398 int y = p.y() - radius / 2; 0399 0400 // painter->drawRect( x, y, radius, radius ); /* debug !!! */ 0401 const int tAway = radius * 3 / 4; 0402 0403 int textX = p.x() + tAway * toffX + textXOff; 0404 int textY = p.y() + tAway * toffY + textYOff; 0405 0406 //painter->drawRect( textX, textY, bRect.width(), bRect.height() ); 0407 painter->drawText(textX, textY, numStr); 0408 0409 #ifdef CUTMARKS_COLOURSEGS 0410 QBrush b(brushColor); // draw a colour segment 0411 painter->setBrush(b); // to show correct orientation 0412 painter->drawPie(x, y, radius, radius, start*16, -90*16); 0413 #endif 0414 0415 painter->restore(); 0416 } 0417 0418 0419 // Draw the circle and the numbers that indicate the adjacent pages 0420 void KookaPrint::drawCornerMarkers(QPainter *painter, const QRect &targetRect, 0421 int row, int col, int maxRows, int maxCols) 0422 { 0423 const bool multiPages = (maxRows>1 || maxCols>1); 0424 0425 const bool firstColumn = (col==0); 0426 const bool lastColumn = (col==(maxCols-1)); 0427 const bool firstRow = (row==0); 0428 const bool lastRow = (row==(maxRows-1)); 0429 0430 #ifdef PRINT_ORDER_COLUMNS 0431 const int indx = maxRows*col + row + 1; 0432 #else 0433 const int indx = maxCols*row + col + 1; 0434 #endif 0435 //qCDebug(KOOKA_LOG) << "for col" << col << "/" << maxCols << "row" << row << "/" << maxRows << "-> index" << indx; 0436 0437 // All the measurements here are derived from 'targetRect', 0438 // which is in device pixels. 0439 0440 // Page index, if required 0441 if (multiPages) 0442 { 0443 const QString numStr = QString("= %1 =").arg(indx); 0444 const QFontMetrics &fm = painter->fontMetrics(); 0445 const int xoff = targetRect.left()+((targetRect.width()-fm.horizontalAdvance(numStr))/2); 0446 0447 painter->setPen(Qt::black); 0448 painter->drawText(xoff, fm.height()-1, numStr); 0449 } 0450 0451 // Top left 0452 QPoint p = targetRect.topLeft(); 0453 drawMarkerAroundPoint(painter, p); 0454 if (multiPages) 0455 { 0456 #ifdef PRINT_ORDER_COLUMNS 0457 if (!firstColumn) drawCutSign(painter, p, indx - maxRows, Qt::BottomLeftCorner); 0458 if (!firstRow) drawCutSign(painter, p, indx - 1, Qt::TopRightCorner); 0459 if (!firstColumn && !firstRow) drawCutSign(painter, p, indx - maxRows - 1, Qt::TopLeftCorner); 0460 #else 0461 if (!firstColumn) drawCutSign(painter, p, indx - 1, Qt::BottomLeftCorner); 0462 if (!firstRow) drawCutSign(painter, p, indx - maxCols, Qt::TopRightCorner); 0463 if (!firstColumn && !firstRow) drawCutSign(painter, p, indx - maxCols - 1, Qt::TopLeftCorner); 0464 #endif 0465 } 0466 0467 // Top right 0468 p = targetRect.topRight(); 0469 drawMarkerAroundPoint(painter, p); 0470 if (multiPages) 0471 { 0472 #ifdef PRINT_ORDER_COLUMNS 0473 if (!lastColumn) drawCutSign(painter, p, indx + maxRows, Qt::BottomRightCorner); 0474 if (!firstRow) drawCutSign(painter, p, indx - 1, Qt::TopLeftCorner); 0475 if (!lastColumn && !firstRow) drawCutSign(painter, p, indx + maxRows - 1, Qt::TopRightCorner); 0476 #else 0477 if (!lastColumn) drawCutSign(painter, p, indx + 1, Qt::BottomRightCorner); 0478 if (!firstRow) drawCutSign(painter, p, indx - maxCols, Qt::TopLeftCorner); 0479 if (!lastColumn && !firstRow) drawCutSign(painter, p, indx - maxCols + 1, Qt::TopRightCorner); 0480 #endif 0481 } 0482 0483 // Bottom right 0484 p = targetRect.bottomRight(); 0485 drawMarkerAroundPoint(painter, p); 0486 if (multiPages) 0487 { 0488 #ifdef PRINT_ORDER_COLUMNS 0489 if (!lastColumn) drawCutSign(painter, p, indx + maxRows, Qt::TopRightCorner); 0490 if (!lastRow) drawCutSign(painter, p, indx + 1, Qt::BottomLeftCorner); 0491 if (!lastColumn && !lastRow) drawCutSign(painter, p, indx + maxRows + 1, Qt::BottomRightCorner); 0492 #else 0493 if (!lastColumn) drawCutSign(painter, p, indx + 1, Qt::TopRightCorner); 0494 if (!lastRow) drawCutSign(painter, p, indx + maxCols, Qt::BottomLeftCorner); 0495 if (!lastColumn && !lastRow) drawCutSign(painter, p, indx + maxCols + 1, Qt::BottomRightCorner); 0496 #endif 0497 } 0498 0499 // Bottom left 0500 p = targetRect.bottomLeft(); 0501 drawMarkerAroundPoint(painter, p); 0502 if (multiPages) 0503 { 0504 #ifdef PRINT_ORDER_COLUMNS 0505 if (!firstColumn) drawCutSign(painter, p, indx - maxRows, Qt::TopLeftCorner); 0506 if (!lastRow) drawCutSign(painter, p, indx + 1, Qt::BottomRightCorner); 0507 if (!firstColumn && !lastRow) drawCutSign(painter, p, indx - maxRows + 1, Qt::BottomLeftCorner); 0508 #else 0509 if (!firstColumn) drawCutSign(painter, p, indx - 1, Qt::TopLeftCorner); 0510 if (!lastRow) drawCutSign(painter, p, indx + maxCols, Qt::BottomRightCorner); 0511 if (!firstColumn && !lastRow) drawCutSign(painter, p, indx + maxCols - 1, Qt::BottomLeftCorner); 0512 #endif 0513 } 0514 } 0515 0516 0517 void KookaPrint::setCopyMode(bool on) 0518 { 0519 qCDebug(KOOKA_LOG) << on; 0520 m_copyMode = on; 0521 }