htmlc++pdfqt6

Create an HTML page in Qt and save the page as a PDF file


I'm trying to create an HTML file using Qt C++, and then save it to a PDF file. So far I have succeeded creating an HTML file, but when I try to save it to a PDF file, I get a warning about D3D11 Live Object in my console, and the PDF file won't be created.

I also noticed that it works in release mode, but not debug mode. Why is that?

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QWebEngineView>
#include <QFile>
#include <QTextStream>
#include <QMessageBox>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void generatePdf();

private slots:
    void onLoadFinished(bool);

private:
    Ui::MainWindow *ui;
    QWebEngineView *view;
    void createHtmlFile();
};

#endif // MAINWINDOW_H

MainWindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QWebEngineSettings>
#include <QCoreApplication>
#include <QDir>
#include <QDebug>
#include <QMessageBox>
#include <QFileDialog>
#include <QStandardPaths>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    createHtmlFile(); // Create the HTML file

    view = new QWebEngineView(this);
    connect(view, &QWebEngineView::loadFinished, this, &MainWindow::onLoadFinished);

    QString htmlFilePath = QCoreApplication::applicationDirPath() + "/index.html"; //Returns the directory that contains the application executable
    qDebug() << "Loading HTML file from: " << htmlFilePath;
    view->setUrl(QUrl::fromLocalFile(htmlFilePath));
    setCentralWidget(view);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::createHtmlFile()
{
    QString htmlFilePath = QCoreApplication::applicationDirPath() + "/index.html"; //Returns the directory that contains the application executable
    QFile file(htmlFilePath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        qDebug() << "Failed to open file for writing: " << file.errorString();
        QMessageBox::warning(this, "File Error", "Failed to create HTML file: " + file.errorString());
        return;
    }

    QTextStream out(&file);
    out << "<!DOCTYPE html>\n";
    out << "<html lang=\"en\">\n";
    out << "<head>\n";
    out << "<meta charset=\"UTF-8\">\n";
    out << "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n";
    out << "<title>QWebEngine Example</title>\n";
    out << "</head>\n";
    out << "<body>\n";
    out << "<h1>Hello from QWebEngine!</h1>\n";
    out << "<p>This is a simple HTML page loaded using Qt's QWebEngine.</p>\n";
    out << "</body>\n";
    out << "</html>\n";
    file.close();
    qDebug() << "HTML file created successfully at: " << htmlFilePath;
}

void MainWindow::onLoadFinished(bool ok)
{
    if (ok)
    {
        qDebug() << "HTML file loaded successfully.";
        generatePdf(); // Generate the PDF once the HTML is loaded
    }
    else
    {
        qDebug() << "Failed to load HTML file.";
        QMessageBox::warning(this, "Load Error", "Failed to load the HTML file.");
    }
}


void MainWindow::generatePdf() //Does not work
{
    QString pdfFilePath = QFileDialog::getSaveFileName(this, tr("Save PDF"),
                                    QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation),
                                    tr("PDF Files (*.pdf)"));
    if (pdfFilePath.isEmpty())
        return;

    view->page()->printToPdf(pdfFilePath);
}

main.cpp

#include "MainWindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

The PDF file will NOT be created. Here's what my console looks like after I run my program:

> HTML file created successfully at: 
> "C:/Users/someUser/Documents/build-HTMLtoPDF-Desktop_Qt_6_6_1_MSVC2019_64bit-Debug/debug/index.html"
> Loading HTML file from: 
> "C:/Users/someUser/Documents/build-HTMLtoPDF-Desktop_Qt_6_6_1_MSVC2019_64bit-Debug/debug/index.html"
> doh set to ""  --  SystemOnly HTML file loaded successfully. D3D11
> WARNING: ID3D11Device::CreateInputLayout: The provided input signature
> expects to read an element with SemanticName/Index: 'TEXCOORD'/2 and
> component(s) of the type 'int32'.  However, the matching entry in the
> Input Layout declaration, element[2], specifies mismatched format:
> 'R16G16_UINT'.  This is not an error, since behavior is well defined:
> The element format determines what data conversion algorithm gets
> applied before it shows up in a shader register. Independently, the
> shader input signature defines how the shader will interpret the data
> that has been placed in its input registers, with no change in the
> bits stored.  It is valid for the application to reinterpret data as a
> different type once it is in the vertex shader, so this warning is
> issued just in case reinterpretation was not intended by the author. [
> STATE_CREATION WARNING #391: CREATEINPUTLAYOUT_TYPE_MISMATCH] Received
> fatal exception EXCEPTION_BREAKPOINT Backtrace:
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB74F19CE8+276867377]    invalid_parameter
> [0x00007FFBBB30AF0F+207]  QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB7B758B88+386176977]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB7B7584FD+386175302]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB7B75855D+386175398]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB7B758431+386175098]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB7B75874A+386175891]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB7B74A113+386116956]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB80E226B7+477180672]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB80E22A6B+477181620]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB80E28B1C+477206373]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB80E14C7B+477124804]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB80E1561C+477127269]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB80E169B0+477132281]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB80E2FAE6+477234991]
>   QWebEnginePage::setUrlRequestInterceptor [0x00007FFB64F6E615+8778334]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB80E2067E+477172423]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB80E2232C+477179765]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB80E2942B+477208692]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB80E2CAB2+477222651]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB74B63F9F+272976872]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB80E1CEF5+477158206]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB7677ACDA+302430499]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB76778993+302421468]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB767BB198+302693857]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB7677A0A8+302427377]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB77252F2F+313801592]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB77246F0B+313752404]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB77247625+313754222]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB77247A60+313755305]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB77258336+313823103]
>   QWebEnginePage::setUrlRequestInterceptor [0x00007FFB64F6E615+8778334]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB74D1D637+274784896]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB74EC31F7+276512320]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB74ED6B35+276592510]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB74ED5A3F+276588168]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB74C64226+274026095]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB74EE1438+276635777]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB74E714AD+276177142]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB7BABB1FD+389725766]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB7328538C+246898645]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB73283F90+246893529]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB7327D0D1+246865178]
>   QWebEnginePage::setUrlRequestInterceptor
> [0x00007FFB73277D3D+246843782]
>   QWebEnginePage::setUrlRequestInterceptor [0x00007FFB64FEF25E+9305767]
>   TargetGetStockObject [0x00007FF6E9FA49A3+287028]
>   TargetGetStockObject [0x00007FF6EA726CE7+8160376]
>   TargetGetStockObject [0x00007FF6EA726AEE+8159871]
>   TargetGetStockObject [0x00007FF6EA71E492+8125475]
>   TargetGetStockObject [0x00007FF6EA71E33E+8125135]
>   TargetGetStockObject [0x00007FF6EA71E1FE+8124815]
>   TargetGetStockObject [0x00007FF6EA71E52E+8125631]
>   BaseThreadInitThunk [0x00007FFC305A7344+20]     RtlUserThreadStart
> [0x00007FFC31B226B1+33]
> [25992:22332:0514/155233.091:INFO:web_contents_delegate_qt.cpp(279)]
> ProcessGone: 3 (-2147483645)
> [25992:22332:0514/155233.091:INFO:web_contents_delegate_qt.cpp(279)]
> ProcessGone: 3 (-2147483645)

How do I solve this?


Solution

  • This is a bug with Qt versions < 6.7.0, because in testing with Qt 6.7.1, the PDF file generates fine.

    See:

    Fixed in Qt 6.7.0 as mentioned in its release notes.

    It's possible to use this minimal example to test different versions:

    #include <QApplication>
    #include <QWebEngineView>
    #include <QFile>
    #include <QTextStream>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        QString path = QCoreApplication::applicationDirPath();
        QFile file(path+"/example.html");
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
        {
            qDebug() << "Failed to open file for writing: " << file.errorString();
            return -1;
        }
    
        QTextStream out(&file);
        out << "<!DOCTYPE html> <html> <body> <h1>Example HTML FILE</h1> </body> </html>";
        file.close();
    
        QWebEngineView view;
        QObject::connect(&view, &QWebEngineView::loadFinished, [&view, &path](bool ok)
        {
            if (ok)
            {
                qDebug() << "HTML file loaded successfully.";
                view.page()->printToPdf(path+"/examplePDF.pdf");
            }
            else
            {
                qDebug() << "Failed to load HTML file.";
            }
        });
    
        view.setUrl(QUrl::fromLocalFile(path+"/example.html"));
        view.show();
    
        return a.exec();
    }