首页 > 其他分享 >044_第三代软件开发-保存PDF

044_第三代软件开发-保存PDF

时间:2023-11-14 13:35:16浏览次数:31  
标签:XXXX 软件开发 void return bool Print PDF 044 const


044_第三代软件开发-保存PDF_pdf

第三代软件开发-保存PDF


文章目录

  • 第三代软件开发-保存PDF
  • 项目介绍
  • 保存PDF
  • 头文件
  • 源文件
  • 使用



关键字:

Qt

Qml

pdf

painter

打印

项目介绍

欢迎来到我们的 QML & C++ 项目!这个项目结合了 QML(Qt Meta-Object Language)和 C++ 的强大功能,旨在开发出色的用户界面和高性能的后端逻辑。

在项目中,我们利用 QML 的声明式语法和可视化设计能力创建出现代化的用户界面。通过直观的编码和可重用的组件,我们能够迅速开发出丰富多样的界面效果和动画效果。同时,我们利用 QML 强大的集成能力,轻松将 C++ 的底层逻辑和数据模型集成到前端界面中。

在后端方面,我们使用 C++ 编写高性能的算法、数据处理和计算逻辑。C++ 是一种强大的编程语言,能够提供卓越的性能和可扩展性。我们的团队致力于优化代码,减少资源消耗,以确保我们的项目在各种平台和设备上都能够高效运行。

无论您是对 QML 和 C++ 开发感兴趣,还是需要我们为您构建复杂的用户界面和后端逻辑,我们都随时准备为您提供支持。请随时联系我们,让我们一同打造现代化、高性能的 QML & C++ 项目!

重要说明☝

☀该专栏在第三代软开发更新完将涨价

保存PDF

这个其实如果是QWidget开发,那就很简单了,直接有现成的打印模块,但是QML下是没有的,这里就需要重新写一下,首先,还是需要我们使用Qt的打印模块,

QT += printsupport

这里需要说明一下,这个文件不是原创,是在GitHub上找到另一个,完了做了修改。

头文件

#ifndef XXXX_PRINT_H
#define XXXX_PRINT_H

#include <QObject>
#ifndef QT_NO_PRINTER
#include <QPrinter>
#include <QPrintDialog>
#endif
#include <QQuickItem>
#include <QJSValue>
#include <QDir>

class XXXX_Print : public QQuickItem
{
    Q_OBJECT
//    QML_ELEMENT
    Q_DISABLE_COPY(XXXX_Print)

public:
    typedef enum { Print, PrintToFile, GrabOnly } GrabMode;
    Q_ENUMS(GrabMode);

private:
    QSharedPointer<QQuickItemGrabResult> m_result;
    // 打印的qml组件
    QQuickItem *m_item;
#ifndef QT_NO_PRINTER
    QPrintDialog    *m_printDialogue;
    QPrinter        *m_printer;
    bool            m_pagePrinted;
    bool            m_sessionOpen;
    // 指定调用“print()”将产生多少份副本
    int             m_copyCount;
    QPainter        *m_painter;

    // 启用或禁用抗锯齿
    bool    m_antialias;
    // 启用或禁用单色打印(例如,热敏打印机)
    bool    m_monochrome;
    // 选择“打印到文件”时要打印到的文件路径(在某些平台上)
    QString m_filepath;
    QRectF  m_margins;
#endif

    GrabMode    m_mode;
    QString     m_fileDest;
    QString     m_fileType;
    int         m_fileQuality;
    QJSValue    m_callback;

    Q_PROPERTY(QQuickItem* item READ getItem WRITE setItem NOTIFY itemChanged)
#ifndef QT_NO_PRINTER
    Q_PROPERTY(QString filepath READ getFilePath WRITE setFilePath NOTIFY filePathChanged)
    Q_PROPERTY(QString fileDest READ fileDest WRITE setFileDest NOTIFY fileDestChanged)
    Q_PROPERTY(bool antialias READ getAntialias WRITE setAntialias NOTIFY antialiasChanged)
    Q_PROPERTY(bool monochrome READ getMonochrome WRITE setMonochrome NOTIFY monochromeChanged)
    // 打印的 dpi  整数分辨率
    Q_PROPERTY(int resolution READ getResolution WRITE setResolution NOTIFY resolutionChanged)
    Q_PROPERTY(int copyCount READ getCopyCount WRITE setCopyCount NOTIFY copyCountChanged)
    // QRectF 对象,表示以设备像素为单位的页面尺寸
    Q_PROPERTY(QRectF pageRect READ getPageRect NOTIFY sizeChanged)
    Q_PROPERTY(QRectF paperRect READ getPaperRect NOTIFY sizeChanged)
    Q_PROPERTY(QStringList paperSizes READ getPaperSizes)
    Q_PROPERTY(QString printerName READ getPrinterName WRITE setPrinterName NOTIFY printerNameChanged)
    Q_PROPERTY(Status status READ getStatus)
#endif

public:
    XXXX_Print(QQuickItem *parent = 0);
    ~XXXX_Print();

#ifndef QT_NO_PRINTER
    typedef enum {
        Millimeter = QPageSize::Millimeter,
        Point = QPageSize::Point,
        Inch = QPageSize::Inch,
        Pica = QPageSize::Pica,
        Didot = QPageSize::Didot,
        Cicero = QPageSize::Cicero,
        DevicePixel
    } Unit;
    Q_ENUMS(Unit)

    typedef enum {
        Idle = QPrinter::Idle,
        Active = QPrinter::Active,
        Aborted = QPrinter::Aborted,
        Error = QPrinter::Error,
        Unknown
    } Status;
    Q_ENUMS(Status)
#endif


public slots:
#ifndef QT_NO_PRINTER
    bool print(QJSValue callback=QJSValue());
    bool setup(bool bDialogue = false);
    bool open();
    bool close();
    bool newPage() const;
    bool abort();
#endif

    bool grabImage(const QString &fileFormat, int quality=100, QJSValue callback=QJSValue());

    bool saveImage(const QString &fileName, const QString &fileFormat, int quality, QJSValue callback=QJSValue());

    // Property Hooks:
    void setItem( QQuickItem *item );
#ifndef QT_NO_PRINTER
    void setFilePath(const QString &filepath);
    void setFileDest(const QString &newFileDest);
    void setMonochrome(bool toggle);
    void setAntialias(bool toggle);
    void setMargins(double top, double right, double bottom, double left);
    bool setPageSize( qreal width, qreal height, Unit unit );
    bool setPageSize( const QString &paperSize );
    void setPrinterName(const QString &printerName);
    void setResolution(int dpi);
    void setCopyCount(int count);
#endif

    QQuickItem *getItem() const { return m_item; }
#ifndef QT_NO_PRINTER
    QString getFilePath() const { return m_filepath; }
    const QString fileDest() const { return m_fileDest; };
    bool getMonochrome() const { return m_monochrome; }
    bool getAntialias() const { return m_antialias; }
    QRectF getMargins() const { return m_margins; }
    QRectF getPageRect(Unit unit=DevicePixel) const;
    QRectF getPaperRect(Unit unit=DevicePixel) const;
    QStringList getPaperSizes() const;
    QString getPrinterName() const;
    int getResolution() const { return m_printer->resolution(); }
    int getCopyCount() const { return m_printer->copyCount(); }
    Status getStatus() const;
#endif

private slots:
    bool grab();
    void grabbed();

private:
    bool printGrab(const QImage &img);
    bool isDirExist(QString fullPath);



signals:
    void itemChanged();
    void frameGrabbed(const QByteArray &imageData);
    void sizeChanged();
    void printComplete();
    void printError();
#ifndef QT_NO_PRINTER
    void filePathChanged();
    void monochromeChanged();
    void antialiasChanged();
    void marginsChanged();
    void printerNameChanged();
    void resolutionChanged();
    void copyCountChanged();
#endif


    void fileDestChanged();
    void strTestChanged();
};

#endif // XXXX_PRINT_H

源文件

#include "XXXX_print.h"

#include <QBuffer>
#include <QFileInfo>
#include <QPainter>
#ifndef QT_NO_PRINTER
# include <QPrintEngine>
#endif
#include <QQuickItemGrabResult>

// Just for converting QByteArray:
#include <QQmlEngine>

void XXXX_Print::setFileDest(const QString &newFileDest)
{
    if (m_fileDest == newFileDest)
        return;
    m_fileDest = newFileDest;
    emit fileDestChanged();
}


XXXX_Print::XXXX_Print(QQuickItem *parent):
    QQuickItem(parent)
{
#ifndef QT_NO_PRINTER
    m_printDialogue = nullptr;
    m_printer = new QPrinter(QPrinter::ScreenResolution);
    m_pagePrinted = false;
    m_sessionOpen = false;
    m_copyCount = 1;
    m_painter = nullptr;
    m_antialias = true;
    m_monochrome = false;
    m_margins = QRectF(0, 0, 0, 0);
    m_filepath.clear();
#endif

    m_mode = XXXX_Print::GrabOnly;
    m_item = NULL;

    m_fileDest.clear();
    m_fileType.clear();
    m_fileQuality = 0;
}

XXXX_Print::~XXXX_Print()
{
#ifndef QT_NO_PRINTER
    delete m_printer;
#endif
}

#ifndef QT_NO_PRINTER
/**
 * @brief XXXX_Print::print  打印/保存PDF(打印 setup至true)
 * @param callback
 * @return
 */
bool XXXX_Print::print(QJSValue callback)
{
    m_mode = XXXX_Print::Print;
    m_callback = callback;
    return grab();
}
#endif

/**
 * @brief XXXX_Print::grabImage 图片以QByteArray存储
 * @param fileFormat
 * @param quality
 * @param callback
 * @return
 */
bool XXXX_Print::grabImage(const QString &fileFormat, int quality, QJSValue callback)
{
    m_mode = XXXX_Print::GrabOnly;
    m_callback = callback;
    m_fileType = fileFormat;
    m_fileQuality = quality;
    return grab();
}

/**
 * @brief XXXX_Print::saveImage   保存图片,不用打开
 * @param fileName                  图片名称
 * @param fileFormat                图片类型
 * @param quality                   图片像素-1 0-100
 * @param callback
 * @return
 */
bool XXXX_Print::saveImage(const QString &fileName, const QString &fileFormat, int quality, QJSValue callback)
{
    m_mode = XXXX_Print::PrintToFile;
    m_callback = callback;
    m_fileDest = fileName;
    m_fileType = fileFormat;
    m_fileQuality = quality;
    return grab();
}

#ifndef QT_NO_PRINTER
/**
 * @brief XXXX_Print::setup  初始化打印机(true)/存储PDF(false)
 * @param bDialogue
 * @return
 */
bool XXXX_Print::setup(bool bDialogue)
{

    m_printer->setOutputFormat(QPrinter::NativeFormat);

    QMarginsF margins( 0.0, 0.0, 0.0, 0.0);
    if( !m_printer->setPageMargins( margins, QPageLayout::Millimeter ) )
    {
        qWarning() << tr("Printer: Failed to set page margin (in mm) as configured.");
        return false;
    }
    QString strFilePath = QCoreApplication::applicationDirPath();
    m_printer->setOutputFileName(m_filepath + m_fileDest);   //设置输出路径

    if(bDialogue)
    {
        m_printDialogue = new QPrintDialog(m_printer);
        if( m_printDialogue->exec() == QDialog::Accepted )
        {
            m_printDialogue->deleteLater();
            return true;
        }
        qWarning() << "打印机初始化失败";
        delete m_printDialogue;
    }
    else
    {
        // HP LaserJet Pro M428f-M429f [453773]
        m_printer->setOutputFormat(QPrinter::PdfFormat);  //设置输出格式为pdf

        return true;
    }

    return false;
}

/**
 * @brief XXXX_Print::open 打开打印机/存储
 * @return
 */
bool XXXX_Print::open()
{
    if( m_sessionOpen )
    {

        qCritical() << tr("Printer::open called while already in a multipage session. (Call 'close' first.)");
        return false;
    }

    m_painter = new QPainter();
    if( !m_painter )
    {
        qCritical() << tr("Printer::open failed to instantiate new QPainter. (Are you out of memory?)");
        return false;
    }

    if(!m_painter->begin(m_printer))
    {
        qCritical() << tr("Failed to initialise QPainter to QPrintDevice.");
        return false;
    }

    m_painter->setRenderHint(QPainter::Antialiasing, m_antialias);
    m_painter->setRenderHint(QPainter::TextAntialiasing, m_antialias);
    m_painter->setRenderHint(QPainter::SmoothPixmapTransform, m_antialias);

    m_sessionOpen = true;
    return true;
}

/**
 * @brief XXXX_Print::close 关闭打印机/存储
 * @return
 */
bool XXXX_Print::close()
{
    if( !m_sessionOpen )
    {
        qCritical() << tr("Printer::close called while not in multipage session.");
        return false;
    }

    delete m_painter;
    m_painter = nullptr;
    m_sessionOpen = false;

    return true;
}

/**
 * @brief XXXX_Print::newPage 下一页
 * @return
 */
bool XXXX_Print::newPage() const
{
    if( !m_sessionOpen )
    {
        qCritical() << tr("Printer::newPage called while not in a multipage session. (Call Printer::open first.)");
        return false;
    }

    return m_printer->newPage();
}

/**
 * @brief XXXX_Print::abort 中止打印机
 * @return
 */
bool XXXX_Print::abort()
{
    if( m_sessionOpen )
        close();

    return m_printer->abort();
}

void XXXX_Print::setMonochrome(bool toggle)
{
    if( m_monochrome == toggle )
        return;

    m_monochrome = toggle;
    emit monochromeChanged();
}

void XXXX_Print::setAntialias(bool toggle)
{
    if( m_antialias == toggle )
        return;

    m_antialias = toggle;
    emit antialiasChanged();
}

void XXXX_Print::setFilePath(const QString &filepath)
{
    if( m_filepath == filepath )
        return;

    isDirExist(filepath);

    m_filepath = filepath;

    emit filePathChanged();
}
#endif

void XXXX_Print::setItem(QQuickItem *item)
{
     if( m_item == item )
         return;

     m_item = item;
     emit itemChanged();
}

#ifndef QT_NO_PRINTER
void XXXX_Print::setMargins(double top, double right, double bottom, double left)
{
    QRectF m( left, top, right-left, bottom-top );
    if( m_margins == m )
        return;

    m_margins = m;
    emit marginsChanged();
}

bool XXXX_Print::setPageSize( const QString &paperSize )
{
    QPageSize size;
    // Run through each..
    for( int x=0; x < QPageSize::LastPageSize; x++ )
    {
        size = QPageSize((QPageSize::PageSizeId)x);
        if( size.name() == paperSize )
        {
            bool result = m_printer->setPageSize( size );
            emit sizeChanged();
            return result;
        }
    }

    qWarning() << tr("Unknown paper size: ") << paperSize << tr(" (Refer to 'paperSizes()' for valid options.)");
    return false;
}

bool XXXX_Print::setPageSize( qreal width, qreal height, Unit unit )
{
    QSizeF szf(width, height);
    QPageSize size;

    switch( unit )
    {
    case DevicePixel:
        // Fanagle from DPI:
        szf /= m_printer->resolution();
        size = QPageSize(szf, QPageSize::Inch);
        break;
    default:
        size = QPageSize(szf, (QPageSize::Unit)unit);
        break;
    }

    bool result = m_printer->setPageSize(size);
    emit sizeChanged();
    return result;
}

void XXXX_Print::setPrinterName(const QString &printerName)
{
    if( m_printer->printerName() == printerName )
        return;

    m_printer->setPrinterName( printerName );
    emit printerNameChanged();
}

void XXXX_Print::setResolution(int dpi)
{
    if( m_printer->resolution() == dpi )
        return;

    m_printer->setResolution( dpi );
    emit resolutionChanged();
}

void XXXX_Print::setCopyCount(int count)
{
    if( m_printer->copyCount() == count )
        return;

    m_printer->setCopyCount( count );
    emit copyCountChanged();
}

QRectF XXXX_Print::getPageRect(Unit unit) const
{
    return m_printer->pageRect( (QPrinter::Unit)unit );
}

QRectF XXXX_Print::getPaperRect(Unit unit) const
{
    return m_printer->paperRect( (QPrinter::Unit)unit );
}

QStringList XXXX_Print::getPaperSizes() const
{
    QStringList results;
    QPageSize size;
    // Run through each..
    for( int x=0; x < QPageSize::LastPageSize; x++ )
    {
        size = QPageSize((QPageSize::PageSizeId)x);
        results.append( size.name() );
    }
    return results;
}

XXXX_Print::Status XXXX_Print::getStatus() const
{
    QPrinter::PrinterState state = m_printer->printEngine()->printerState();
    return (XXXX_Print::Status)state;
}
#endif

bool XXXX_Print::grab()
{
    if( !m_item )
    {
        qWarning() << tr("Printer::grab: No item source specified. (Set it with the 'item' property.)");
        return false;
    }

    QSharedPointer<QQuickItemGrabResult> res = m_item->grabToImage();
    if( !res )
    {
        qWarning() << tr("Printer::grab: Grab failed for some reason. (Is the item loaded and rendered?)");
        return false;
    }

    connect( res.data(), SIGNAL(ready()), this, SLOT(grabbed()) );
    m_result = res;

    return true;
}

#ifndef QT_NO_PRINTER
bool XXXX_Print::printGrab(const QImage &img)
{
    if( !m_sessionOpen )
    {
        qCritical() << tr("Printer: Attempt to print without first calling Printer::open(). (This behaviour changed in 1.2)");;
        return false;
    }
    if( m_monochrome )
        m_painter->drawImage( m_printer->paperRect(QPrinter::DevicePixel), img.convertToFormat(QImage::Format_Mono, Qt::MonoOnly | Qt::ThresholdDither) );
    else
        m_painter->drawImage( m_printer->paperRect(QPrinter::DevicePixel), img );

    return true;
}

/**
 * @brief XXXX_Print::isDirExist 判断文件夹是否存在,不存在则创建
 * @param fullPath
 * @return
 */
bool XXXX_Print::isDirExist(QString fullPath)
{
//    QString strFilePath = QCoreApplication::applicationDirPath();

    QDir dir(fullPath);
    if(dir.exists())
    {
      return true;
    }
    else
    {
        return dir.mkdir(fullPath);
    }
}
#endif

void XXXX_Print::grabbed()
{
    const QImage img = m_result.data()->image();
    m_result.clear();

    QQmlEngine *jse = qmlEngine(this);
    jse->collectGarbage();

    bool ret = true;

    if( m_mode == XXXX_Print::PrintToFile )
    {
        ret = img.save(m_fileDest, m_fileType.toStdString().c_str(), m_fileQuality);
        if( m_callback.isCallable() )
        {
            QJSValueList args;
            args << ret;
            m_callback.call(args);
        }
    }
#ifndef QT_NO_PRINTER
    else if( m_mode == XXXX_Print::Print )
    {
        ret = printGrab(img);
        if( m_callback.isCallable() )
        {
            QJSValueList args;
            args << ret;
            m_callback.call(args);
        }
    }
#endif
    else if( m_callback.isCallable() )
    {
        QImage image;
        QByteArray ba;
        QBuffer buffer(&ba);
        buffer.open(QIODevice::WriteOnly);
        // 此函数将 QImage 写入给定设备
        ret = img.save(&buffer, m_fileType.toStdString().c_str(), m_fileQuality);
        buffer.close();

        if( ret )
        {
            QJSValueList args;
            args << jse->toScriptValue<QByteArray>(ba);
            m_callback.call( args );
        }
    }

//    m_callback = QJSValue();

    if( ret )
        emit printComplete();
    else
        emit printError();
}

#ifndef QT_NO_PRINTER
QString XXXX_Print::getPrinterName() const
{
    return m_printer->printerName();
}
#endif

使用

XXX_Print {
        id: printPDF

        filepath: pdfFilePath
        fileDest: "/" + UserProfile.userName + dateString +".pdf"
        antialias: false
        monochrome: false

        onPrintComplete: console.log("Print complete.");
        onPrintError: console.log("Print error!");
        Component.onCompleted: scanPaperSizes();

        function scanPaperSizes()
        {
            printPDF.setPageSize( 'A4' );
            printPDF.setMargins(0,0,0,0)
        }

    }

044_第三代软件开发-保存PDF_QPainter_02


标签:XXXX,软件开发,void,return,bool,Print,PDF,044,const
From: https://blog.51cto.com/DreamLife/8366089

相关文章

  • 047_第三代软件开发-日志分离
    第三代软件开发-日志分离文章目录第三代软件开发-日志分离项目介绍日志分离用法关键字:Qt、Qml、log、日志、分离项目介绍欢迎来到我们的QML&C++项目!这个项目结合了QML(QtMeta-ObjectLanguage)和C++的强大功能,旨在开发出色的用户界面和高性能的后端逻辑。在项目中,我......
  • 直播app软件开发的步骤和代码!
    随着互联网的发展,直播App已经成为人们日常生活的一部分,它为观众提供了实时观看、互动交流和参与体验的机会,同时也为开发者带来了可观的商业价值,本文将详细介绍直播App的开发步骤和相关代码。一、需求分析在开发直播App之前,需要进行详细的需求分析,这包括对目标用户、竞争对手和市场......
  • Python 如何实现合并 PDF 文件?
    在处理多个PDF文档时,频繁地打开关闭文件会严重影响效率。因此,对于一大堆内容相关的PDF文件,我们可以先将这些PDF文件合并起来再操作,从而提高工作效率。比如,在传送大量的PDF文档时,在处理同一项目下的多个PDF文档时,或在打印一系列PDF文档时,将文档合并起来可以减少工作量......
  • Excel word pdf查找
    importorg.apache.commons.lang.StringUtils;importorg.apache.pdfbox.pdmodel.PDDocument;importorg.apache.pdfbox.text.PDFTextStripper;importorg.apache.poi.ooxml.POIXMLDocument;importorg.apache.poi.openxml4j.opc.OPCPackage;importorg.apache.poi.xssf.......
  • 开源网安受邀参加网络空间安全合作与发展论坛,为软件开发安全建设献计献策
    11月10日,在广西南宁举办的“2023网络空间安全合作与发展论坛”圆满结束。论坛在中国兵工学会的指导下,以“凝聚网络空间安全学术智慧,赋能数字经济时代四链融合”为主题,邀请了多位专家及企业代表共探讨网络安全发展与数字经济建设。开源网安常务副总王颉博士受邀参加本届论坛并分享了......
  • 软件开发项目文档系列之十四如何撰写系统试运行报告
    试运行报告是一个关键的质量控制工具,可用于验证新系统、流程或设备的可行性和性能。通过记录试运行的过程、结果和问题,可以帮助组织更好地了解项目的进展情况,识别潜在的风险和问题,并及时采取纠正措施。试运行报告还可以作为一个重要的参考文档,供未来的决策、培训和改进使用。因此,......
  • 212-c# url下载pdf,url请求,有参数,且携带cookies
    usingSystem;usingSystem.Net;usingSystem.Net.Http;usingSystem.Net.Http.Headers;usingSystem.Threading.Tasks;classProgram{staticvoidMain(){//设置要下载的PDF文件的URLstringpdfUrl="https://example.com/path/to/your/pdf......
  • 教育培训app软件开发功能-多端开发
      近些年,随着网上直播课的流行,传统教育方式也在寻求改变,用户逐渐从线下转移到线上听课,通过线上平台他们可以进行实时互动、集思广益,为了带给用户更好的体验,教育培训类app便应运而生了,交互性的界面、丰富的课程内容以及及时的反馈和评价,用新颖的方式满足了用户对知识的需求,那么......
  • 历时三年,写的一本数据结构与算法pdf,开源了!
    前言大家好,我是bigsai,很早就在写博客,将文章整理成了一个pdf,并且开源到github上!自己写东西断断续续也不少时间了,也写了不少东西(虽然是偏向小白),这个其实花费的时间还是比较多的,这次的话主要将数据结构与算法中一些文章整理出来,初步整理成一版pdf,先分享给大家。因为在整理pdf方......
  • 把pdf放到公众号的教程
    微信公众号作为与读者互动的重要平台,有时需要分享PDF格式的文件,例如电子书、报告、教程等。传统方式可能需要读者额外操作来下载查看,而使用“微附件”可以简化这一过程。本教程将引导您如何通过“微附件”官网生成PDF文件的路径,并将其嵌入公众号文章中。1.准备PDF文件确保您拥有的......