File indexing completed on 2024-06-23 05:48:53
0001 /* 0002 This file is part of the Okteta Kasten module, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2007-2008 Friedrich W. H. Kossebau <kossebau@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0007 */ 0008 0009 #include "printtool.hpp" 0010 0011 // controller 0012 #include "printjob.hpp" 0013 #include "printdialog.hpp" 0014 #include "framestopaperprinter.hpp" 0015 #include "headerfooterframerenderer.hpp" 0016 #include "bytearrayframerenderer.hpp" 0017 // Okteta Kasten gui 0018 #include <Kasten/Okteta/ByteArrayView> 0019 // Okteta Kasten core 0020 #include <Kasten/Okteta/ByteArrayDocument> 0021 // Okteta core 0022 #include <Okteta/AbstractByteArrayModel> 0023 // Kasten core 0024 #include <Kasten/AbstractModelSynchronizer> 0025 // KF 0026 #include <KLocalizedString> 0027 #include <KMessageBox> 0028 // Qt 0029 #include <QApplication> 0030 #include <QPrinter> 0031 #include <QPageLayout> 0032 #include <QFont> 0033 #include <QFontMetrics> 0034 0035 namespace Kasten { 0036 0037 PrintTool::PrintTool() = default; 0038 0039 PrintTool::~PrintTool() = default; 0040 0041 void PrintTool::setTargetModel(AbstractModel* model) 0042 { 0043 // if( mByteArrayView ) mByteArrayView->disconnect( this ); 0044 0045 mByteArrayView = model ? model->findBaseModel<ByteArrayView*>() : nullptr; 0046 0047 mDocument = mByteArrayView ? qobject_cast<ByteArrayDocument*>(mByteArrayView->baseModel()) : nullptr; 0048 mByteArrayModel = mDocument ? mDocument->content() : nullptr; 0049 0050 const bool hasView = (mByteArrayView && mByteArrayModel); 0051 Q_EMIT viewChanged(hasView); 0052 } 0053 0054 void PrintTool::print() 0055 { 0056 auto* printer = new QPrinter; 0057 0058 // LayoutDialogPage* layoutPage = new LayoutDialogPage(); 0059 // QList<QWidget*> customDialogPages; 0060 // customDialogPages << layoutPage; 0061 auto* printDialog = new PrintDialog(printer, QApplication::activeWindow()); 0062 // Disable PrintPageRange, this tells Qt we can't do client-side page selection, 0063 // so it will try do server-side page selection if supported 0064 printDialog->setOption(QPrintDialog::PrintPageRange, false); 0065 // printDialog->setOptionTabs(customDialogPages); 0066 0067 printDialog->setWindowTitle(i18nc("@title:window", "Print Byte Array %1", mDocument->title())); 0068 connect(printDialog, qOverload<QPrinter*>(&QPrintDialog::accepted), this, &PrintTool::triggerPrint); 0069 printDialog->open(); 0070 } 0071 0072 void PrintTool::triggerPrint(QPrinter* printer) 0073 { 0074 const QString creator = QStringLiteral("Print Plugin for Okteta " OKTETA_VERSION); // no i18n(), keep space at end as separator 0075 printer->setCreator(creator); 0076 0077 FramesToPaperPrinter framesPrinter; 0078 const QPageLayout pageLayout = printer->pageLayout(); 0079 const int printerResolution = printer->resolution(); 0080 framesPrinter.setPaperRect(pageLayout.fullRectPixels(printerResolution)); 0081 framesPrinter.setPageRect(pageLayout.paintRectPixels(printerResolution)); 0082 printer->setFullPage(true); 0083 0084 PrintInfo info; 0085 const QRect pageRect = framesPrinter.pageRect(); 0086 const int left = pageRect.left(); 0087 const int width = pageRect.width(); 0088 0089 auto* headerFrameRenderer = new HeaderFooterFrameRenderer(&info); 0090 headerFrameRenderer->setTexts(QStringLiteral("%d"), 0091 QStringLiteral("%f"), 0092 i18nc("in the header of the printed page, e.g. Page 2 of 20", "Page %p of %P")); 0093 headerFrameRenderer->setWidth(width); 0094 headerFrameRenderer->setPos(pageRect.topLeft()); 0095 0096 auto* footerFrameRenderer = new HeaderFooterFrameRenderer(&info); 0097 footerFrameRenderer->setTexts(i18nc("in the footer of the printed page, e.g. Printed by: Joe User", 0098 "Printed by: %U"), 0099 QString(), 0100 QStringLiteral("%F")); 0101 footerFrameRenderer->setWidth(width); 0102 const int footerTop = pageRect.bottom() - footerFrameRenderer->height(); 0103 footerFrameRenderer->setPos(left, footerTop); 0104 0105 const int contentHeight = pageRect.height() - footerFrameRenderer->height() - headerFrameRenderer->height(); 0106 const int contentTop = pageRect.top() + headerFrameRenderer->height(); 0107 auto* byteArrayFrameRenderer = new ByteArrayFrameRenderer; 0108 byteArrayFrameRenderer->setPos(left, contentTop); 0109 byteArrayFrameRenderer->setWidth(width); 0110 byteArrayFrameRenderer->setHeight(contentHeight); 0111 0112 Okteta::AddressRange range = mByteArrayView->selection(); 0113 if (!range.isValid()) { 0114 range.setByWidth(0, mByteArrayModel->size()); 0115 } 0116 byteArrayFrameRenderer->setByteArrayModel(mByteArrayModel, range.start(), range.width()); 0117 0118 // TODO: use noOfBytesPerLine of view, scale resolution down if it does not fit the page 0119 const int noOfBytesPerLine = mByteArrayView->noOfBytesPerLine(); 0120 // byteArrayFrameRenderer->setNoOfBytesPerLine( mByteArrayView->noOfBytesPerLine() ); 0121 0122 const Okteta::Address startOffset = mByteArrayView->startOffset() + range.start(); 0123 const int line = startOffset / noOfBytesPerLine; 0124 const Okteta::Address firstLineOffset = mByteArrayView->firstLineOffset() + line * noOfBytesPerLine; 0125 byteArrayFrameRenderer->setFirstLineOffset(firstLineOffset); 0126 byteArrayFrameRenderer->setStartOffset(startOffset); 0127 byteArrayFrameRenderer->setOffsetCoding((Okteta::OffsetFormat::Format)mByteArrayView->offsetCoding()); 0128 0129 byteArrayFrameRenderer->setCharCoding(mByteArrayView->charCodingName()); 0130 byteArrayFrameRenderer->setBufferSpacing(mByteArrayView->byteSpacingWidth(), 0131 mByteArrayView->noOfGroupedBytes(), 0132 mByteArrayView->groupSpacingWidth()); 0133 byteArrayFrameRenderer->setBinaryGapWidth(mByteArrayView->binaryGapWidth()); 0134 0135 byteArrayFrameRenderer->setValueCoding((Okteta::ValueCoding)mByteArrayView->valueCoding()); 0136 byteArrayFrameRenderer->setShowsNonprinting(mByteArrayView->showsNonprinting()); 0137 byteArrayFrameRenderer->setSubstituteChar(mByteArrayView->substituteChar()); 0138 byteArrayFrameRenderer->setUndefinedChar(mByteArrayView->undefinedChar()); 0139 byteArrayFrameRenderer->showByteArrayColumns(mByteArrayView->visibleByteArrayCodings()); 0140 0141 // if( !confirmPrintPageNumber( byteArrayFrameRenderer->framesCount()) ) 0142 // return; 0143 0144 framesPrinter.addFrameRenderer(headerFrameRenderer); 0145 framesPrinter.addFrameRenderer(byteArrayFrameRenderer); 0146 framesPrinter.addFrameRenderer(footerFrameRenderer); 0147 0148 info.setNoOfPages(byteArrayFrameRenderer->framesCount()); 0149 AbstractModelSynchronizer* synchronizer = mDocument->synchronizer(); 0150 if (synchronizer) { 0151 info.setUrl(synchronizer->url()); 0152 } 0153 0154 QApplication::setOverrideCursor(Qt::WaitCursor); 0155 0156 auto* printJob = new PrintJob(&framesPrinter, 0, byteArrayFrameRenderer->framesCount() - 1, printer); 0157 const bool success = printJob->exec(); 0158 0159 delete printer; 0160 0161 QApplication::restoreOverrideCursor(); 0162 0163 if (!success) { 0164 const QString message = i18nc("@info", "Could not print."); 0165 0166 KMessageBox::error(QApplication::activeWindow(), message, i18nc("@title:window", "Print Byte Array %1", mDocument->title())); 0167 } 0168 } 0169 0170 } 0171 0172 #include "moc_printtool.cpp"