File indexing completed on 2024-04-28 05:08:25
0001 /*************************************************************************** 0002 Copyright (C) 2020 Robby Stephenson <robby@periapsis.org> 0003 ***************************************************************************/ 0004 0005 /*************************************************************************** 0006 * * 0007 * This program is free software; you can redistribute it and/or * 0008 * modify it under the terms of the GNU General Public License as * 0009 * published by the Free Software Foundation; either version 2 of * 0010 * the License or (at your option) version 3 or any later version * 0011 * accepted by the membership of KDE e.V. (or its successor approved * 0012 * by the membership of KDE e.V.), which shall act as a proxy * 0013 * defined in Section 14 of version 3 of the license. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, * 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0018 * GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0022 * * 0023 ***************************************************************************/ 0024 0025 #include "printhandler.h" 0026 #include "document.h" 0027 #include "controller.h" 0028 #include "translators/htmlexporter.h" 0029 #include "utils/cursorsaver.h" 0030 #include "config/tellico_config.h" 0031 #include "../tellico_debug.h" 0032 0033 #ifdef USE_KHTML 0034 #include <KHTMLPart> 0035 #include <KHTMLView> 0036 #include <KAboutData> 0037 #else 0038 #include <QWebEngineView> 0039 #include <QWebEnginePage> 0040 #include <QWebEngineSettings> 0041 #include <QPrinter> 0042 #include <QPrinterInfo> 0043 #include <QPrintDialog> 0044 #include <QPrintPreviewDialog> 0045 #include <QPrintPreviewWidget> 0046 #include <QEventLoop> 0047 #endif 0048 0049 using Tellico::PrintHandler; 0050 0051 #ifndef USE_KHTML 0052 class WebPagePrintable : public QWebEnginePage { 0053 Q_OBJECT 0054 0055 public: 0056 WebPagePrintable(QObject* parent) : QWebEnginePage(parent) { 0057 QWebEngineSettings* settings = this->settings(); 0058 settings->setAttribute(QWebEngineSettings::JavascriptEnabled, false); 0059 settings->setAttribute(QWebEngineSettings::PluginsEnabled, false); 0060 settings->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true); 0061 settings->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls, true); 0062 } 0063 0064 public Q_SLOTS: 0065 void printDocument(QPrinter* printer) { 0066 Tellico::GUI::CursorSaver cs(Qt::WaitCursor); 0067 QEventLoop loop; 0068 print(printer, [&](bool) { loop.quit(); }); 0069 loop.exec(); 0070 } 0071 }; 0072 #endif 0073 0074 PrintHandler::PrintHandler(QObject* parent_) : QObject(parent_) 0075 , m_inPrintPreview(false) { 0076 } 0077 0078 PrintHandler::~PrintHandler() { 0079 } 0080 0081 void PrintHandler::setEntries(const Tellico::Data::EntryList& entries_) { 0082 m_entries = entries_; 0083 m_html.clear(); 0084 } 0085 0086 void PrintHandler::setColumns(const QStringList& columns_) { 0087 m_columns = columns_; 0088 m_html.clear(); 0089 } 0090 0091 void PrintHandler::print() { 0092 GUI::CursorSaver cs(Qt::WaitCursor); 0093 0094 if(m_html.isEmpty()) { 0095 m_html = generateHtml(); 0096 if(m_html.isEmpty()) { 0097 myDebug() << "PrintHandler - empty html output"; 0098 return; 0099 } 0100 } 0101 0102 #ifdef USE_KHTML 0103 KHTMLPart w; 0104 0105 // KHTMLPart printing was broken in KDE until KHTML 5.16 0106 // see https://git.reviewboard.kde.org/r/125681/ 0107 const QString version = w.componentData().version(); 0108 const uint major = version.section(QLatin1Char('.'), 0, 0).toUInt(); 0109 const uint minor = version.section(QLatin1Char('.'), 1, 1).toUInt(); 0110 if(major == 5 && minor < 16) { 0111 myWarning() << "Printing is broken for KDE Frameworks < 5.16. Please upgrade"; 0112 return; 0113 } 0114 0115 w.setJScriptEnabled(false); 0116 w.setJavaEnabled(false); 0117 w.setMetaRefreshEnabled(false); 0118 w.setPluginsEnabled(false); 0119 w.begin(Data::Document::self()->URL()); 0120 w.write(m_html); 0121 w.end(); 0122 w.view()->print(); 0123 #else 0124 QScopedPointer<QWebEngineView> view(new QWebEngineView); 0125 WebPagePrintable* page = new WebPagePrintable(view.data()); 0126 view->setPage(page); 0127 view->setHtml(m_html, Data::Document::self()->URL()); 0128 0129 // don't have busy cursor when showing the print dialog 0130 cs.restore(); 0131 0132 auto info = QPrinterInfo::defaultPrinter(); 0133 QScopedPointer<QPrinter> printer; 0134 if(info.isNull()) { 0135 printer.reset(new QPrinter); 0136 } else { 0137 printer.reset(new QPrinter(info)); 0138 } 0139 printer->setResolution(300); 0140 QPointer<QPrintDialog> dialog = new QPrintDialog(printer.data(), view.data()); 0141 if(dialog->exec() != QDialog::Accepted) { 0142 return; 0143 } 0144 page->printDocument(printer.data()); 0145 #endif 0146 } 0147 0148 void PrintHandler::printPreview() { 0149 // print preview only works with WebEngine 0150 #ifndef USE_KHTML 0151 if(m_inPrintPreview) { 0152 return; 0153 } 0154 GUI::CursorSaver cs(Qt::WaitCursor); 0155 0156 if(m_html.isEmpty()) { 0157 m_html = generateHtml(); 0158 if(m_html.isEmpty()) { 0159 myDebug() << "PrintHandler - empty html output in preview"; 0160 return; 0161 } 0162 } 0163 0164 QScopedPointer<QWebEngineView> view(new QWebEngineView); 0165 WebPagePrintable* page = new WebPagePrintable(view.data()); 0166 view->setPage(page); 0167 view->setHtml(m_html, Data::Document::self()->URL()); 0168 0169 // don't have busy cursor when showing the print dialog 0170 cs.restore(); 0171 0172 m_inPrintPreview = true; 0173 auto info = QPrinterInfo::defaultPrinter(); 0174 QScopedPointer<QPrinter> printer; 0175 if(info.isNull()) { 0176 printer.reset(new QPrinter); 0177 } else { 0178 printer.reset(new QPrinter(info)); 0179 } 0180 printer->setResolution(300); 0181 QPrintPreviewDialog preview(printer.data(), view.data()); 0182 connect(&preview, &QPrintPreviewDialog::paintRequested, 0183 page, &WebPagePrintable::printDocument); 0184 { 0185 // this is a workaround for ensuring the initial dailog open shows the preview already 0186 // with Qt 5.15.2, it didn't seem to get previewed initially 0187 QList<QPrintPreviewWidget*> list = preview.findChildren<QPrintPreviewWidget*>(); 0188 QPrintPreviewWidget* w = list.first(); 0189 if(w) w->updatePreview(); 0190 } 0191 preview.exec(); 0192 m_inPrintPreview = false; 0193 #endif 0194 } 0195 0196 QString PrintHandler::generateHtml() const { 0197 Export::HTMLExporter exporter(Data::Document::self()->collection()); 0198 // only print visible entries 0199 exporter.setEntries(m_entries); 0200 exporter.setXSLTFile(QStringLiteral("tellico-printing.xsl")); 0201 exporter.setPrintHeaders(Config::printFieldHeaders()); 0202 exporter.setPrintGrouped(Config::printGrouped()); 0203 exporter.setGroupBy(Controller::self()->expandedGroupBy()); 0204 if(!Config::printGrouped()) { // the sort titles are only used if the entries are not grouped 0205 exporter.setSortTitles(Controller::self()->sortTitles()); 0206 } 0207 exporter.setColumns(m_columns); 0208 exporter.setMaxImageSize(Config::maxImageWidth(), Config::maxImageHeight()); 0209 if(Config::printFormatted()) { 0210 exporter.setOptions(Export::ExportUTF8 | Export::ExportFormatted); 0211 } else { 0212 exporter.setOptions(Export::ExportUTF8); 0213 } 0214 0215 return exporter.text(); 0216 } 0217 0218 #ifndef USE_KHTML 0219 #include "printhandler.moc" 0220 #endif