Skip to content

Commit

Permalink
fix: improve printing by producing a better-quality pdf instead (#764)
Browse files Browse the repository at this point in the history
  • Loading branch information
danieleds committed Sep 21, 2018
1 parent eabde2b commit 5deaf00
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 6 deletions.
42 changes: 42 additions & 0 deletions src/ui/EditorNS/editor.cpp
Expand Up @@ -779,6 +779,48 @@ namespace EditorNS
#endif
}

QPromise<QByteArray> Editor::printToPdf(const QPageLayout& pageLayout)
{
// 1. Set theme to default because dark themes would force the printer to color the entire
// document in the background color. Default theme has white background.
// 2. Set WebView's bg-color to white to prevent visual artifacts when printing less than one page.
// 3. Set C_CMD_DISPLAY_PRINT_STYLE to hide UI elements like the gutter.

return QPromise<QByteArray>(
[&](const QPromiseResolve<QByteArray>& resolve, const QPromiseReject<QByteArray>& reject) {

#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
QColor prevBackgroundColor = m_webView->page()->backgroundColor();
QString prevStylesheet = m_webView->styleSheet();

setTheme(themeFromName("default"));
m_webView->page()->setBackgroundColor(Qt::transparent);
m_webView->setStyleSheet("background-color: white");
asyncSendMessageWithResultP("C_CMD_DISPLAY_PRINT_STYLE").wait();

m_webView->page()->printToPdf(
[=](const QByteArray& data) {
QTimer::singleShot(0, [=]() {
asyncSendMessageWithResultP("C_CMD_DISPLAY_NORMAL_STYLE").wait();
m_webView->setStyleSheet(prevStylesheet);
m_webView->page()->setBackgroundColor(prevBackgroundColor);
setTheme(themeFromName(NqqSettings::getInstance().Appearance.getColorScheme()));
});

if (data.isEmpty() || data.isNull()) {
reject(QByteArray());
} else {
resolve(data);
}
},
pageLayout);

#else
reject(QByteArray());
#endif
});
}

QPromise<QString> Editor::getCurrentWord()
{
return asyncSendMessageWithResultP("C_FUN_GET_CURRENT_WORD")
Expand Down
12 changes: 12 additions & 0 deletions src/ui/include/EditorNS/editor.h
Expand Up @@ -389,7 +389,19 @@ namespace EditorNS
std::shared_future<QVariant> asyncSendMessageWithResult(const QString &msg, const QVariant &data, std::function<void(QVariant)> callback = 0);
std::shared_future<QVariant> asyncSendMessageWithResult(const QString &msg, std::function<void(QVariant)> callback = 0);

/**
* @brief Print the editor. As of Qt 5.11, it produces low-quality, non-vector graphics with big dimension.
* @param printer
*/
void print(std::shared_ptr<QPrinter> printer);

/**
* @brief Returns the content of the editor layed out in a pdf file that can be directly saved to disk.
* This method produces light, vector graphics.
* @param pageLayout
* @return
*/
QPromise<QByteArray> printToPdf(const QPageLayout &pageLayout = QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF()));
};

}
Expand Down
37 changes: 31 additions & 6 deletions src/ui/mainwindow.cpp
Expand Up @@ -29,8 +29,10 @@
#include <QLineEdit>
#include <QMessageBox>
#include <QMimeData>
#include <QPageSetupDialog>
#include <QScrollArea>
#include <QScrollBar>
#include <QTemporaryFile>
#include <QTimer>
#include <QToolBar>
#include <QToolButton>
Expand Down Expand Up @@ -2235,16 +2237,39 @@ void MainWindow::runCommand()

void MainWindow::on_actionPrint_triggered()
{
std::shared_ptr<QPrinter> printer = std::make_shared<QPrinter>(QPrinter::HighResolution);
QPrintDialog dialog(printer.get());
if (dialog.exec() == QDialog::Accepted)
currentEditor()->print(printer);
// TODO If ghostscript is available on the system, we could
// - show a QPrintDialog to the user
// - generate the pdf file
// - print the pdf via ghostscript
// https://stackoverflow.com/questions/2599925/how-to-print-pdf-on-default-network-printer-using-ghostscript-gswin32c-exe-she

QPageSetupDialog dlg;
if (dlg.exec() == QDialog::Accepted) {
currentEditor()->printToPdf(dlg.printer()->pageLayout()).then([this](QByteArray data) {
QFile file(QDir::tempPath() + "/notepadqq.print." +
QString::number(QDateTime::currentMSecsSinceEpoch(), 16) + ".pdf");

if (file.open(QIODevice::WriteOnly)) { // FIXME: Delete the file when we're done
file.write(data);
file.close();

bool ok = QDesktopServices::openUrl(QUrl::fromLocalFile(file.fileName()));
if (!ok) {
QMessageBox::warning(this,
QCoreApplication::applicationName(),
tr("%1 wasn't able to open the produced pdf file:\n%2")
.arg(QCoreApplication::applicationName(), file.fileName()),
QMessageBox::Ok,
QMessageBox::Ok);
}
}
});
}
}

void MainWindow::on_actionPrint_Now_triggered()
{
std::shared_ptr<QPrinter> printer = std::make_shared<QPrinter>(QPrinter::HighResolution);
currentEditor()->print(printer);
qWarning() << "Not implemented.";
}
/*
void MainWindow::on_actionLaunch_in_Chrome_triggered()
Expand Down

0 comments on commit 5deaf00

Please sign in to comment.