Repository navigation
feat(batch-print): add headless batch print for pdf/docx/djvu/xps #384
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,129 @@ | ||
| # SPDX-FileCopyrightText: 2023 - 2026 UnionTech Software Technology Co., Ltd. | ||
| # | ||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||
|
|
||
| # [v4] Batch print unit tests switch (default OFF) | ||
| option(BATCH_PRINT_TESTS "Build batch print unit tests" OFF) | ||
|
|
||
| # Find Qt components needed by batch-print modules (DBus for notifications, PrintSupport for QPdfWriter) | ||
| pkg_check_modules(FREETYPE REQUIRED freetype2) | ||
| find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS DBus PrintSupport Sql) | ||
|
|
||
| # batchprint-core: CupsClient + NotifyClient + PrintSettings + ErrorMessages (no reader source dependency) | ||
| add_library(batchprint-core STATIC | ||
| cupsclient.h cupsclient.cpp | ||
| icupsapi.h | ||
| notifyclient.h notifyclient.cpp | ||
| printsettings.h printsettings.cpp | ||
| errormessages.h errormessages.cpp | ||
| ) | ||
|
|
||
| target_include_directories(batchprint-core PUBLIC | ||
| ${CMAKE_CURRENT_SOURCE_DIR} | ||
| ) | ||
|
|
||
| target_link_libraries(batchprint-core PUBLIC | ||
| Qt${QT_VERSION_MAJOR}::Gui | ||
| Qt${QT_VERSION_MAJOR}::DBus | ||
| ) | ||
|
|
||
| # batchprint-convert: FormatConverter (depends on selected reader/document sources + deepin-pdfium) | ||
| # Explicitly list only the reader source files needed for document loading/rendering, | ||
| # NOT the entire reader GUI (browser/sidebar/widgets/uiframe). | ||
| set(BATCHPRINT_READER_SOURCES | ||
| ${CMAKE_SOURCE_DIR}/reader/app/Global.cpp | ||
| ${CMAKE_SOURCE_DIR}/reader/document/Model.cpp | ||
| ${CMAKE_SOURCE_DIR}/reader/document/PDFModel.cpp | ||
| ${CMAKE_SOURCE_DIR}/reader/document/DjVuModel.cpp | ||
| ${CMAKE_SOURCE_DIR}/reader/document/XpsDocumentAdapter.cpp | ||
| ${CMAKE_SOURCE_DIR}/reader/document/XpsTextExtractor.cpp | ||
| ) | ||
|
|
||
| add_library(batchprint-convert STATIC | ||
| formatconverter.h formatconverter.cpp | ||
| ${BATCHPRINT_READER_SOURCES} | ||
| ) | ||
|
|
||
| set_target_properties(batchprint-convert PROPERTIES | ||
| AUTOMOC ON | ||
| AUTOUIC ON | ||
| ) | ||
|
|
||
| target_include_directories(batchprint-convert PUBLIC | ||
| ${CMAKE_CURRENT_SOURCE_DIR} | ||
| ${CMAKE_SOURCE_DIR}/reader | ||
| ${CMAKE_SOURCE_DIR}/reader/app | ||
| ${CMAKE_SOURCE_DIR}/reader/document | ||
| ${PDFIUM_INCLUDE_DIRS} | ||
| $<$<BOOL:${XPS_SUPPORT_ENABLED}>:${XPS_DEPS_INCLUDE_DIRS}> | ||
| ) | ||
|
|
||
| target_compile_definitions(batchprint-convert PRIVATE | ||
| INSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}" | ||
| INSTALL_LIBDIR="${CMAKE_INSTALL_LIBDIR}" | ||
| APP_VERSION="1.0.0" | ||
| ) | ||
|
|
||
| target_link_libraries(batchprint-convert PUBLIC | ||
| batchprint-core | ||
| Qt${QT_VERSION_MAJOR}::Gui | ||
| Qt${QT_VERSION_MAJOR}::Widgets | ||
| Qt${QT_VERSION_MAJOR}::PrintSupport | ||
| Qt${QT_VERSION_MAJOR}::Network | ||
| Qt${QT_VERSION_MAJOR}::Svg | ||
| Qt${QT_VERSION_MAJOR}::Concurrent | ||
| Qt${QT_VERSION_MAJOR}::Sql | ||
| Qt${QT_VERSION_MAJOR}::Xml | ||
| ${DDJVU_LIBRARIES} | ||
| ${LIBJPEG_LIBRARIES} | ||
| ${FREETYPE_LIBRARIES} | ||
| $<$<BOOL:${XPS_SUPPORT_ENABLED}>:${XPS_DEPS_LIBRARIES}> | ||
| ) | ||
|
|
||
| # DTK linking | ||
| if(DTK_USE_TARGETS) | ||
| target_link_libraries(batchprint-convert PUBLIC | ||
| Dtk${DTK_VERSION_MAJOR}::Widget | ||
| Dtk${DTK_VERSION_MAJOR}::Gui | ||
| Dtk${DTK_VERSION_MAJOR}::Core | ||
| ) | ||
| endif() | ||
|
|
||
| if (QT_VERSION_MAJOR MATCHES 6) | ||
| target_link_libraries(batchprint-convert PUBLIC Qt${QT_VERSION_MAJOR}::Core5Compat) | ||
| endif() | ||
|
|
||
| if (USE_PDFIUM_BUNDLE) | ||
| target_link_libraries(batchprint-convert PUBLIC deepin-pdfium-reader) | ||
| else() | ||
| target_link_libraries(batchprint-convert PUBLIC PkgConfig::Deepin-pdfium) | ||
| endif() | ||
|
|
||
| if (XPS_SUPPORT_ENABLED) | ||
| target_compile_definitions(batchprint-convert PUBLIC XPS_SUPPORT_ENABLED) | ||
| target_compile_options(batchprint-convert PUBLIC ${XPS_DEPS_CFLAGS_OTHER}) | ||
| endif() | ||
|
|
||
| # Executable | ||
| add_executable(deepin-reader-batchprint | ||
| main.cpp | ||
| batchprintapp.h batchprintapp.cpp | ||
| ) | ||
|
|
||
| target_link_libraries(deepin-reader-batchprint PRIVATE | ||
| batchprint-core | ||
| batchprint-convert | ||
| ) | ||
|
|
||
| install(TARGETS deepin-reader-batchprint | ||
| RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} | ||
| ) | ||
|
|
||
| if (BATCH_PRINT_TESTS) | ||
| add_subdirectory(tests) | ||
| endif() | ||
|
|
||
| # Batch print unit tests | ||
| if (BATCH_PRINT_TESTS) | ||
| enable_testing() | ||
| endif() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| // SPDX-FileCopyrightText: 2023 - 2026 UnionTech Software Technology Co., Ltd. | ||
| // | ||
| // SPDX-License-Identifier: GPL-3.0-or-later | ||
|
|
||
| #include "batchprintapp.h" | ||
| #include "formatconverter.h" | ||
| #include "notifyclient.h" | ||
| #include "errormessages.h" | ||
|
|
||
| #include <QTemporaryDir> | ||
|
Check warning on line 10 in batch-print/batchprintapp.cpp
|
||
| #include <QFileInfo> | ||
|
Check warning on line 11 in batch-print/batchprintapp.cpp
|
||
| #include <QDebug> | ||
|
Check warning on line 12 in batch-print/batchprintapp.cpp
|
||
|
|
||
| BatchPrintApp::BatchPrintApp(ICupsApi *cupsApi) | ||
| { | ||
| if (cupsApi) { | ||
| m_cupsApi = cupsApi; | ||
| m_ownsCupsApi = false; | ||
| } else { | ||
| m_cupsApi = new CupsClient(); | ||
|
Check warning on line 20 in batch-print/batchprintapp.cpp
|
||
| m_ownsCupsApi = true; | ||
| } | ||
| } | ||
|
|
||
| BatchPrintApp::~BatchPrintApp() | ||
| { | ||
| if (m_ownsCupsApi) | ||
| delete m_cupsApi; | ||
| } | ||
|
|
||
| int BatchPrintApp::run(const QStringList &fileList) | ||
| { | ||
| CupsClient *cups = dynamic_cast<CupsClient *>(m_cupsApi); | ||
| if (cups) { | ||
| if (!cups->init()) { | ||
| qWarning() << "CUPS init failed"; | ||
| NotifyClient::notifyError(ErrorMessages::cupsUnavailable()); | ||
| return 2; | ||
| } | ||
| if (!cups->checkEnvironment()) { | ||
| qWarning() << "CUPS environment check failed"; | ||
| NotifyClient::notifyError(ErrorMessages::noDefaultPrinter()); | ||
| return 2; | ||
| } | ||
| if (cups->isColorSupported()) { | ||
| m_settings.colorMode = ColorMode::Auto; | ||
| } else { | ||
| m_settings.colorMode = ColorMode::Gray; | ||
| } | ||
| } | ||
|
|
||
| int total = fileList.size(); | ||
| int succeeded = 0; | ||
| QStringList failedFiles; | ||
|
|
||
| for (const QString &filePath : fileList) { | ||
| QTemporaryDir tempDir; | ||
| if (!tempDir.isValid()) { | ||
| failedFiles.append(QFileInfo(filePath).fileName()); | ||
| continue; | ||
| } | ||
|
|
||
| QString outputPdfPath; | ||
| QString errorMsg; | ||
| if (!FormatConverter::convertToPdf(filePath, tempDir.path(), | ||
| outputPdfPath, errorMsg)) { | ||
| qWarning() << errorMsg; | ||
| failedFiles.append(QFileInfo(filePath).fileName()); | ||
| continue; | ||
| } | ||
|
|
||
| QString jobTitle = QFileInfo(filePath).fileName(); | ||
| bool printOk = false; | ||
| if (cups) { | ||
| printOk = cups->submitJob(outputPdfPath, jobTitle, m_settings); | ||
| } else { | ||
| printOk = m_cupsApi->printFile(QString(), outputPdfPath, jobTitle, 0, nullptr); | ||
| } | ||
|
|
||
| if (!printOk) { | ||
| failedFiles.append(QFileInfo(filePath).fileName()); | ||
| continue; | ||
| } | ||
|
|
||
| ++succeeded; | ||
| } | ||
|
|
||
| NotifyClient::notifyResult(total, succeeded, failedFiles); | ||
|
|
||
| if (succeeded == total) | ||
| return 0; | ||
| return 1; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| // SPDX-FileCopyrightText: 2023 - 2026 UnionTech Software Technology Co., Ltd. | ||
| // | ||
| // SPDX-License-Identifier: GPL-3.0-or-later | ||
|
|
||
| #ifndef BATCHPRINTAPP_H | ||
| #define BATCHPRINTAPP_H | ||
|
|
||
| #include "cupsclient.h" | ||
| #include "printsettings.h" | ||
|
|
||
| #include <QString> | ||
|
Check warning on line 11 in batch-print/batchprintapp.h
|
||
| #include <QStringList> | ||
|
Check warning on line 12 in batch-print/batchprintapp.h
|
||
|
|
||
| class BatchPrintApp | ||
| { | ||
| public: | ||
| explicit BatchPrintApp(ICupsApi *cupsApi = nullptr); | ||
| ~BatchPrintApp(); | ||
|
|
||
| int run(const QStringList &fileList); | ||
|
|
||
| private: | ||
| ICupsApi *m_cupsApi = nullptr; | ||
| bool m_ownsCupsApi = false; | ||
| PrintSettings m_settings; | ||
| }; | ||
|
|
||
| #endif // BATCHPRINTAPP_H | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (broader_impact): The batch-print executable and its context-menu registration are only added when
USE_PDFIUM_BUNDLEis enabled. Configurations that intentionally use the system PDFium library build the reader but omit the advertised batch-print feature entirely.Triggers: When the project is configured with
-DUSE_PDFIUM_BUNDLE=OFF.Suggested fix: Move the batch-print subdirectory and context-menu installation outside the
USE_PDFIUM_BUNDLEconditional; retain only the PDFium target selection inside the conditional.