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"