feat(batch-print): add headless batch print for pdf/docx/djvu/xps - #385
Conversation
Reviewer's GuideThis 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 printingsequenceDiagram
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
Flow diagram for document format normalizationflowchart 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
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
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>7171d0c to
8e0e04f
Compare
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: 用户可在文件管理器中多选文档批量打印,无需逐个操作。
8e0e04f to
7bd82e1
Compare
deepin pr auto review🤖 AI 代码审查报告📊 总体评价
🔍 详细分析1. 语法逻辑 ❌评价: 一般 ❌ 不通过 潜在问题:
建议: 在DOCX转换路径中添加QProcess的清理逻辑,使用QScopedPointer或智能指针管理QProcess生命周期 2. 代码质量 ❌评价: 良好 ❌ 不通过 潜在问题:
建议: 提取DBus通知公共方法消除重复代码;在DJVU转换中复用computePageSizeMm方法 3. 代码性能 ✅评价: 优秀 ✅ 通过 潜在问题: 建议: 性能良好,资源使用合理 4. 代码安全 🔒评价: 优秀 ✅ 通过
安全漏洞详情: 建议: 安全合规 💡 改进建议代码示例// 修复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 代码审查工具自动生成 |
|
[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. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
/merge |
feat: add headless batch print for pdf/docx/djvu/xps
Summary
新增
deepin-reader-batchprint独立进程,支持在文件管理器中多选 pdf/docx/djvu/xps 文档后通过右键菜单"批量打印"静默完成打印,全程无对话框交互。Key changes
deepin-reader-batchprint.conf注册右键菜单项Test scenarios
ll-builder build成功,batch-print 正确编出并打包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:
Bug Fixes:
Enhancements:
Build:
Deployment:
Tests: