Skip to content

feat(batch-print): add headless batch print for pdf/docx/djvu/xps - #385

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
pengfeixx:feat/batch-print
Sep 15, 2026
Merged

deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
pengfeixx:feat/batch-print

Conversation

@pengfeixx

@pengfeixx pengfeixx commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

feat: add headless batch print for pdf/docx/djvu/xps

Summary

新增 deepin-reader-batchprint 独立进程,支持在文件管理器中多选 pdf/docx/djvu/xps 文档后通过右键菜单"批量打印"静默完成打印,全程无对话框交互。

Key changes

  • batch-print 模块:格式归一化(pdf 直通、docx 经 pandoc、djvu 300dpi 渲染、xps 导出)+ CUPS 运行时 dlopen 提交 + DBus 通知
  • PrintSettings 结构体:预留 DTK 打印设置接口,当前仅 copies/sides/ColorModel 安全子集映射为 CUPS 选项
  • 构建系统:CMakeLists.txt 集成 batch-print 子目录;linglong.yaml build 段切换为 CMake 构建;translation-generate.cmake 修复 lrelease 路径查找
  • 单元测试:printsettings/cupsclient/formatconverter/notifyclient 四个测试模块
  • 上下文菜单:新增 deepin-reader-batchprint.conf 注册右键菜单项

Test scenarios

  • 玲珑构建 ll-builder build 成功,batch-print 正确编出并打包
  • DOCX/PDF/DJVU/XPS 批量打印均正常提交到打印机
  • 退出码:0=全部成功、1=存在失败、2=环境错误

Related: V-4012

Summary by Sourcery

Add silent batch printing for PDF, DOCX, DJVU, and XPS documents through a standalone file-manager-integrated workflow.

New Features:

  • Add a standalone headless batch-print executable for silently printing selected PDF, DOCX, DJVU, and XPS files from the file manager.
  • Register a localized file-manager context-menu action for batch printing supported document formats.
  • Provide CUPS submission and DBus result/error notifications with success, partial-failure, and environment-error handling.

Bug Fixes:

  • Improve DJVU page resolution handling and installation-path lookup for multiarch library layouts.
  • Make translation generation locate Qt lrelease across supported installation paths.

Enhancements:

  • Introduce reusable print settings with safe mapping for copies, duplex mode, and color model.
  • Add format conversion support that normalizes supported documents to PDF before printing.

Build:

  • Integrate the batch-print targets and context-menu installation into CMake, and migrate the Linglong build workflow to CMake.

Deployment:

  • Package the batch-print executable and required multiarch/runtime dependencies in the Linglong build.

Tests:

  • Add standalone unit-test coverage for print settings, CUPS integration, format conversion, notification formatting, and related regression cases.

@sourcery-ai

sourcery-ai Bot commented Sep 15, 2026

Copy link
Copy Markdown

Reviewer's Guide

This PR introduces a separately packaged, headless batch-print process invoked from the file manager, reusing reader conversion code to normalize PDF/DOCX/DjVu/XPS documents, dynamically interfacing with CUPS for silent submission, and notifying users over DBus; it also adds CMake/Linglong integration, context-menu registration, runtime install-path handling, and focused unit tests.

Sequence diagram for headless batch document printing

sequenceDiagram
    actor User
    participant FileManager
    participant BatchPrint as deepin-reader-batchprint
    participant Converter as FormatConverter
    participant CUPS as CupsClient
    participant Notifications as DBusNotifications

    User->>FileManager: Select documents and choose Batch Print
    FileManager->>BatchPrint: run(files)
    BatchPrint->>CUPS: init()
    BatchPrint->>CUPS: checkEnvironment()
    CUPS-->>BatchPrint: Default printer
    loop Each selected file
        BatchPrint->>Converter: convertToPdf(filePath, tempDir)
        Converter-->>BatchPrint: outputPdfPath
        BatchPrint->>CUPS: submitJob(outputPdfPath, jobTitle, settings)
        CUPS-->>BatchPrint: Print result
    end
    BatchPrint->>Notifications: notifyResult(total, succeeded, failedFiles)
    BatchPrint-->>FileManager: Exit code 0 or 1
Loading

Flow diagram for document format normalization

flowchart LR
    Input["PDF / DOCX / DjVu / XPS"] --> Detect["detectFileTypeWithFallback"]
    Detect --> PDF["PDF: direct path"]
    Detect --> DOCX["DOCX: DocumentFactory conversion"]
    Detect --> DJVU["DjVu: render pages at 300 DPI"]
    Detect --> XPS["XPS: Document::saveAs"]
    PDF --> Output["PDF submitted to CUPS"]
    DOCX --> Output
    DJVU --> Output
    XPS --> Output
Loading

File-Level Changes

Change Details Files
Added a standalone headless batch-print executable that validates the print environment, converts supported documents to PDF, submits each job, reports aggregate results, and returns status-based exit codes.
  • Added command-line processing and per-file temporary conversion/print workflow.
  • Added CUPS runtime loading, default-printer discovery, color capability detection, and job submission.
  • Added DBus desktop notifications with fallback stderr reporting for environment and per-file outcomes.
batch-print/main.cpp
batch-print/batchprintapp.cpp
batch-print/batchprintapp.h
batch-print/cupsclient.cpp
batch-print/cupsclient.h
batch-print/icupsapi.h
batch-print/notifyclient.cpp
batch-print/notifyclient.h
batch-print/errormessages.cpp
batch-print/errormessages.h
Implemented format normalization for PDF, DOCX, DjVu, and XPS inputs while reusing selected reader/document components.
  • Passed PDFs through unchanged.
  • Converted DOCX through the existing document/pandoc path.
  • Rendered DjVu pages at 300 DPI with source-derived page geometry.
  • Exported XPS documents to PDF when XPS support is enabled.
batch-print/formatconverter.cpp
batch-print/formatconverter.h
reader/document/Model.cpp
reader/document/Model.h
reader/document/DjVuModel.cpp
reader/document/DjVuModel.h
reader/document/DjVuModel.cpp
Added a print-settings abstraction with a safe initial CUPS option mapping.
  • Defined extensible settings for copies, duplex, color, orientation, paper, watermark, range, scaling, and layout.
  • Mapped copies, sides, and ColorModel to CUPS options with bounds and printer color capability handling.
batch-print/printsettings.h
batch-print/printsettings.cpp
Integrated batch printing into the CMake and Linglong packaging flows and registered the file-manager context-menu action.
  • Added batch-print libraries, executable, optional tests, dependencies, and installation rules.
  • Switched the Linglong build script to CMake and updated multiarch library/dependency packaging paths.
  • Registered Batch Print for supported document MIME types and single/multiple file selections.
  • Improved lrelease discovery and propagated the install library directory to runtime path resolution.
CMakeLists.txt
batch-print/CMakeLists.txt
linglong.yaml
cmake/translation-generate.cmake
reader/CMakeLists.txt
reader/document/Model.cpp
src/context-menus/deepin-reader-batchprint.conf
Added unit-test coverage for settings mapping, CUPS interfaces, conversion geometry/basic paths, and notification formatting.
  • Covered CUPS mock behavior and option generation.
  • Covered unsupported/missing files, PDF passthrough, and DjVu geometry calculations.
  • Covered success, failure, truncation, and environment-notification message paths.
batch-print/tests/CMakeLists.txt
batch-print/tests/ut_printsettings.cpp
batch-print/tests/ut_cupsclient.cpp
batch-print/tests/ut_formatconverter.cpp
batch-print/tests/ut_notifyclient.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 2 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="CMakeLists.txt" line_range="264-271" />
<code_context>

 if (USE_PDFIUM_BUNDLE)
     add_subdirectory(3rdparty/deepin-pdfium)
+    add_subdirectory(batch-print)
+
+    # Install context-menus (batch print)
+    install(FILES src/context-menus/deepin-reader-batchprint.conf
+            DESTINATION ${CMAKE_INSTALL_DATADIR}/applications/context-menus)
 endif()

 # 单元测试(可选)
</code_context>
<issue_to_address>
**issue (broader_impact):** The batch-print target is only added when `USE_PDFIUM_BUNDLE` is enabled, even though its own CMake file contains a system-PDFium linking branch. Builds selecting the supported system PDFium configuration therefore omit `deepin-reader-batchprint` and its context-menu registration entirely.

**Triggers:** When the project is built with `-DUSE_PDFIUM_BUNDLE=OFF`.

**Suggested fix:** Move `add_subdirectory(batch-print)` and the context-menu installation outside the `if (USE_PDFIUM_BUNDLE)` block.

```suggestion
if (USE_PDFIUM_BUNDLE)
    add_subdirectory(3rdparty/deepin-pdfium)
endif()

add_subdirectory(batch-print)

# Install context-menus (batch print)
install(FILES src/context-menus/deepin-reader-batchprint.conf
        DESTINATION ${CMAKE_INSTALL_DATADIR}/applications/context-menus)
```
</issue_to_address>

### Comment 2
<location path="batch-print/batchprintapp.cpp" line_range="77" />
<code_context>
+        if (cups) {
+            printOk = cups->submitJob(outputPdfPath, jobTitle, m_settings);
+        } else {
+            printOk = m_cupsApi->printFile(QString(), outputPdfPath, jobTitle, 0, nullptr);
+        }
+
</code_context>
<issue_to_address>
**issue (bug_risk):** The injected `ICupsApi` path submits the converted file with an empty printer name and bypasses `PrintSettings`, while the concrete `CupsClient` path selects the default printer and applies the settings. Any non-`CupsClient` implementation therefore receives different arguments and cannot faithfully emulate or implement batch printing.

**Triggers:** When `BatchPrintApp` is constructed with an `ICupsApi` implementation, including mocks or alternate CUPS backends.

**Suggested fix:** Expose printer selection/settings through `ICupsApi`, or require the injected implementation to provide an equivalent submit-job operation rather than calling `printFile` with an empty printer and zero options.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread CMakeLists.txt
Comment thread batch-print/batchprintapp.cpp Outdated
@pengfeixx
pengfeixx force-pushed the feat/batch-print branch 4 times, most recently from 7171d0c to 8e0e04f Compare September 15, 2026 05:53
Add deepin-reader-batchprint standalone process for multi-file batch
printing from file manager context menu without any dialog interaction.

新增无界面批量打印能力:文件管理器多选文档后右键"批量打印"
拉起独立进程静默完成打印,支持 pdf/docx/djvu/xps 格式。

Bundle libqt6waylandclient6 matching the apt Qt 6.8.0 set and resolve
indirect deps via rpath-link, fixing linglong link failure caused by
mixing runtime's libQt6WaylandClient private ABI.

修复玲珑构建链接失败:打包与本体 Qt 版本一致的 libQt6WaylandClient,
并通过 rpath-link 优先解析应用自带的间接依赖,避免混用运行时 Qt。

Log: 新增deepin-reader批量打印功能并修复玲珑构建
Influence: 用户可在文件管理器中多选文档批量打印,无需逐个操作。
@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 78 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 总体评分 78 分,大于 70 分通过阈值,代码质量基本符合要求,但存在部分需改进的问题。

🔍 详细分析

1. 语法逻辑 ❌

评价: 一般 ❌ 不通过

潜在问题:

  1. batch-print/formatconverter.cpp:727 - QProcess资源泄漏:DOCX转换路径中getDocument可能分配QProcess对象,但代码仅在doc非空时delete doc,未清理proc指针

建议: 在DOCX转换路径中添加QProcess的清理逻辑,使用QScopedPointer或智能指针管理QProcess生命周期


2. 代码质量 ❌

评价: 良好 ❌ 不通过

潜在问题:

  1. batch-print/notifyclient.cpp:39 - notifyResult和notifyError存在重复的DBus通知代码(创建QDBusInterface、构建args、调用Notify),应提取公共方法
  2. batch-print/formatconverter.cpp:689 - computePageSizeMm静态方法已定义,但DJVU转换循环中重复内联计算px到pt到mm,未复用此方法

建议: 提取DBus通知公共方法消除重复代码;在DJVU转换中复用computePageSizeMm方法


3. 代码性能 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: 性能良好,资源使用合理


4. 代码安全 🔒

评价: 优秀 ✅ 通过

🔐 存在 0 个安全漏洞

📊 漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个

安全漏洞详情:
✅ 未发现安全漏洞

建议: 安全合规


💡 改进建议代码示例

// 修复QProcess资源泄漏(formatconverter.cpp DOCX转换路径)
QProcess *proc = nullptr;
Document *doc = DocumentFactory::getDocument(Dr::DOCX, filePath, convertedDir,
                                             QString(), &proc, error);
if (doc) {
    delete doc;
    if (proc) {
        proc->waitForFinished(30000);
        delete proc;
    }
    outputPdfPath = convertedDir + QStringLiteral("/temp.pdf");
    if (!QFileInfo::exists(outputPdfPath)) {
        errorMsg = ErrorMessages::convertFailed(fi.fileName());
        return false;
    }
    return true;
}
if (proc) {
    proc->waitForFinished(30000);
    delete proc;
}
errorMsg = ErrorMessages::convertFailed(fi.fileName());
return false;

// 提取DBus通知公共方法(notifyclient.cpp)
static void sendDbusNotification(const QString &body) {
    QDBusInterface iface(QStringLiteral("org.freedesktop.Notifications"),
                         QStringLiteral("/org/freedesktop/Notifications"),
                         QStringLiteral("org.freedesktop.Notifications"));
    if (!iface.isValid()) {
        fprintf(stderr, "%s\n", body.toUtf8().constData());
        return;
    }
    QVariantList args;
    args << QStringLiteral("deepin-reader");
    args << quint32(0);
    args << QStringLiteral("deepin-reader");
    args << ErrorMessages::notifyTitle();
    args << body;
    args << QStringList();
    args << QVariantMap();
    args << qint32(-1);
    QDBusMessage reply = iface.call(QStringLiteral("Notify"), args);
    if (reply.type() == QDBusMessage::ErrorMessage) {
        fprintf(stderr, "%s\n", body.toUtf8().constData());
    }
}

本报告由 AI 代码审查工具自动生成

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: lzwind, pengfeixx

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@pengfeixx

Copy link
Copy Markdown
Contributor Author

/merge

@deepin-bot
deepin-bot Bot merged commit 5de3f0d into linuxdeepin:master Sep 15, 2026
8 checks passed
@pengfeixx
pengfeixx deleted the feat/batch-print branch September 15, 2026 06:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants