From 649a3238f91921e3f38f8e91e49f97a02655c94d Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Fri, 9 Jul 2021 19:24:15 +0200 Subject: Add QtPdf to cmake build Port QtPdf to Qt6: * QtPdf,QtPdfWidgets,QtPdfQuick libs * QtPdfQuickPlugin, QtPdfPlugin (imageformat) plugins * widget and quick examples * qtpdf tests To fit gn cmake integration and new repo layout code is a bit reshuffled. Compared to qmke build following features are not ported yet: * ios fat libs * qtbase 3rdparty static dependencies WebEngine build can be skipped with setting QT_FEATURE_qtwebengine_build=OFF Note this patch needs follow up for 6.2 branch to disable qtpdf builds by default, since this should not part of qt 6.2 release. Task-number: QTBUG-95353 Change-Id: I4dd9f3934bdd478fb6d2fa686074a24d91f09953 Reviewed-by: Allan Sandfeld Jensen (cherry picked from commit 79d04aa9e3e9aa84d7378260519f9e9a6759dc41) Reviewed-by: Qt Cherry-pick Bot --- CMakeLists.txt | 44 +- cmake/Functions.cmake | 71 +-- configure.cmake | 96 ++-- examples/CMakeLists.txt | 8 +- examples/pdf/CMakeLists.txt | 5 + examples/pdf/multipage/CMakeLists.txt | 62 +++ examples/pdf/multipage/viewer.qml | 46 +- examples/pdf/pdfviewer/CMakeLists.txt | 62 +++ examples/pdf/pdfviewer/viewer.qml | 48 +- examples/pdfwidgets/CMakeLists.txt | 1 + examples/pdfwidgets/pdfviewer/CMakeLists.txt | 63 +++ src/CMakeLists.txt | 23 +- src/host/CMakeLists.txt | 9 + src/pdf/CMakeLists.txt | 161 ++++++ src/pdf/api/qpdfbookmarkmodel.h | 98 ---- src/pdf/api/qpdfdestination.h | 85 ---- src/pdf/api/qpdfdestination_p.h | 71 --- src/pdf/api/qpdfdocument.h | 140 ------ src/pdf/api/qpdfdocument_p.h | 124 ----- src/pdf/api/qpdfdocumentrenderoptions.h | 94 ---- src/pdf/api/qpdflinkmodel_p.h | 106 ---- src/pdf/api/qpdflinkmodel_p_p.h | 91 ---- src/pdf/api/qpdfnamespace.h | 73 --- src/pdf/api/qpdfpagenavigation.h | 92 ---- src/pdf/api/qpdfpagerenderer.h | 92 ---- src/pdf/api/qpdfsearchmodel.h | 98 ---- src/pdf/api/qpdfsearchmodel_p.h | 86 ---- src/pdf/api/qpdfsearchresult.h | 76 --- src/pdf/api/qpdfsearchresult_p.h | 72 --- src/pdf/api/qpdfselection.h | 91 ---- src/pdf/api/qpdfselection_p.h | 65 --- src/pdf/api/qtpdfglobal.h | 61 --- src/pdf/configure.cmake | 39 ++ src/pdf/configure/BUILD.root.gn.in | 36 ++ src/pdf/jsbridge.cpp | 38 -- src/pdf/plugins/imageformats/pdf/CMakeLists.txt | 11 + src/pdf/plugins/imageformats/pdf/main.cpp | 74 +++ src/pdf/plugins/imageformats/pdf/pdf.json | 4 + src/pdf/plugins/imageformats/pdf/qpdfiohandler.cpp | 239 +++++++++ src/pdf/plugins/imageformats/pdf/qpdfiohandler_p.h | 88 ++++ src/pdf/qpdfbookmarkmodel.cpp | 1 + src/pdf/qpdfbookmarkmodel.h | 98 ++++ src/pdf/qpdfdestination.h | 85 ++++ src/pdf/qpdfdestination_p.h | 71 +++ src/pdf/qpdfdocument.h | 140 ++++++ src/pdf/qpdfdocument_p.h | 124 +++++ src/pdf/qpdfdocumentrenderoptions.h | 94 ++++ src/pdf/qpdflinkmodel_p.h | 106 ++++ src/pdf/qpdflinkmodel_p_p.h | 91 ++++ src/pdf/qpdfnamespace.h | 73 +++ src/pdf/qpdfpagenavigation.h | 92 ++++ src/pdf/qpdfpagerenderer.h | 92 ++++ src/pdf/qpdfsearchmodel.h | 98 ++++ src/pdf/qpdfsearchmodel_p.h | 86 ++++ src/pdf/qpdfsearchresult.h | 76 +++ src/pdf/qpdfsearchresult_p.h | 72 +++ src/pdf/qpdfselection.h | 91 ++++ src/pdf/qpdfselection_p.h | 65 +++ src/pdf/qtpdf.gni | 7 - src/pdf/qtpdfglobal.h | 61 +++ src/pdf/quick/plugin.cpp | 103 ---- src/pdf/quick/plugins.qmltypes | 52 -- src/pdf/quick/qml/+material/PdfStyle.qml | 54 -- src/pdf/quick/qml/+universal/PdfStyle.qml | 55 --- src/pdf/quick/qml/PdfMultiPageView.qml | 434 ---------------- src/pdf/quick/qml/PdfPageView.qml | 276 ----------- src/pdf/quick/qml/PdfScrollablePageView.qml | 307 ------------ src/pdf/quick/qml/PdfStyle.qml | 54 -- src/pdf/quick/qmldir | 4 - src/pdf/quick/qquickpdfdocument.cpp | 305 ------------ src/pdf/quick/qquickpdfdocument_p.h | 137 ------ src/pdf/quick/qquickpdflinkmodel.cpp | 131 ----- src/pdf/quick/qquickpdflinkmodel_p.h | 87 ---- src/pdf/quick/qquickpdfnavigationstack.cpp | 272 ----------- src/pdf/quick/qquickpdfnavigationstack_p.h | 102 ---- src/pdf/quick/qquickpdfsearchmodel.cpp | 301 ------------ src/pdf/quick/qquickpdfsearchmodel_p.h | 113 ----- src/pdf/quick/qquickpdfselection.cpp | 541 -------------------- src/pdf/quick/qquickpdfselection_p.h | 148 ------ src/pdf/quick/qquicktableviewextra.cpp | 78 --- src/pdf/quick/qquicktableviewextra_p.h | 92 ---- src/pdfquick/CMakeLists.txt | 55 +++ src/pdfquick/plugin.cpp | 99 ++++ src/pdfquick/plugins.qmltypes | 52 ++ src/pdfquick/qml/+material/PdfStyle.qml | 54 ++ src/pdfquick/qml/+universal/PdfStyle.qml | 55 +++ src/pdfquick/qml/PdfMultiPageView.qml | 434 ++++++++++++++++ src/pdfquick/qml/PdfPageView.qml | 276 +++++++++++ src/pdfquick/qml/PdfScrollablePageView.qml | 307 ++++++++++++ src/pdfquick/qml/PdfStyle.qml | 54 ++ src/pdfquick/qquickpdfdocument.cpp | 305 ++++++++++++ src/pdfquick/qquickpdfdocument_p.h | 138 ++++++ src/pdfquick/qquickpdflinkmodel.cpp | 131 +++++ src/pdfquick/qquickpdflinkmodel_p.h | 88 ++++ src/pdfquick/qquickpdfnavigationstack.cpp | 272 +++++++++++ src/pdfquick/qquickpdfnavigationstack_p.h | 103 ++++ src/pdfquick/qquickpdfsearchmodel.cpp | 301 ++++++++++++ src/pdfquick/qquickpdfsearchmodel_p.h | 114 +++++ src/pdfquick/qquickpdfselection.cpp | 543 +++++++++++++++++++++ src/pdfquick/qquickpdfselection_p.h | 148 ++++++ src/pdfquick/qquicktableviewextra.cpp | 78 +++ src/pdfquick/qquicktableviewextra_p.h | 93 ++++ src/pdfquick/qtpdfquickglobal_p.h | 59 +++ src/pdfwidgets/CMakeLists.txt | 15 + src/plugins/imageformats/pdf/main.cpp | 74 --- src/plugins/imageformats/pdf/pdf.json | 4 - src/plugins/imageformats/pdf/qpdfiohandler.cpp | 239 --------- src/plugins/imageformats/pdf/qpdfiohandler_p.h | 88 ---- sync.profile | 4 +- tests/CMakeLists.txt | 3 +- tests/auto/CMakeLists.txt | 7 +- tests/auto/pdf/CMakeLists.txt | 6 + tests/auto/pdf/qpdfbookmarkmodel/CMakeLists.txt | 9 + tests/auto/pdf/qpdfdocument/CMakeLists.txt | 9 + tests/auto/pdf/qpdfpagenavigation/CMakeLists.txt | 8 + tests/auto/pdf/qpdfpagerenderer/CMakeLists.txt | 9 + tests/auto/pdf/qpdfsearchmodel/CMakeLists.txt | 8 + 117 files changed, 6491 insertions(+), 5863 deletions(-) create mode 100644 examples/pdf/CMakeLists.txt create mode 100644 examples/pdf/multipage/CMakeLists.txt create mode 100644 examples/pdf/pdfviewer/CMakeLists.txt create mode 100644 examples/pdfwidgets/CMakeLists.txt create mode 100644 examples/pdfwidgets/pdfviewer/CMakeLists.txt create mode 100644 src/pdf/CMakeLists.txt delete mode 100644 src/pdf/api/qpdfbookmarkmodel.h delete mode 100644 src/pdf/api/qpdfdestination.h delete mode 100644 src/pdf/api/qpdfdestination_p.h delete mode 100644 src/pdf/api/qpdfdocument.h delete mode 100644 src/pdf/api/qpdfdocument_p.h delete mode 100644 src/pdf/api/qpdfdocumentrenderoptions.h delete mode 100644 src/pdf/api/qpdflinkmodel_p.h delete mode 100644 src/pdf/api/qpdflinkmodel_p_p.h delete mode 100644 src/pdf/api/qpdfnamespace.h delete mode 100644 src/pdf/api/qpdfpagenavigation.h delete mode 100644 src/pdf/api/qpdfpagerenderer.h delete mode 100644 src/pdf/api/qpdfsearchmodel.h delete mode 100644 src/pdf/api/qpdfsearchmodel_p.h delete mode 100644 src/pdf/api/qpdfsearchresult.h delete mode 100644 src/pdf/api/qpdfsearchresult_p.h delete mode 100644 src/pdf/api/qpdfselection.h delete mode 100644 src/pdf/api/qpdfselection_p.h delete mode 100644 src/pdf/api/qtpdfglobal.h create mode 100644 src/pdf/configure.cmake create mode 100644 src/pdf/configure/BUILD.root.gn.in delete mode 100644 src/pdf/jsbridge.cpp create mode 100644 src/pdf/plugins/imageformats/pdf/CMakeLists.txt create mode 100644 src/pdf/plugins/imageformats/pdf/main.cpp create mode 100644 src/pdf/plugins/imageformats/pdf/pdf.json create mode 100644 src/pdf/plugins/imageformats/pdf/qpdfiohandler.cpp create mode 100644 src/pdf/plugins/imageformats/pdf/qpdfiohandler_p.h create mode 100644 src/pdf/qpdfbookmarkmodel.h create mode 100644 src/pdf/qpdfdestination.h create mode 100644 src/pdf/qpdfdestination_p.h create mode 100644 src/pdf/qpdfdocument.h create mode 100644 src/pdf/qpdfdocument_p.h create mode 100644 src/pdf/qpdfdocumentrenderoptions.h create mode 100644 src/pdf/qpdflinkmodel_p.h create mode 100644 src/pdf/qpdflinkmodel_p_p.h create mode 100644 src/pdf/qpdfnamespace.h create mode 100644 src/pdf/qpdfpagenavigation.h create mode 100644 src/pdf/qpdfpagerenderer.h create mode 100644 src/pdf/qpdfsearchmodel.h create mode 100644 src/pdf/qpdfsearchmodel_p.h create mode 100644 src/pdf/qpdfsearchresult.h create mode 100644 src/pdf/qpdfsearchresult_p.h create mode 100644 src/pdf/qpdfselection.h create mode 100644 src/pdf/qpdfselection_p.h delete mode 100644 src/pdf/qtpdf.gni create mode 100644 src/pdf/qtpdfglobal.h delete mode 100644 src/pdf/quick/plugin.cpp delete mode 100644 src/pdf/quick/plugins.qmltypes delete mode 100644 src/pdf/quick/qml/+material/PdfStyle.qml delete mode 100644 src/pdf/quick/qml/+universal/PdfStyle.qml delete mode 100644 src/pdf/quick/qml/PdfMultiPageView.qml delete mode 100644 src/pdf/quick/qml/PdfPageView.qml delete mode 100644 src/pdf/quick/qml/PdfScrollablePageView.qml delete mode 100644 src/pdf/quick/qml/PdfStyle.qml delete mode 100644 src/pdf/quick/qmldir delete mode 100644 src/pdf/quick/qquickpdfdocument.cpp delete mode 100644 src/pdf/quick/qquickpdfdocument_p.h delete mode 100644 src/pdf/quick/qquickpdflinkmodel.cpp delete mode 100644 src/pdf/quick/qquickpdflinkmodel_p.h delete mode 100644 src/pdf/quick/qquickpdfnavigationstack.cpp delete mode 100644 src/pdf/quick/qquickpdfnavigationstack_p.h delete mode 100644 src/pdf/quick/qquickpdfsearchmodel.cpp delete mode 100644 src/pdf/quick/qquickpdfsearchmodel_p.h delete mode 100644 src/pdf/quick/qquickpdfselection.cpp delete mode 100644 src/pdf/quick/qquickpdfselection_p.h delete mode 100644 src/pdf/quick/qquicktableviewextra.cpp delete mode 100644 src/pdf/quick/qquicktableviewextra_p.h create mode 100644 src/pdfquick/CMakeLists.txt create mode 100644 src/pdfquick/plugin.cpp create mode 100644 src/pdfquick/plugins.qmltypes create mode 100644 src/pdfquick/qml/+material/PdfStyle.qml create mode 100644 src/pdfquick/qml/+universal/PdfStyle.qml create mode 100644 src/pdfquick/qml/PdfMultiPageView.qml create mode 100644 src/pdfquick/qml/PdfPageView.qml create mode 100644 src/pdfquick/qml/PdfScrollablePageView.qml create mode 100644 src/pdfquick/qml/PdfStyle.qml create mode 100644 src/pdfquick/qquickpdfdocument.cpp create mode 100644 src/pdfquick/qquickpdfdocument_p.h create mode 100644 src/pdfquick/qquickpdflinkmodel.cpp create mode 100644 src/pdfquick/qquickpdflinkmodel_p.h create mode 100644 src/pdfquick/qquickpdfnavigationstack.cpp create mode 100644 src/pdfquick/qquickpdfnavigationstack_p.h create mode 100644 src/pdfquick/qquickpdfsearchmodel.cpp create mode 100644 src/pdfquick/qquickpdfsearchmodel_p.h create mode 100644 src/pdfquick/qquickpdfselection.cpp create mode 100644 src/pdfquick/qquickpdfselection_p.h create mode 100644 src/pdfquick/qquicktableviewextra.cpp create mode 100644 src/pdfquick/qquicktableviewextra_p.h create mode 100644 src/pdfquick/qtpdfquickglobal_p.h create mode 100644 src/pdfwidgets/CMakeLists.txt delete mode 100644 src/plugins/imageformats/pdf/main.cpp delete mode 100644 src/plugins/imageformats/pdf/pdf.json delete mode 100644 src/plugins/imageformats/pdf/qpdfiohandler.cpp delete mode 100644 src/plugins/imageformats/pdf/qpdfiohandler_p.h create mode 100644 tests/auto/pdf/CMakeLists.txt create mode 100644 tests/auto/pdf/qpdfbookmarkmodel/CMakeLists.txt create mode 100644 tests/auto/pdf/qpdfdocument/CMakeLists.txt create mode 100644 tests/auto/pdf/qpdfpagenavigation/CMakeLists.txt create mode 100644 tests/auto/pdf/qpdfpagerenderer/CMakeLists.txt create mode 100644 tests/auto/pdf/qpdfsearchmodel/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 9939167a0..823945088 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,21 +39,25 @@ set(__QtFeature_only_evaluate_features OFF) include(configure.cmake) include(src/core/api/configure.cmake) include(src/webenginequick/configure.cmake) +include(src/pdf/configure.cmake) qt_feature_module_end(ONLY_EVALUATE_FEATURES) - -if(NOT ${webEngineSupport}) +if(NOT ${QtWebEngine_SUPPORT}) add_custom_target(WebEngineErrorMessage ALL - ${CMAKE_COMMAND} -E cmake_echo_color --red "QtWebEngine will not be built: ${webEngineError}" - COMMENT "Check QtWebEngine support") - message("-- Support check for QtWebEngine failed: ${webEngineError}") + ${CMAKE_COMMAND} -E cmake_echo_color --red "QtWebEngine will not be built: ${QtWebEngine_ERROR}" + COMMENT "Check QtWebEngine support" + VERBATIM + ) + message("-- Support check for QtWebEngine failed: ${QtWebEngine_ERROR}") set(QT_FEATURE_qtwebengine_build OFF CACHE BOOL "Build QtWebEngine" FORCE) endif() -if(NOT ${pdfSupport}) +if(NOT ${QtPdf_SUPPORT}) add_custom_target(PdfErrorMessage ALL - ${CMAKE_COMMAND} -E cmake_echo_color --red "QtPdf will not be built: ${pdfError}" - COMMENT "Check QtPdf support") - message("-- Support check for QtPdf failed: ${pdfError}") + ${CMAKE_COMMAND} -E cmake_echo_color --red "QtPdf will not be built: ${QtPdf_ERROR}" + COMMENT "Check QtPdf support" + VERBATIM + ) + message("-- Support check for QtPdf failed: ${QtPdf_ERROR}") set(QT_FEATURE_qtpdf_build OFF CACHE BOOL "Build QtPdf" FORCE) endif() @@ -63,11 +67,19 @@ if(NOT QT_FEATURE_qtwebengine_build AND NOT QT_FEATURE_qtpdf_build) return() endif() -add_subdirectory(src/core/api) -add_subdirectory(src/core/tools) -add_subdirectory(src/process) -add_subdirectory(src/webenginewidgets) -add_subdirectory(src/webenginequick) +if(QT_FEATURE_qtwebengine_build) + add_subdirectory(src/core/api) + add_subdirectory(src/core/tools) + add_subdirectory(src/process) + add_subdirectory(src/webenginewidgets) + add_subdirectory(src/webenginequick) +endif() + +if(QT_FEATURE_qtpdf_build) + add_subdirectory(src/pdf) + add_subdirectory(src/pdfwidgets) + add_subdirectory(src/pdfquick) +endif() qt_build_repo_end() get_install_config(installConfig) @@ -112,6 +124,7 @@ endif() get_filename_component(WEBENGINE_ROOT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" REALPATH) get_qt_features(featureList webengine) get_qt_features(featureList qtwebengine) +get_qt_features(featureList qtpdf) if(NOT DEFINED CMAKE_TOOLCHAIN_FILE AND QT_SUPERBUILD) set(CMAKE_TOOLCHAIN_FILE "${CMAKE_BINARY_DIR}/qtbase/lib/cmake/Qt6/qt.toolchain.cmake") @@ -233,7 +246,7 @@ if(NOT Ninja_FOUND) externalproject_add_stepdependencies(gn install ninja) endif() -if(NOT QT_FEATURE_framework) +if(QT_FEATURE_qtwebengine_build AND NOT QT_FEATURE_framework) # install resources (again), coin calls install with DESTDIR install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/translations/qtwebengine_locales DESTINATION ${CMAKE_INSTALL_PREFIX}/translations @@ -269,6 +282,7 @@ if(CMAKE_CROSSCOMPILING) -DCMAKE_C_FLAGS= -DCMAKE_CXX_FLAGS= -DQT_FEATURE_qtwebengine_build=${QT_FEATURE_qtwebengine_build} + -DQT_FEATURE_qtpdf_build=${QT_FEATURE_qtpdf_build} ) externalproject_add_stepdependencies(qtwebengine install hostBuild) endif() diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake index 4f342eb2d..516ae79fc 100644 --- a/cmake/Functions.cmake +++ b/cmake/Functions.cmake @@ -1,19 +1,22 @@ -function(assertTargets errorResult supportResult) - if(NOT DEFINED ${supportResult}) - set(${supportResult} ON PARENT_SCOPE) - set(${supportResult} ON) - endif() - if(${${supportResult}}) - list(REMOVE_ITEM ARGN ${errorResult}) - list(REMOVE_ITEM ARGN ${supportResult}) - foreach(qtTarget IN ITEMS ${ARGN}) - if(NOT TARGET Qt::${qtTarget}) - set(${errorResult} "Missing required Qt::${qtTarget}." PARENT_SCOPE) - set(${supportResult} OFF PARENT_SCOPE) - return() - endif() - endforeach() - endif() +function(assertTargets) + qt_parse_all_arguments(arg "add_check_for_support" + "" "" "MODULES;TARGETS" "${ARGN}" + ) + foreach(module ${arg_MODULES}) + if(NOT DEFINED ${module}_SUPPORT) + set(${module}_SUPPORT ON PARENT_SCOPE) + set(${module}_SUPPORT ON) + endif() + if(${module}_SUPPORT) + foreach(qtTarget ${arg_TARGETS}) + if(NOT TARGET Qt::${qtTarget}) + set(${module}_ERROR "Missing required Qt::${qtTarget}." PARENT_SCOPE) + set(${module}_SUPPORT OFF PARENT_SCOPE) + break() + endif() + endforeach() + endif() + endforeach() endfunction() function(add_implicit_dependencies target) @@ -27,29 +30,31 @@ function(add_implicit_dependencies target) endif() endfunction() - # TODO: this should be idealy in qtbase -function(add_check_for_support errorResult supportResult) - if(NOT DEFINED ${supportResult}) - set(${supportResult} ON PARENT_SCOPE) - set(${supportResult} ON) - endif() - if(${${supportResult}}) - qt_parse_all_arguments(arg "add_check_for_support" - "" "MODULE" "MESSAGE;CONDITION" "${ARGN}") - if("x${arg_CONDITION}" STREQUAL x) - set(arg_CONDITION ON) +function(add_check_for_support) + qt_parse_all_arguments(arg "add_check_for_support" + "" "" "MODULES;MESSAGE;CONDITION" "${ARGN}" + ) + foreach(module ${arg_MODULES}) + if(NOT DEFINED ${module}_SUPPORT) + set(${module}_SUPPORT ON PARENT_SCOPE) + set(${module}_SUPPORT ON) endif() - qt_evaluate_config_expression(result ${arg_CONDITION}) - if(NOT ${result}) - set(${supportResult} OFF PARENT_SCOPE) - set(${errorResult} ${arg_MESSAGE} PARENT_SCOPE) + if(${module}_SUPPORT) + if("x${arg_CONDITION}" STREQUAL x) + set(arg_CONDITION ON) + endif() + qt_evaluate_config_expression(result ${arg_CONDITION}) + if(NOT ${result}) + set(${module}_SUPPORT OFF PARENT_SCOPE) + set(${module}_ERROR ${arg_MESSAGE} PARENT_SCOPE) qt_configure_add_report_entry(TYPE WARNING - MESSAGE "${arg_MODULE} won't be built. ${arg_MESSAGE}" + MESSAGE "${module} won't be built. ${arg_MESSAGE}" CONDITION ON ) + endif() endif() - endif() + endforeach() endfunction() function(get_qt_features outList module) diff --git a/configure.cmake b/configure.cmake index 418d90fbe..995f4c342 100644 --- a/configure.cmake +++ b/configure.cmake @@ -9,7 +9,7 @@ if(QT_CONFIGURE_RUNNING) endfunction() else() find_package(Ninja 1.7.2) - find_package(Gn ${QT_REPO_MODULE_VERSION} EXACT) + find_package(Gn ${QT_REPO_MODULES_VERSION} EXACT) find_package(Python2 2.7.5) find_package(GPerf) find_package(BISON) @@ -207,7 +207,17 @@ qt_feature("qtwebengine-quick-build" PRIVATE ) qt_feature("qtpdf-build" PRIVATE LABEL "Build Qt PDF" - PURPOSE "Enables building the Qt PDF rendering module." + PURPOSE "Enables building the Qt Pdf modules." +) +qt_feature("qtpdf-widgets-build" PRIVATE + LABEL "Build Qt PdfWidgets" + PURPOSE "Enables building the Qt Pdf module." + CONDITION TARGET Qt::Widgets +) +qt_feature("qtpdf-quick-build" PRIVATE + LABEL "Build Qt PdfQuick" + PURPOSE "Enables building the Qt Pdf module." + CONDITION TARGET Qt::Quick AND TARGET Qt::Qml ) qt_feature("webengine-system-ninja" PRIVATE LABEL "Use system ninja" @@ -326,77 +336,80 @@ else() set(WIN_ARM_64 OFF) endif() -assertTargets(webEngineError webEngineSupport Gui Widgets OpenGL OpenGLWidgets Quick Qml) -add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine +assertTargets( + MODULES QtWebEngine QtPdf + TARGETS Gui Widgets OpenGL OpenGLWidgets Quick Qml +) +add_check_for_support( + MODULES QtWebEngine QtPdf CONDITION LINUX OR (WIN32 AND NOT WIN_ARM_64) OR (MACOS AND NOT CMAKE_CROSSCOMPILING) MESSAGE "Build can be done only on Linux, Windows or macOS." ) if(LINUX AND CMAKE_CROSSCOMPILING) get_gn_arch(testArch ${TEST_architecture_arch}) - add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine + add_check_for_support( + MODULES QtWebEngine QtPdf CONDITION testArch MESSAGE "Cross compiling is not supported for ${TEST_architecture_arch}." ) endif() -add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine +add_check_for_support( + MODULES QtWebEngine QtPdf CONDITION NOT QT_FEATURE_static MESSAGE "Static build is not supported." ) -add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine +add_check_for_support( + MODULES QtWebEngine QtPdf CONDITION TARGET Nodejs::Nodejs MESSAGE "Nodejs is required." ) -add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine +add_check_for_support( + MODULES QtWebEngine QtPdf CONDITION Python2_FOUND MESSAGE "Python2 version 2.7.5 or later is required." ) -add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine +add_check_for_support( + MODULES QtWebEngine QtPdf CONDITION GPerf_FOUND MESSAGE "Tool gperf is required." ) -add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine +add_check_for_support( + MODULES QtWebEngine QtPdf CONDITION BISON_FOUND MESSAGE "Tool bison is required." ) -add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine +add_check_for_support( + MODULES QtWebEngine QtPdf CONDITION FLEX_FOUND MESSAGE "Tool flex is required." ) -add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine +add_check_for_support( + MODULES QtWebEngine QtPdf CONDITION NOT LINUX OR PkgConfig_FOUND MESSAGE "A pkg-config support is required." ) -add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine +add_check_for_support( + MODULES QtWebEngine QtPdf CONDITION NOT LINUX OR TEST_glibc MESSAGE "A suitable version >= 2.17 of glibc is required." ) -add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine +add_check_for_support( + MODULES QtWebEngine QtPdf CONDITION NOT LINUX OR TEST_khr MESSAGE "Build requires Khronos development headers for build - see mesa/libegl1-mesa-dev" ) -add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine +add_check_for_support( + MODULES QtWebEngine CONDITION NOT LINUX OR FONTCONFIG_FOUND MESSAGE "Build requires fontconfig." ) -add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine +add_check_for_support( + MODULES QtWebEngine CONDITION NOT LINUX OR NSS_FOUND MESSAGE "Build requires nss >= 3.26." ) -add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine +add_check_for_support( + MODULES QtWebEngine CONDITION NOT LINUX OR DBUS_FOUND MESSAGE "Build requires dbus." ) @@ -409,19 +422,19 @@ foreach(xs ${xcbSupport}) set(xcbErrorMessage "${xcbErrorMessage} ${xs}:NO") endif() endforeach() -add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine +add_check_for_support( + MODULES QtWebEngine CONDITION NOT LINUX OR NOT QT_FEATURE_xcb OR QT_FEATURE_webengine_ozone_x11 MESSAGE "Could not find all necessary libraries for qpa-xcb support.\ ${xcbErrorMessage}" ) -add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine +add_check_for_support( + MODULES QtWebEngine QtPdf CONDITION NOT WIN32 OR TEST_winversion MESSAGE "Build requires Visual Studio 2019 or higher." ) -add_check_for_support(webEngineError webEngineSupport - MODULE QtWebEngine +add_check_for_support( + MODULES QtWebEngine QtPdf CONDITION (LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL GNU) OR (LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL Clang) OR @@ -431,11 +444,6 @@ add_check_for_support(webEngineError webEngineSupport (MACOS AND CMAKE_CXX_COMPILER_ID STREQUAL AppleClang) MESSAGE "${CMAKE_CXX_COMPILER_ID} compiler is not supported." ) -add_check_for_support(pdfError pdfSupport - MODULE QtPdf - CONDITION OFF - MESSAGE "QtPdf is missing cmake port." -) #### Summary @@ -475,13 +483,13 @@ qt_configure_end_summary_section() qt_configure_add_report_entry( TYPE NOTE MESSAGE "QtWebEngine build is disabled by user." - CONDITION ${webEngineSupport} AND NOT QT_FEATURE_qtwebengine_build + CONDITION QtWebEngine_SUPPORT AND NOT QT_FEATURE_qtwebengine_build ) qt_configure_add_report_entry( TYPE NOTE MESSAGE "QtPdf build is disabled by user." - CONDITION ${pdfSupport} AND NOT QT_FEATURE_qtpdf_build + CONDITION QtPdf_SUPPORT AND NOT QT_FEATURE_qtpdf_build ) qt_configure_add_report_entry( diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 5c6e1592d..2bd079b43 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -13,7 +13,9 @@ project(QtWebEngineExamples set(QT_USE_FIXED_QT_ADD_RESOURCE_BASE TRUE) find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals Core) -find_package(Qt6 ${PROJECT_VERSION} CONFIG OPTIONAL_COMPONENTS WebEngineCore WebEngineWidgets WebEngineQuick QuickControls2) +find_package(Qt6 ${PROJECT_VERSION} CONFIG OPTIONAL_COMPONENTS + WebEngineCore WebEngineWidgets WebEngineQuick PdfWidgets QuickControls2 Svg +) qt_build_repo_begin() qt_examples_build_begin() @@ -23,10 +25,10 @@ endif() if(QT_FEATURE_qtwebengine_build AND QT_FEATURE_qtwebengine_widgets_build) add_subdirectory(webenginewidgets) endif() -if(QT_FEATURE_qtpdf_build ) +if(QT_FEATURE_qtpdf_build AND QT_FEATURE_qtpdf_quick_build) add_subdirectory(pdf) endif() -if(QT_FEATURE_qtpdf_build AND QT_FEATURE_pdf_widgets) +if(QT_FEATURE_qtpdf_build AND QT_FEATURE_qtpdf_widgets_build) add_subdirectory(pdfwidgets) endif() diff --git a/examples/pdf/CMakeLists.txt b/examples/pdf/CMakeLists.txt new file mode 100644 index 000000000..cca6c03db --- /dev/null +++ b/examples/pdf/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(pdfviewer) +add_subdirectory(multipage) +if(NOT TARGET Qt::Svg) + message(WARNING "QtSvg is required as runtime dependency for qtpdfquick examples.") +endif() diff --git a/examples/pdf/multipage/CMakeLists.txt b/examples/pdf/multipage/CMakeLists.txt new file mode 100644 index 000000000..141da88b6 --- /dev/null +++ b/examples/pdf/multipage/CMakeLists.txt @@ -0,0 +1,62 @@ +cmake_minimum_required(VERSION 3.16) +project(multipage LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/pdf/multipage") + +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Qml) + +qt_add_executable(multipage + main.cpp +) +set_target_properties(multipage PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) +target_link_libraries(multipage PUBLIC + Qt::Gui + Qt::Qml +) + +set(viewer_resource_files + "resources/document-open.svg" + "resources/edit-clear.svg" + "resources/edit-copy.svg" + "resources/edit-select-all.svg" + "resources/go-down-search.svg" + "resources/go-next-view-page.svg" + "resources/go-previous-view-page.svg" + "resources/go-up-search.svg" + "resources/rotate-left.svg" + "resources/rotate-right.svg" + "resources/test.pdf" + "resources/zoom-fit-best.svg" + "resources/zoom-fit-width.svg" + "resources/zoom-in.svg" + "resources/zoom-original.svg" + "resources/zoom-out.svg" + "viewer.qml" +) + +qt6_add_resources(multipage "viewer" + PREFIX + "/pdfviewer" + FILES + ${viewer_resource_files} +) + +install(TARGETS multipage + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/pdf/multipage/viewer.qml b/examples/pdf/multipage/viewer.qml index f66c8d381..ed84d5547 100644 --- a/examples/pdf/multipage/viewer.qml +++ b/examples/pdf/multipage/viewer.qml @@ -47,14 +47,14 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -import QtQml 2.14 // workaround for QTBUG-82873 -import QtQuick 2.14 -import QtQuick.Controls 2.14 -import QtQuick.Layouts 1.14 -import QtQuick.Pdf 5.15 -import QtQuick.Shapes 1.14 -import QtQuick.Window 2.14 -import Qt.labs.platform 1.1 as Platform +import QtQml // workaround for QTBUG-82873 +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Pdf +import QtQuick.Shapes +import QtQuick.Window +import Qt.labs.platform as Platform ApplicationWindow { id: root @@ -72,7 +72,7 @@ ApplicationWindow { ToolButton { action: Action { shortcut: StandardKey.Open - icon.source: "resources/document-open.svg" + icon.source: "qrc:/pdfviewer/resources/document-open.svg" onTriggered: fileDialog.open() } } @@ -80,7 +80,7 @@ ApplicationWindow { action: Action { shortcut: StandardKey.ZoomIn enabled: view.renderScale < 10 - icon.source: "resources/zoom-in.svg" + icon.source: "qrc:/pdfviewer/resources/zoom-in.svg" onTriggered: view.renderScale *= Math.sqrt(2) } } @@ -88,46 +88,46 @@ ApplicationWindow { action: Action { shortcut: StandardKey.ZoomOut enabled: view.renderScale > 0.1 - icon.source: "resources/zoom-out.svg" + icon.source: "qrc:/pdfviewer/resources/zoom-out.svg" onTriggered: view.renderScale /= Math.sqrt(2) } } ToolButton { action: Action { - icon.source: "resources/zoom-fit-width.svg" + icon.source: "qrc:/pdfviewer/resources/zoom-fit-width.svg" onTriggered: view.scaleToWidth(root.contentItem.width, root.contentItem.height) } } ToolButton { action: Action { - icon.source: "resources/zoom-fit-best.svg" + icon.source: "qrc:/pdfviewer/resources/zoom-fit-best.svg" onTriggered: view.scaleToPage(root.contentItem.width, root.contentItem.height) } } ToolButton { action: Action { shortcut: "Ctrl+0" - icon.source: "resources/zoom-original.svg" + icon.source: "qrc:/pdfviewer/resources/zoom-original.svg" onTriggered: view.resetScale() } } ToolButton { action: Action { shortcut: "Ctrl+L" - icon.source: "resources/rotate-left.svg" + icon.source: "qrc:/pdfviewer/resources/rotate-left.svg" onTriggered: view.pageRotation -= 90 } } ToolButton { action: Action { shortcut: "Ctrl+R" - icon.source: "resources/rotate-right.svg" + icon.source: "qrc:/pdfviewer/resources/rotate-right.svg" onTriggered: view.pageRotation += 90 } } ToolButton { action: Action { - icon.source: "resources/go-previous-view-page.svg" + icon.source: "qrc:/pdfviewer/resources/go-previous-view-page.svg" enabled: view.backEnbled onTriggered: view.back() } @@ -152,7 +152,7 @@ ApplicationWindow { } ToolButton { action: Action { - icon.source: "resources/go-next-view-page.svg" + icon.source: "qrc:/pdfviewer/resources/go-next-view-page.svg" enabled: view.forwardEnabled onTriggered: view.forward() } @@ -163,14 +163,14 @@ ApplicationWindow { ToolButton { action: Action { shortcut: StandardKey.SelectAll - icon.source: "resources/edit-select-all.svg" + icon.source: "qrc:/pdfviewer/resources/edit-select-all.svg" onTriggered: view.selectAll() } } ToolButton { action: Action { shortcut: StandardKey.Copy - icon.source: "resources/edit-copy.svg" + icon.source: "qrc:/pdfviewer/resources/edit-copy.svg" enabled: view.selectedText !== "" onTriggered: view.copySelectionToClipboard() } @@ -308,7 +308,7 @@ ApplicationWindow { anchors.fill: parent ToolButton { action: Action { - icon.source: "resources/go-up-search.svg" + icon.source: "qrc:/pdfviewer/resources/go-up-search.svg" shortcut: StandardKey.FindPrevious onTriggered: view.searchBack() } @@ -324,7 +324,7 @@ ApplicationWindow { onAccepted: searchDrawer.open() Image { visible: searchField.text !== "" - source: "resources/edit-clear.svg" + source: "qrc:/pdfviewer/resources/edit-clear.svg" anchors { right: parent.right top: parent.top @@ -339,7 +339,7 @@ ApplicationWindow { } ToolButton { action: Action { - icon.source: "resources/go-down-search.svg" + icon.source: "qrc:/pdfviewer/resources/go-down-search.svg" shortcut: StandardKey.FindNext onTriggered: view.searchForward() } diff --git a/examples/pdf/pdfviewer/CMakeLists.txt b/examples/pdf/pdfviewer/CMakeLists.txt new file mode 100644 index 000000000..8265861d0 --- /dev/null +++ b/examples/pdf/pdfviewer/CMakeLists.txt @@ -0,0 +1,62 @@ +cmake_minimum_required(VERSION 3.16) +project(pdfviewer LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/pdf/pdfviewer") + +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Qml) + +qt_add_executable(pdfviewerquick + main.cpp +) +set_target_properties(pdfviewerquick PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) +target_link_libraries(pdfviewerquick PUBLIC + Qt::Gui + Qt::Qml +) + +set(viewer_resource_files + "resources/document-open.svg" + "resources/edit-clear.svg" + "resources/edit-copy.svg" + "resources/edit-select-all.svg" + "resources/go-down-search.svg" + "resources/go-next-view-page.svg" + "resources/go-previous-view-page.svg" + "resources/go-up-search.svg" + "resources/rotate-left.svg" + "resources/rotate-right.svg" + "resources/test.pdf" + "resources/zoom-fit-best.svg" + "resources/zoom-fit-width.svg" + "resources/zoom-in.svg" + "resources/zoom-original.svg" + "resources/zoom-out.svg" + "viewer.qml" +) + +qt6_add_resources(pdfviewerquick "viewer" + PREFIX + "/pdfviewer" + FILES + ${viewer_resource_files} +) + +install(TARGETS pdfviewerquick + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml index 38d62740a..8c85a09da 100644 --- a/examples/pdf/pdfviewer/viewer.qml +++ b/examples/pdf/pdfviewer/viewer.qml @@ -47,15 +47,15 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -import QtQml 2.14 // workaround for QTBUG-82873 -import QtQuick 2.14 -import QtQuick.Controls 2.14 -import QtQuick.Layouts 1.14 -import QtQuick.Pdf 5.15 -import QtQuick.Shapes 1.14 -import QtQuick.Window 2.14 -import Qt.labs.animation 1.0 -import Qt.labs.platform 1.1 as Platform +import QtQml // workaround for QTBUG-82873 +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Pdf +import QtQuick.Shapes +import QtQuick.Window +import Qt.labs.animation +import Qt.labs.platform as Platform ApplicationWindow { id: root @@ -74,7 +74,7 @@ ApplicationWindow { ToolButton { action: Action { shortcut: StandardKey.Open - icon.source: "resources/document-open.svg" + icon.source: "qrc:/pdfviewer/resources/document-open.svg" onTriggered: fileDialog.open() } } @@ -82,7 +82,7 @@ ApplicationWindow { action: Action { shortcut: StandardKey.ZoomIn enabled: view.sourceSize.width < 10000 - icon.source: "resources/zoom-in.svg" + icon.source: "qrc:/pdfviewer/resources/zoom-in.svg" onTriggered: view.renderScale *= root.scaleStep } } @@ -90,46 +90,46 @@ ApplicationWindow { action: Action { shortcut: StandardKey.ZoomOut enabled: view.sourceSize.width > 50 - icon.source: "resources/zoom-out.svg" + icon.source: "qrc:/pdfviewer/resources/zoom-out.svg" onTriggered: view.renderScale /= root.scaleStep } } ToolButton { action: Action { - icon.source: "resources/zoom-fit-width.svg" + icon.source: "qrc:/pdfviewer/resources/zoom-fit-width.svg" onTriggered: view.scaleToWidth(root.contentItem.width, root.contentItem.height) } } ToolButton { action: Action { - icon.source: "resources/zoom-fit-best.svg" + icon.source: "qrc:/pdfviewer/resources/zoom-fit-best.svg" onTriggered: view.scaleToPage(root.contentItem.width, root.contentItem.height) } } ToolButton { action: Action { shortcut: "Ctrl+0" - icon.source: "resources/zoom-original.svg" + icon.source: "qrc:/pdfviewer/resources/zoom-original.svg" onTriggered: view.resetScale() } } ToolButton { action: Action { shortcut: "Ctrl+L" - icon.source: "resources/rotate-left.svg" + icon.source: "qrc:/pdfviewer/resources/rotate-left.svg" onTriggered: view.pageRotation -= 90 } } ToolButton { action: Action { shortcut: "Ctrl+R" - icon.source: "resources/rotate-right.svg" + icon.source: "qrc:/pdfviewer/resources/rotate-right.svg" onTriggered: view.pageRotation += 90 } } ToolButton { action: Action { - icon.source: "resources/go-previous-view-page.svg" + icon.source: "qrc:/pdfviewer/resources/go-previous-view-page.svg" enabled: view.backEnabled onTriggered: view.back() } @@ -155,7 +155,7 @@ ApplicationWindow { } ToolButton { action: Action { - icon.source: "resources/go-next-view-page.svg" + icon.source: "qrc:/pdfviewer/resources/go-next-view-page.svg" enabled: view.forwardEnabled onTriggered: view.forward() } @@ -166,14 +166,14 @@ ApplicationWindow { ToolButton { action: Action { shortcut: StandardKey.SelectAll - icon.source: "resources/edit-select-all.svg" + icon.source: "qrc:/pdfviewer/resources/edit-select-all.svg" onTriggered: view.selectAll() } } ToolButton { action: Action { shortcut: StandardKey.Copy - icon.source: "resources/edit-copy.svg" + icon.source: "qrc:/pdfviewer/resources/edit-copy.svg" enabled: view.selectedText !== "" onTriggered: view.copySelectionToClipboard() } @@ -282,7 +282,7 @@ ApplicationWindow { anchors.fill: parent ToolButton { action: Action { - icon.source: "resources/go-up-search.svg" + icon.source: "qrc:/pdfviewer/resources/go-up-search.svg" shortcut: StandardKey.FindPrevious onTriggered: view.searchBack() } @@ -299,7 +299,7 @@ ApplicationWindow { onAccepted: searchDrawer.open() Image { visible: searchField.text !== "" - source: "resources/edit-clear.svg" + source: "qrc:/pdfviewer/resources/edit-clear.svg" anchors { right: parent.right top: parent.top @@ -314,7 +314,7 @@ ApplicationWindow { } ToolButton { action: Action { - icon.source: "resources/go-down-search.svg" + icon.source: "qrc:/pdfviewer/resources/go-down-search.svg" shortcut: StandardKey.FindNext onTriggered: view.searchForward() } diff --git a/examples/pdfwidgets/CMakeLists.txt b/examples/pdfwidgets/CMakeLists.txt new file mode 100644 index 000000000..37496ebe3 --- /dev/null +++ b/examples/pdfwidgets/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(pdfviewer) diff --git a/examples/pdfwidgets/pdfviewer/CMakeLists.txt b/examples/pdfwidgets/pdfviewer/CMakeLists.txt new file mode 100644 index 000000000..afcbf035a --- /dev/null +++ b/examples/pdfwidgets/pdfviewer/CMakeLists.txt @@ -0,0 +1,63 @@ +# Generated from pdfviewer.pro. + +cmake_minimum_required(VERSION 3.14) +project(pdfviewer LANGUAGES CXX) + +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +if(NOT DEFINED INSTALL_EXAMPLESDIR) + set(INSTALL_EXAMPLESDIR "examples") +endif() + +set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/pdfwidgets/pdfviewer") + +find_package(Qt6 COMPONENTS Core) +find_package(Qt6 COMPONENTS Gui) +find_package(Qt6 COMPONENTS Widgets) + +qt_add_executable(pdfviewerwidgets + main.cpp + mainwindow.cpp mainwindow.h mainwindow.ui + pageselector.cpp pageselector.h + zoomselector.cpp zoomselector.h +) +set_target_properties(pdfviewerwidgets PROPERTIES + WIN32_EXECUTABLE TRUE + MACOSX_BUNDLE TRUE +) +target_link_libraries(pdfviewerwidgets PUBLIC + Qt::Core + Qt::Gui + Qt::Widgets + Qt::PdfWidgets +) + + +# Resources: +set(resources_resource_files + "images/busy.png" + "images/fileopen.png" + "images/go-next-24.png" + "images/go-previous-24.png" + "images/zoom-in-24.png" + "images/zoom-in-32.png" + "images/zoom-out-24.png" + "images/zoom-out-32.png" +) + +qt6_add_resources(pdfviewerwidgets "resources" + PREFIX + "/icons" + FILES + ${resources_resource_files} +) + +install(TARGETS pdfviewerwidgets + RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" + BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" + LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" +) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f46b55f82..2db5f81e7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -23,9 +23,24 @@ set(QT_USE_FIXED_QT_ADD_RESOURCE_BASE TRUE) find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals Core) qt_build_repo_begin() -add_subdirectory(core) -add_subdirectory(process) -add_subdirectory(webenginewidgets) -add_subdirectory(webenginequick) +if(QT_FEATURE_qtwebengine_build) + add_subdirectory(core) + add_subdirectory(process) + if(QT_FEATURE_qtwebengine_widgets_build) + add_subdirectory(webenginewidgets) + endif() + if(QT_FEATURE_qtwebengine_quick_build) + add_subdirectory(webenginequick) + endif() +endif() +if(QT_FEATURE_qtpdf_build) + add_subdirectory(pdf) + if(QT_FEATURE_qtpdf_widgets_build) + add_subdirectory(pdfwidgets) + endif() + if(QT_FEATURE_qtpdf_quick_build) + add_subdirectory(pdfquick) + endif() +endif() qt_build_repo_end() diff --git a/src/host/CMakeLists.txt b/src/host/CMakeLists.txt index 9053d1e59..822fa8a27 100644 --- a/src/host/CMakeLists.txt +++ b/src/host/CMakeLists.txt @@ -36,3 +36,12 @@ if(QT_FEATURE_qtwebengine_build) DESTINATION ${WEBENGINE_ROOT_BUILD_DIR}/src/core/v8_toolchain ) endif() +if(QT_FEATURE_qtpdf_build) + install(FILES ${buildDir}/host_toolchain/BUILD.gn + DESTINATION ${WEBENGINE_ROOT_BUILD_DIR}/src/pdf/host_toolchain + ) + install(FILES ${buildDir}/v8_toolchain/BUILD.gn + DESTINATION ${WEBENGINE_ROOT_BUILD_DIR}/src/pdf/v8_toolchain + ) +endif() + diff --git a/src/pdf/CMakeLists.txt b/src/pdf/CMakeLists.txt new file mode 100644 index 000000000..b639b1243 --- /dev/null +++ b/src/pdf/CMakeLists.txt @@ -0,0 +1,161 @@ +if(NOT DEFINED WEBENGINE_ROOT_SOURCE_DIR) + get_filename_component(WEBENGINE_ROOT_SOURCE_DIR + "${CMAKE_CURRENT_LIST_DIR}/../.." REALPATH + ) +endif() +find_package(Qt6 ${PROJECT_VERSION} REQUIRED COMPONENTS Gui Network OpenGL Quick) +include(${WEBENGINE_ROOT_SOURCE_DIR}/cmake/Functions.cmake) +set(buildDir "${CMAKE_CURRENT_BINARY_DIR}") + +add_subdirectory(plugins/imageformats/pdf) + +qt_internal_add_module(Pdf + SOURCES + qpdfbookmarkmodel.cpp qpdfbookmarkmodel.h + qpdfdestination.cpp qpdfdestination.h qpdfdestination_p.h + qpdfdocument.cpp qpdfdocument.h qpdfdocument_p.h + qpdfdocumentrenderoptions.h + qpdflinkmodel.cpp qpdflinkmodel_p.h qpdflinkmodel_p_p.h + qpdfpagenavigation.cpp qpdfpagenavigation.h + qpdfpagerenderer.cpp qpdfpagerenderer.h + qpdfsearchmodel.cpp qpdfsearchmodel.h qpdfsearchmodel_p.h + qpdfsearchresult.cpp qpdfsearchresult.h qpdfsearchresult_p.h + qpdfselection.cpp qpdfselection.h qpdfselection_p.h + qtpdfglobal.h + qpdfnamespace.h + INCLUDE_DIRECTORIES + ../3rdparty/chromium + DEFINES + QT_BUILD_PDF_LIB + NOMINMAX + LIBRARIES + Qt::CorePrivate + Qt::Network + PUBLIC_LIBRARIES + Qt::Core + Qt::Gui +) + +make_config_for_gn(Pdf gn_config) +make_install_only(Pdf) +qt_internal_add_docs(Pdf + doc/qtpdf.qdocconf +) + +## +# REPO BUILD +## + +if(WEBENGINE_REPO_BUILD) + find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals Core) + find_package(Gn ${QT_REPO_MODULE_VERSION} EXACT REQUIRED) + find_package(Ninja 1.7.2 REQUIRED) + find_package(Python2 2.7.5 REQUIRED) + find_package(Nodejs 10.19 REQUIRED) + find_package(PkgConfig) + if(PkgConfig_FOUND) + create_pkg_config_host_wrapper() + endif() + + ## + # TOOLCHAIN SETUP + ## + + if(LINUX) + setup_toolchains() + endif() + + ## + # MULTICONFIG SETUP + ## + + get_configs(configs) + get_architectures(archs) + + foreach(arch ${archs}) + foreach(config ${configs}) + + ## + # BULID.gn SETUP + ## + + set(buildGn pdf_${config}_${arch}) + add_gn_target(${buildGn} ${config} ${arch} SOURCES DEFINES CXX_COMPILE_OPTIONS C_COMPILE_OPTIONS INCLUDES) + resolve_target_includes(gnIncludes Pdf) + get_forward_declaration_macro(forwardDeclarationMacro) + read_gn_target(${buildGn} ${WEBENGINE_ROOT_BUILD_DIR}/src/pdf/${config}/gn_config.cxx.cmake) + read_gn_target(${buildGn} ${WEBENGINE_ROOT_BUILD_DIR}/src/pdf/${config}/gn_config.c.cmake) + configure_gn_target(${buildGn} ${config} + ${WEBENGINE_ROOT_SOURCE_DIR}/src/pdf/configure/BUILD.root.gn.in ${buildDir}/${config}/${arch}/BUILD.gn) + + ## + # GN PARAMETERS + ## + + unset(gnArgArg) + append_build_type_setup(gnArgArg) + append_compiler_linker_sdk_setup(gnArgArg) + append_sanitizer_setup(gnArgArg) + append_toolchain_setup(gnArgArg) + append_pkg_config_setup(gnArgArg) + + list(APPEND gnArgArg + qtwebengine_target="${buildDir}/${config}/${arch}:QtPdf" + enable_remoting=false + enable_web_speech=false + chrome_pgo_phase=0 + ) + + if(LINUX) + list(APPEND gnArgArg + use_x11=false + is_cfi=false + ozone_auto_platforms=false + use_gnome_keyring=false) + endif() + if(MACOS) + list(APPEND gnArgArg angle_enable_vulkan=false) + endif() + if(WIN32) + list(APPEND gnArgArg + ninja_use_custom_environment_files=false + safe_browsing_mode=0 + ) + endif() + + extend_gn_list(gnArgArg + ARGS pdf_enable_v8 + CONDITION QT_FEATURE_pdf_v8 + ) + extend_gn_list(gnArgArg + ARGS pdf_enable_xfa + CONDITION QT_FEATURE_pdf_xfa + ) + extend_gn_list(gnArgArg + ARGS pdf_enable_xfa_bmp + CONDITION QT_FEATURE_pdf_xfa_bmp + ) + extend_gn_list(gnArgArg + ARGS pdf_enable_xfa_gif + CONDITION QT_FEATURE_pdf_xfa_gif + ) + extend_gn_list(gnArgArg + ARGS pdf_enable_xfa_png + CONDITION QT_FEATURE_pdf_xfa_png + ) + extend_gn_list(gnArgArg + ARGS pdf_enable_xfa_tiff + CONDITION QT_FEATURE_pdf_xfa_tiff + ) + + ## + # GN CALL + ## + + execute_gn(gnArgArg) + endforeach() + endforeach() + set(arch ${CMAKE_SYSTEM_PROCESSOR}) + target_include_directories(Pdf PRIVATE ${buildDir}/$/${arch}/gen) + add_gn_build_aritfacts_to_target(Pdf QtPdf ON ${buildDir}) +endif() diff --git a/src/pdf/api/qpdfbookmarkmodel.h b/src/pdf/api/qpdfbookmarkmodel.h deleted file mode 100644 index 8e06a1547..000000000 --- a/src/pdf/api/qpdfbookmarkmodel.h +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFBOOKMARKMODEL_H -#define QPDFBOOKMARKMODEL_H - -#include -#include - -QT_BEGIN_NAMESPACE - -class QPdfDocument; -class QPdfBookmarkModelPrivate; - -class Q_PDF_EXPORT QPdfBookmarkModel : public QAbstractItemModel -{ - Q_OBJECT - - Q_PROPERTY(QPdfDocument* document READ document WRITE setDocument NOTIFY documentChanged) - Q_PROPERTY(StructureMode structureMode READ structureMode WRITE setStructureMode NOTIFY structureModeChanged) - -public: - enum StructureMode - { - TreeMode, - ListMode - }; - Q_ENUM(StructureMode) - - enum Role - { - TitleRole = Qt::DisplayRole, - LevelRole = Qt::UserRole, - PageNumberRole - }; - Q_ENUM(Role) - - explicit QPdfBookmarkModel(QObject *parent = nullptr); - - QPdfDocument* document() const; - void setDocument(QPdfDocument *document); - - StructureMode structureMode() const; - void setStructureMode(StructureMode mode); - - QVariant data(const QModelIndex &index, int role) const override; - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; - QModelIndex parent(const QModelIndex &index) const override; - int rowCount(const QModelIndex &parent = QModelIndex()) const override; - int columnCount(const QModelIndex &parent = QModelIndex()) const override; - QHash roleNames() const override; - -Q_SIGNALS: - void documentChanged(QPdfDocument *document); - void structureModeChanged(QPdfBookmarkModel::StructureMode structureMode); - -private: - Q_DECLARE_PRIVATE(QPdfBookmarkModel) - - Q_PRIVATE_SLOT(d_func(), void _q_documentStatusChanged()) -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/pdf/api/qpdfdestination.h b/src/pdf/api/qpdfdestination.h deleted file mode 100644 index f9c186ff6..000000000 --- a/src/pdf/api/qpdfdestination.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFDESTINATION_H -#define QPDFDESTINATION_H - -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QPdfDestinationPrivate; - -class Q_PDF_EXPORT QPdfDestination -{ - Q_GADGET - Q_PROPERTY(bool valid READ isValid) - Q_PROPERTY(int page READ page) - Q_PROPERTY(QPointF location READ location) - Q_PROPERTY(qreal zoom READ zoom) - -public: - ~QPdfDestination(); - QPdfDestination(const QPdfDestination &other); - QPdfDestination &operator=(const QPdfDestination &other); - QPdfDestination(QPdfDestination &&other) noexcept; - QPdfDestination &operator=(QPdfDestination &&other) noexcept { swap(other); return *this; } - void swap(QPdfDestination &other) noexcept { d.swap(other.d); } - bool isValid() const; - int page() const; - QPointF location() const; - qreal zoom() const; - -protected: - QPdfDestination(); - QPdfDestination(int page, QPointF location, qreal zoom); - QPdfDestination(QPdfDestinationPrivate *d); - friend class QPdfDocument; - friend class QQuickPdfNavigationStack; - -protected: - QExplicitlySharedDataPointer d; -}; - -Q_PDF_EXPORT QDebug operator<<(QDebug, const QPdfDestination &); - -QT_END_NAMESPACE - -#endif // QPDFDESTINATION_H diff --git a/src/pdf/api/qpdfdestination_p.h b/src/pdf/api/qpdfdestination_p.h deleted file mode 100644 index 3520fb795..000000000 --- a/src/pdf/api/qpdfdestination_p.h +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFDESTINATION_P_H -#define QPDFDESTINATION_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_NAMESPACE - -class QPdfDestinationPrivate : public QSharedData -{ -public: - QPdfDestinationPrivate() = default; - QPdfDestinationPrivate(int page, QPointF location, qreal zoom) - : page(page), - location(location), - zoom(zoom) { } - - int page = -1; - QPointF location; - qreal zoom = 1; -}; - -QT_END_NAMESPACE - -#endif // QPDFDESTINATION_P_H diff --git a/src/pdf/api/qpdfdocument.h b/src/pdf/api/qpdfdocument.h deleted file mode 100644 index 54ca687fa..000000000 --- a/src/pdf/api/qpdfdocument.h +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFDOCUMENT_H -#define QPDFDOCUMENT_H - -#include - -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QPdfDocumentPrivate; -class QNetworkReply; - -class Q_PDF_EXPORT QPdfDocument : public QObject -{ - Q_OBJECT - - Q_PROPERTY(int pageCount READ pageCount NOTIFY pageCountChanged FINAL) - Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged FINAL) - Q_PROPERTY(Status status READ status NOTIFY statusChanged FINAL) - -public: - enum Status { - Null, - Loading, - Ready, - Unloading, - Error - }; - Q_ENUM(Status) - - enum DocumentError { - NoError, - UnknownError, - DataNotYetAvailableError, - FileNotFoundError, - InvalidFileFormatError, - IncorrectPasswordError, - UnsupportedSecuritySchemeError - }; - Q_ENUM(DocumentError) - - enum MetaDataField { - Title, - Subject, - Author, - Keywords, - Producer, - Creator, - CreationDate, - ModificationDate - }; - Q_ENUM(MetaDataField) - - explicit QPdfDocument(QObject *parent = nullptr); - ~QPdfDocument(); - - DocumentError load(const QString &fileName); - - Status status() const; - - void load(QIODevice *device); - void setPassword(const QString &password); - QString password() const; - - QVariant metaData(MetaDataField field) const; - - DocumentError error() const; - - void close(); - - int pageCount() const; - - QSizeF pageSize(int page) const; - - QImage render(int page, QSize imageSize, QPdfDocumentRenderOptions options = QPdfDocumentRenderOptions()); - - Q_INVOKABLE QPdfSelection getSelection(int page, QPointF start, QPointF end); - Q_INVOKABLE QPdfSelection getSelectionAtIndex(int page, int startIndex, int maxLength); - Q_INVOKABLE QPdfSelection getAllText(int page); - -Q_SIGNALS: - void passwordChanged(); - void passwordRequired(); - void statusChanged(QPdfDocument::Status status); - void pageCountChanged(int pageCount); - -private: - friend class QPdfBookmarkModelPrivate; - friend class QPdfLinkModelPrivate; - friend class QPdfSearchModel; - friend class QPdfSearchModelPrivate; - friend class QQuickPdfSelection; - - Q_PRIVATE_SLOT(d, void _q_tryLoadingWithSizeFromContentHeader()) - Q_PRIVATE_SLOT(d, void _q_copyFromSequentialSourceDevice()) - QScopedPointer d; -}; - -QT_END_NAMESPACE - -#endif // QPDFDOCUMENT_H diff --git a/src/pdf/api/qpdfdocument_p.h b/src/pdf/api/qpdfdocument_p.h deleted file mode 100644 index b6ee2dfd0..000000000 --- a/src/pdf/api/qpdfdocument_p.h +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFDOCUMENT_P_H -#define QPDFDOCUMENT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qpdfdocument.h" - -#include "third_party/pdfium/public/fpdfview.h" -#include "third_party/pdfium/public/fpdf_dataavail.h" - -#include -#include -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -class QPdfMutexLocker : public std::unique_lock -{ -public: - QPdfMutexLocker(); -}; - -class Q_PDF_PRIVATE_EXPORT QPdfDocumentPrivate: public FPDF_FILEACCESS, public FX_FILEAVAIL, public FX_DOWNLOADHINTS -{ -public: - QPdfDocumentPrivate(); - ~QPdfDocumentPrivate(); - - QPdfDocument *q; - - FPDF_AVAIL avail; - FPDF_DOCUMENT doc; - bool loadComplete; - - QPointer device; - QScopedPointer ownDevice; - QBuffer asyncBuffer; - QPointer sequentialSourceDevice; - QByteArray password; - - QPdfDocument::Status status; - QPdfDocument::DocumentError lastError; - int pageCount; - - void clear(); - - void load(QIODevice *device, bool ownDevice); - void loadAsync(QIODevice *device); - - void _q_tryLoadingWithSizeFromContentHeader(); - void initiateAsyncLoadWithTotalSizeKnown(quint64 totalSize); - void _q_copyFromSequentialSourceDevice(); - void tryLoadDocument(); - void checkComplete(); - bool checkPageComplete(int page); - void setStatus(QPdfDocument::Status status); - - static FPDF_BOOL fpdf_IsDataAvail(struct _FX_FILEAVAIL* pThis, size_t offset, size_t size); - static int fpdf_GetBlock(void* param, unsigned long position, unsigned char* pBuf, unsigned long size); - static void fpdf_AddSegment(struct _FX_DOWNLOADHINTS* pThis, size_t offset, size_t size); - void updateLastError(); - QString getText(FPDF_TEXTPAGE textPage, int startIndex, int count); - QPointF getCharPosition(FPDF_TEXTPAGE textPage, double pageHeight, int charIndex); - QRectF getCharBox(FPDF_TEXTPAGE textPage, double pageHeight, int charIndex); - - struct TextPosition { - QPointF position; - qreal height = 0; - int charIndex = -1; - }; - TextPosition hitTest(int page, QPointF position); -}; - -QT_END_NAMESPACE - -#endif // QPDFDOCUMENT_P_H diff --git a/src/pdf/api/qpdfdocumentrenderoptions.h b/src/pdf/api/qpdfdocumentrenderoptions.h deleted file mode 100644 index cafb4716f..000000000 --- a/src/pdf/api/qpdfdocumentrenderoptions.h +++ /dev/null @@ -1,94 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias König -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFDOCUMENTRENDEROPTIONS_H -#define QPDFDOCUMENTRENDEROPTIONS_H - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QPdfDocumentRenderOptions -{ -public: - Q_DECL_CONSTEXPR QPdfDocumentRenderOptions() noexcept : m_renderFlags(0), m_rotation(0), m_reserved(0) {} - - Q_DECL_CONSTEXPR QPdf::Rotation rotation() const noexcept { return static_cast(m_rotation); } - Q_DECL_RELAXED_CONSTEXPR void setRotation(QPdf::Rotation r) noexcept { m_rotation = r; } - - Q_DECL_CONSTEXPR QPdf::RenderFlags renderFlags() const noexcept { return static_cast(m_renderFlags); } - Q_DECL_RELAXED_CONSTEXPR void setRenderFlags(QPdf::RenderFlags r) noexcept { m_renderFlags = r; } - - Q_DECL_CONSTEXPR QRect scaledClipRect() const noexcept { return m_clipRect; } - Q_DECL_RELAXED_CONSTEXPR void setScaledClipRect(const QRect &r) noexcept { m_clipRect = r; } - - Q_DECL_CONSTEXPR QSize scaledSize() const noexcept { return m_scaledSize; } - Q_DECL_RELAXED_CONSTEXPR void setScaledSize(const QSize &s) noexcept { m_scaledSize = s; } - -private: - friend Q_DECL_CONSTEXPR inline bool operator==(QPdfDocumentRenderOptions lhs, QPdfDocumentRenderOptions rhs) noexcept; - - QRect m_clipRect; - QSize m_scaledSize; - - quint32 m_renderFlags : 8; - quint32 m_rotation : 3; - quint32 m_reserved : 21; - quint32 m_reserved2 = 0; -}; - -Q_DECLARE_TYPEINFO(QPdfDocumentRenderOptions, Q_PRIMITIVE_TYPE); - -Q_DECL_CONSTEXPR inline bool operator==(QPdfDocumentRenderOptions lhs, QPdfDocumentRenderOptions rhs) noexcept -{ - return lhs.m_clipRect == rhs.m_clipRect && lhs.m_scaledSize == rhs.m_scaledSize && - lhs.m_renderFlags == rhs.m_renderFlags && lhs.m_rotation == rhs.m_rotation && - lhs.m_reserved == rhs.m_reserved && lhs.m_reserved2 == rhs.m_reserved2; // fix -Wunused-private-field -} - -Q_DECL_CONSTEXPR inline bool operator!=(QPdfDocumentRenderOptions lhs, QPdfDocumentRenderOptions rhs) noexcept -{ - return !operator==(lhs, rhs); -} - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QPdfDocumentRenderOptions) - -#endif // QPDFDOCUMENTRENDEROPTIONS_H diff --git a/src/pdf/api/qpdflinkmodel_p.h b/src/pdf/api/qpdflinkmodel_p.h deleted file mode 100644 index cf9c0aad4..000000000 --- a/src/pdf/api/qpdflinkmodel_p.h +++ /dev/null @@ -1,106 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFLINKMODEL_P_H -#define QPDFLINKMODEL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qtpdfglobal.h" -#include "qpdfdocument.h" - -#include -#include - -QT_BEGIN_NAMESPACE - -class QPdfLinkModelPrivate; - -class Q_PDF_EXPORT QPdfLinkModel : public QAbstractListModel -{ - Q_OBJECT - Q_PROPERTY(QPdfDocument *document READ document WRITE setDocument NOTIFY documentChanged) - Q_PROPERTY(int page READ page WRITE setPage NOTIFY pageChanged) - -public: - enum class Role : int { - Rect = Qt::UserRole, - Url, - Page, - Location, - Zoom, - _Count - }; - Q_ENUM(Role) - explicit QPdfLinkModel(QObject *parent = nullptr); - ~QPdfLinkModel(); - - QPdfDocument *document() const; - - QHash roleNames() const override; - int rowCount(const QModelIndex &parent) const override; - QVariant data(const QModelIndex &index, int role) const override; - - int page() const; - -public Q_SLOTS: - void setDocument(QPdfDocument *document); - void setPage(int page); - -Q_SIGNALS: - void documentChanged(); - void pageChanged(int page); - -private Q_SLOTS: - void onStatusChanged(QPdfDocument::Status status); - -private: - QHash m_roleNames; - Q_DECLARE_PRIVATE(QPdfLinkModel) -}; - -QT_END_NAMESPACE - -#endif // QPDFLINKMODEL_P_H diff --git a/src/pdf/api/qpdflinkmodel_p_p.h b/src/pdf/api/qpdflinkmodel_p_p.h deleted file mode 100644 index 0606b4746..000000000 --- a/src/pdf/api/qpdflinkmodel_p_p.h +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFLINKMODEL_P_P_H -#define QPDFLINKMODEL_P_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qpdflinkmodel_p.h" -#include - -#include "third_party/pdfium/public/fpdfview.h" - -#include - -QT_BEGIN_NAMESPACE - -class QPdfLinkModelPrivate: public QAbstractItemModelPrivate -{ - Q_DECLARE_PUBLIC(QPdfLinkModel) - -public: - QPdfLinkModelPrivate(); - - void update(); - - struct Link { - // where it is on the current page - QRectF rect; - int textStart = -1; - int textCharCount = 0; - // destination inside PDF - int page = -1; // -1 means look at the url instead - QPointF location; - qreal zoom = 0; // 0 means no specified zoom: don't change when clicking - // web destination - QUrl url; - - QString toString() const; - }; - - QPdfDocument *document = nullptr; - QList links; - int page = 0; -}; - -QT_END_NAMESPACE - -#endif // QPDFLINKMODEL_P_P_H diff --git a/src/pdf/api/qpdfnamespace.h b/src/pdf/api/qpdfnamespace.h deleted file mode 100644 index e76d0abd9..000000000 --- a/src/pdf/api/qpdfnamespace.h +++ /dev/null @@ -1,73 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias König -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFNAMESPACE_H -#define QPDFNAMESPACE_H - -#include - -QT_BEGIN_NAMESPACE - -namespace QPdf { - Q_NAMESPACE - - enum Rotation { - Rotate0, - Rotate90, - Rotate180, - Rotate270 - }; - Q_ENUM_NS(Rotation) - - enum RenderFlag { - NoRenderFlags = 0x000, - RenderAnnotations = 0x001, - RenderOptimizedForLcd = 0x002, - RenderGrayscale = 0x004, - RenderForceHalftone = 0x008, - RenderTextAliased = 0x010, - RenderImageAliased = 0x020, - RenderPathAliased = 0x040 - }; - Q_FLAG_NS(RenderFlag) - Q_DECLARE_FLAGS(RenderFlags, RenderFlag) -} - -Q_DECLARE_OPERATORS_FOR_FLAGS(QPdf::RenderFlags) - -QT_END_NAMESPACE -#endif diff --git a/src/pdf/api/qpdfpagenavigation.h b/src/pdf/api/qpdfpagenavigation.h deleted file mode 100644 index dc412c33b..000000000 --- a/src/pdf/api/qpdfpagenavigation.h +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias König -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFPAGENAVIGATION_H -#define QPDFPAGENAVIGATION_H - -#include -#include - -QT_BEGIN_NAMESPACE - -class QPdfDocument; -class QPdfPageNavigationPrivate; - -class Q_PDF_EXPORT QPdfPageNavigation : public QObject -{ - Q_OBJECT - - Q_PROPERTY(QPdfDocument* document READ document WRITE setDocument NOTIFY documentChanged) - - Q_PROPERTY(int currentPage READ currentPage WRITE setCurrentPage NOTIFY currentPageChanged) - Q_PROPERTY(int pageCount READ pageCount NOTIFY pageCountChanged) - Q_PROPERTY(bool canGoToPreviousPage READ canGoToPreviousPage NOTIFY canGoToPreviousPageChanged) - Q_PROPERTY(bool canGoToNextPage READ canGoToNextPage NOTIFY canGoToNextPageChanged) - -public: - explicit QPdfPageNavigation(QObject *parent = nullptr); - ~QPdfPageNavigation(); - - QPdfDocument* document() const; - void setDocument(QPdfDocument *document); - - int currentPage() const; - void setCurrentPage(int currentPage); - - int pageCount() const; - - bool canGoToPreviousPage() const; - bool canGoToNextPage() const; - -public Q_SLOTS: - void goToPreviousPage(); - void goToNextPage(); - -Q_SIGNALS: - void documentChanged(QPdfDocument *document); - void currentPageChanged(int currentPage); - void pageCountChanged(int pageCount); - void canGoToPreviousPageChanged(bool canGo); - void canGoToNextPageChanged(bool canGo); - -private: - QScopedPointer d_ptr; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/pdf/api/qpdfpagerenderer.h b/src/pdf/api/qpdfpagerenderer.h deleted file mode 100644 index faeaef8af..000000000 --- a/src/pdf/api/qpdfpagerenderer.h +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias König -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFPAGERENDERER_H -#define QPDFPAGERENDERER_H - -#include - -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QPdfPageRendererPrivate; - -class Q_PDF_EXPORT QPdfPageRenderer : public QObject -{ - Q_OBJECT - - Q_PROPERTY(QPdfDocument* document READ document WRITE setDocument NOTIFY documentChanged) - Q_PROPERTY(RenderMode renderMode READ renderMode WRITE setRenderMode NOTIFY renderModeChanged) - -public: - enum class RenderMode - { - MultiThreaded, - SingleThreaded - }; - Q_ENUM(RenderMode) - - explicit QPdfPageRenderer(QObject *parent = nullptr); - ~QPdfPageRenderer() override; - - RenderMode renderMode() const; - void setRenderMode(RenderMode mode); - - QPdfDocument* document() const; - void setDocument(QPdfDocument *document); - - quint64 requestPage(int pageNumber, QSize imageSize, - QPdfDocumentRenderOptions options = QPdfDocumentRenderOptions()); - -Q_SIGNALS: - void documentChanged(QPdfDocument *document); - void renderModeChanged(RenderMode renderMode); - - void pageRendered(int pageNumber, QSize imageSize, const QImage &image, - QPdfDocumentRenderOptions options, quint64 requestId); - -private: - QScopedPointer d_ptr; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/pdf/api/qpdfsearchmodel.h b/src/pdf/api/qpdfsearchmodel.h deleted file mode 100644 index 1a413c763..000000000 --- a/src/pdf/api/qpdfsearchmodel.h +++ /dev/null @@ -1,98 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFSEARCHMODEL_H -#define QPDFSEARCHMODEL_H - -#include - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QPdfSearchModelPrivate; - -class Q_PDF_EXPORT QPdfSearchModel : public QAbstractListModel -{ - Q_OBJECT - Q_PROPERTY(QPdfDocument *document READ document WRITE setDocument NOTIFY documentChanged) - Q_PROPERTY(QString searchString READ searchString WRITE setSearchString NOTIFY searchStringChanged) - -public: - enum class Role : int { - Page = Qt::UserRole, - IndexOnPage, - Location, - ContextBefore, - ContextAfter, - _Count - }; - Q_ENUM(Role) - explicit QPdfSearchModel(QObject *parent = nullptr); - ~QPdfSearchModel(); - - QList resultsOnPage(int page) const; - QPdfSearchResult resultAtIndex(int index) const; - - QPdfDocument *document() const; - QString searchString() const; - - QHash roleNames() const override; - int rowCount(const QModelIndex &parent) const override; - QVariant data(const QModelIndex &index, int role) const override; - -public Q_SLOTS: - void setSearchString(QString searchString); - void setDocument(QPdfDocument *document); - -Q_SIGNALS: - void documentChanged(); - void searchStringChanged(); - -protected: - void updatePage(int page); - void timerEvent(QTimerEvent *event) override; - -private: - QHash m_roleNames; - Q_DECLARE_PRIVATE(QPdfSearchModel) -}; - -QT_END_NAMESPACE - -#endif // QPDFSEARCHMODEL_H diff --git a/src/pdf/api/qpdfsearchmodel_p.h b/src/pdf/api/qpdfsearchmodel_p.h deleted file mode 100644 index 551eff47c..000000000 --- a/src/pdf/api/qpdfsearchmodel_p.h +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFSEARCHMODEL_P_H -#define QPDFSEARCHMODEL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qpdfsearchmodel.h" -#include "qpdfsearchresult_p.h" -#include - -#include "third_party/pdfium/public/fpdfview.h" - -QT_BEGIN_NAMESPACE - -class QPdfSearchModelPrivate : public QAbstractItemModelPrivate -{ - Q_DECLARE_PUBLIC(QPdfSearchModel) - -public: - QPdfSearchModelPrivate(); - void clearResults(); - bool doSearch(int page); - - struct PageAndIndex { - int page; - int index; - }; - PageAndIndex pageAndIndexForResult(int resultIndex); - int rowsBeforePage(int page); - - QPdfDocument *document = nullptr; - QString searchString; - QList pagesSearched; - QList> searchResults; - int rowCountSoFar = 0; - int updateTimerId = -1; - int nextPageToUpdate = 0; -}; - -QT_END_NAMESPACE - -#endif // QPDFSEARCHMODEL_P_H diff --git a/src/pdf/api/qpdfsearchresult.h b/src/pdf/api/qpdfsearchresult.h deleted file mode 100644 index 0acf03d52..000000000 --- a/src/pdf/api/qpdfsearchresult.h +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFSEARCHRESULT_H -#define QPDFSEARCHRESULT_H - -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QPdfSearchResultPrivate; - -class Q_PDF_EXPORT QPdfSearchResult : public QPdfDestination -{ - Q_GADGET - Q_PROPERTY(QString contextBefore READ contextBefore) - Q_PROPERTY(QString contextAfter READ contextAfter) - Q_PROPERTY(QList rectangles READ rectangles) - -public: - QPdfSearchResult(); - ~QPdfSearchResult() {} - - QString contextBefore() const; - QString contextAfter() const; - QList rectangles() const; - -private: - QPdfSearchResult(int page, QList rects, QString contextBefore, QString contextAfter); - QPdfSearchResult(QPdfSearchResultPrivate *d); - friend class QPdfDocument; - friend class QPdfSearchModelPrivate; - friend class QQuickPdfNavigationStack; -}; - -Q_PDF_EXPORT QDebug operator<<(QDebug, const QPdfSearchResult &); - -QT_END_NAMESPACE - -#endif // QPDFSEARCHRESULT_H diff --git a/src/pdf/api/qpdfsearchresult_p.h b/src/pdf/api/qpdfsearchresult_p.h deleted file mode 100644 index eca37890e..000000000 --- a/src/pdf/api/qpdfsearchresult_p.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFSEARCHRESULT_P_H -#define QPDFSEARCHRESULT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qpdfdestination_p.h" - -QT_BEGIN_NAMESPACE - -class QPdfSearchResultPrivate : public QPdfDestinationPrivate -{ -public: - QPdfSearchResultPrivate() = default; - QPdfSearchResultPrivate(int page, QList rects, QString contextBefore, QString contextAfter) : - QPdfDestinationPrivate(page, rects.first().topLeft(), 0), - contextBefore(contextBefore), - contextAfter(contextAfter), - rects(rects) {} - - QString contextBefore; - QString contextAfter; - QList rects; -}; - -QT_END_NAMESPACE - -#endif // QPDFSEARCHRESULT_P_H diff --git a/src/pdf/api/qpdfselection.h b/src/pdf/api/qpdfselection.h deleted file mode 100644 index 70077fdb0..000000000 --- a/src/pdf/api/qpdfselection.h +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFSELECTION_H -#define QPDFSELECTION_H - -#include - -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QPdfSelectionPrivate; - -class Q_PDF_EXPORT QPdfSelection -{ - Q_GADGET - Q_PROPERTY(bool valid READ isValid) - Q_PROPERTY(QList bounds READ bounds) - Q_PROPERTY(QRectF boundingRectangle READ boundingRectangle) - Q_PROPERTY(QString text READ text) - Q_PROPERTY(int startIndex READ startIndex) - Q_PROPERTY(int endIndex READ endIndex) - -public: - ~QPdfSelection(); - QPdfSelection(const QPdfSelection &other); - QPdfSelection &operator=(const QPdfSelection &other); - QPdfSelection(QPdfSelection &&other) noexcept; - QPdfSelection &operator=(QPdfSelection &&other) noexcept { swap(other); return *this; } - void swap(QPdfSelection &other) noexcept { d.swap(other.d); } - bool isValid() const; - QList bounds() const; - QString text() const; - QRectF boundingRectangle() const; - int startIndex() const; - int endIndex() const; -#if QT_CONFIG(clipboard) - void copyToClipboard(QClipboard::Mode mode = QClipboard::Clipboard) const; -#endif - -private: - QPdfSelection(); - QPdfSelection(const QString &text, QList bounds, QRectF boundingRect, int startIndex, int endIndex); - QPdfSelection(QPdfSelectionPrivate *d); - friend class QPdfDocument; - friend class QQuickPdfSelection; - -private: - QExplicitlySharedDataPointer d; -}; - -QT_END_NAMESPACE - -#endif // QPDFSELECTION_H diff --git a/src/pdf/api/qpdfselection_p.h b/src/pdf/api/qpdfselection_p.h deleted file mode 100644 index 37ca3a3ce..000000000 --- a/src/pdf/api/qpdfselection_p.h +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFSELECTION_P_H -#define QPDFSELECTION_P_H - -#include -#include - -QT_BEGIN_NAMESPACE - -class QPdfSelectionPrivate : public QSharedData -{ -public: - QPdfSelectionPrivate() = default; - QPdfSelectionPrivate(const QString &text, QList bounds, QRectF boundingRect, int startIndex, int endIndex) - : text(text), - bounds(bounds), - boundingRect(boundingRect), - startIndex(startIndex), - endIndex(endIndex) { } - - QString text; - QList bounds; - QRectF boundingRect; - int startIndex; - int endIndex; -}; - -QT_END_NAMESPACE - -#endif // QPDFSELECTION_P_H diff --git a/src/pdf/api/qtpdfglobal.h b/src/pdf/api/qtpdfglobal.h deleted file mode 100644 index 8b4b0c206..000000000 --- a/src/pdf/api/qtpdfglobal.h +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QTPDFGLOBAL_H -#define QTPDFGLOBAL_H - -#include - -QT_BEGIN_NAMESPACE - -#ifndef Q_PDF_EXPORT -# ifndef QT_STATIC -# if defined(QT_BUILD_PDF_LIB) -# define Q_PDF_EXPORT Q_DECL_EXPORT -# else -# define Q_PDF_EXPORT Q_DECL_IMPORT -# endif -# else -# define Q_PDF_EXPORT -# endif -#endif - -#define Q_PDF_PRIVATE_EXPORT Q_PDF_EXPORT - -QT_END_NAMESPACE - -#endif // QTPDFGLOBAL_H - diff --git a/src/pdf/configure.cmake b/src/pdf/configure.cmake new file mode 100644 index 000000000..ce1203205 --- /dev/null +++ b/src/pdf/configure.cmake @@ -0,0 +1,39 @@ +qt_feature("pdf-v8" PRIVATE + LABEL "Support V8" + PURPOSE "Enables javascript support." + AUTODETECT false + CONDITION NOT IOS +) +qt_feature("pdf-xfa" PRIVATE + LABEL "Support XFA" + PURPOSE "Enables XFA support." + CONDITION QT_FEATURE_pdf_v8 +) +qt_feature("pdf-xfa-bmp" PRIVATE + LABEL "Support XFA-BMP" + PURPOSE "Enables XFA-BMP support." + CONDITION QT_FEATURE_pdf_xfa +) +qt_feature("pdf-xfa-gif" PRIVATE + LABEL "Support XFA-GIF" + PURPOSE "Enables XFA-GIF support." + CONDITION QT_FEATURE_pdf_xfa +) +qt_feature("pdf-xfa-png" PRIVATE + LABEL "Support XFA-PNG" + PURPOSE "Enables XFA-PNG support." + CONDITION QT_FEATURE_pdf_xfa +) +qt_feature("pdf-xfa-tiff" PRIVATE + LABEL "Support XFA-TIFF" + PURPOSE "Enables XFA-TIFF support." + CONDITION QT_FEATURE_pdf_xfa +) +qt_configure_add_summary_section(NAME "Qt PDF") +qt_configure_add_summary_entry(ARGS "pdf-v8") +qt_configure_add_summary_entry(ARGS "pdf-xfa") +qt_configure_add_summary_entry(ARGS "pdf-xfa-bmp") +qt_configure_add_summary_entry(ARGS "pdf-xfa-gif") +qt_configure_add_summary_entry(ARGS "pdf-xfa-png") +qt_configure_add_summary_entry(ARGS "pdf-xfa-tiff") +qt_configure_end_summary_section() diff --git a/src/pdf/configure/BUILD.root.gn.in b/src/pdf/configure/BUILD.root.gn.in new file mode 100644 index 000000000..a0cd41747 --- /dev/null +++ b/src/pdf/configure/BUILD.root.gn.in @@ -0,0 +1,36 @@ +config("QtPdf_config") { + cflags = [ + @GN_CFLAGS_C@, + ] + cflags_cc = [ + @GN_CFLAGS_CC@, + ] + defines = [ + @GN_DEFINES@, + ] + include_dirs = [ + @GN_INCLUDE_DIRS@, + rebase_path("${target_gen_dir}/.moc/") + ] +} + +config("cpp17_config") { + # static initialized constexpr expressions must be compiled always as c++14 or always as c++17 + # and our qtwebengine core sources use them as c++17 + if (is_win) { + cflags_cc = [ "/std:c++17" ] + } else { + cflags_cc = [ "-std=c++17" ] + } +} + +shared_library("QtPdf") { + cmake_config = "@GN_CONFIG@" + configs += [ + ":cpp17_config", + ":QtPdf_config" + ] + deps = [ + "//third_party/pdfium" + ] +} diff --git a/src/pdf/jsbridge.cpp b/src/pdf/jsbridge.cpp deleted file mode 100644 index 33d3b2465..000000000 --- a/src/pdf/jsbridge.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "fpdfsdk/javascript/JS_Runtime_Stub.cpp" - diff --git a/src/pdf/plugins/imageformats/pdf/CMakeLists.txt b/src/pdf/plugins/imageformats/pdf/CMakeLists.txt new file mode 100644 index 000000000..8a33e590b --- /dev/null +++ b/src/pdf/plugins/imageformats/pdf/CMakeLists.txt @@ -0,0 +1,11 @@ +qt_internal_add_plugin(QPdfPlugin + OUTPUT_NAME qpdf + TYPE imageformats + SOURCES + main.cpp + qpdfiohandler.cpp qpdfiohandler_p.h + LIBRARIES + Qt::PdfPrivate +) + +make_install_only(QPdfPlugin) diff --git a/src/pdf/plugins/imageformats/pdf/main.cpp b/src/pdf/plugins/imageformats/pdf/main.cpp new file mode 100644 index 000000000..b4d59353c --- /dev/null +++ b/src/pdf/plugins/imageformats/pdf/main.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qpdfiohandler_p.h" + +QT_BEGIN_NAMESPACE + +class QPdfPlugin : public QImageIOPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QImageIOHandlerFactoryInterface_iid FILE "pdf.json") + +public: + Capabilities capabilities(QIODevice *device, const QByteArray &format) const override; + QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override; +}; + +QImageIOPlugin::Capabilities QPdfPlugin::capabilities(QIODevice *device, const QByteArray &format) const +{ + if (format == "pdf") + return Capabilities(CanRead); + if (!format.isEmpty()) + return {}; + + Capabilities cap; + if (device->isReadable() && QPdfIOHandler::canRead(device)) + cap |= CanRead; + return cap; +} + +QImageIOHandler *QPdfPlugin::create(QIODevice *device, const QByteArray &format) const +{ + QPdfIOHandler *hand = new QPdfIOHandler(); + hand->setDevice(device); + hand->setFormat(format); + return hand; +} + +QT_END_NAMESPACE + +#include "main.moc" diff --git a/src/pdf/plugins/imageformats/pdf/pdf.json b/src/pdf/plugins/imageformats/pdf/pdf.json new file mode 100644 index 000000000..1f5268ca1 --- /dev/null +++ b/src/pdf/plugins/imageformats/pdf/pdf.json @@ -0,0 +1,4 @@ +{ + "Keys": [ "pdf" ], + "MimeTypes": [ "application/pdf" ] +} diff --git a/src/pdf/plugins/imageformats/pdf/qpdfiohandler.cpp b/src/pdf/plugins/imageformats/pdf/qpdfiohandler.cpp new file mode 100644 index 000000000..4f610935c --- /dev/null +++ b/src/pdf/plugins/imageformats/pdf/qpdfiohandler.cpp @@ -0,0 +1,239 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qpdfiohandler_p.h" +#include +#include + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(qLcPdf, "qt.imageformat.pdf") + +QPdfIOHandler::QPdfIOHandler() +{ +} + +bool QPdfIOHandler::canRead() const +{ + if (!device()) + return false; + if (m_loaded) + return true; + if (QPdfIOHandler::canRead(device())) { + setFormat("pdf"); + return true; + } + return false; +} + +bool QPdfIOHandler::canRead(QIODevice *device) +{ + char buf[6]; + device->peek(buf, 6); + return (!qstrncmp(buf, "%PDF-", 5) || Q_UNLIKELY(!qstrncmp(buf, "\012%PDF-", 6))); +} + +int QPdfIOHandler::currentImageNumber() const +{ + return m_page; +} + +QRect QPdfIOHandler::currentImageRect() const +{ + return QRect(QPoint(0, 0), m_doc.pageSize(m_page).toSize()); +} + +int QPdfIOHandler::imageCount() const +{ + int ret = 0; + if (const_cast(this)->load(device())) + ret = m_doc.pageCount(); + qCDebug(qLcPdf) << "imageCount" << ret; + return ret; +} + +bool QPdfIOHandler::read(QImage *image) +{ + if (load(device())) { + if (m_page >= m_doc.pageCount()) + return false; + if (m_page < 0) + m_page = 0; + const bool xform = (m_clipRect.isValid() || m_scaledSize.isValid() || m_scaledClipRect.isValid()); + QSize pageSize = m_doc.pageSize(m_page).toSize(); + QSize finalSize = pageSize; + QRectF bounds; + if (xform && !finalSize.isEmpty()) { + bounds = QRectF(QPointF(0,0), QSizeF(finalSize)); + QPoint tr1, tr2; + QSizeF sc(1, 1); + if (m_clipRect.isValid()) { + tr1 = -m_clipRect.topLeft(); + finalSize = m_clipRect.size(); + } + if (m_scaledSize.isValid()) { + sc = QSizeF(qreal(m_scaledSize.width()) / finalSize.width(), + qreal(m_scaledSize.height()) / finalSize.height()); + finalSize = m_scaledSize; + pageSize = m_scaledSize; + } + if (m_scaledClipRect.isValid()) { + tr2 = -m_scaledClipRect.topLeft(); + finalSize = m_scaledClipRect.size(); + } + QTransform t; + t.translate(tr2.x(), tr2.y()); + t.scale(sc.width(), sc.height()); + t.translate(tr1.x(), tr1.y()); + bounds = t.mapRect(bounds); + } + qCDebug(qLcPdf) << Q_FUNC_INFO << m_page << finalSize; + if (image->size() != finalSize || !image->reinterpretAsFormat(QImage::Format_ARGB32_Premultiplied)) { + *image = QImage(finalSize, QImage::Format_ARGB32_Premultiplied); + if (!finalSize.isEmpty() && image->isNull()) { + // avoid QTBUG-68229 + qWarning("QPdfIOHandler: QImage allocation failed (size %i x %i)", finalSize.width(), finalSize.height()); + return false; + } + } + if (!finalSize.isEmpty()) { + QPdfDocumentRenderOptions options; + if (m_scaledClipRect.isValid()) + options.setScaledClipRect(m_scaledClipRect); + options.setScaledSize(pageSize); + image->fill(m_backColor.rgba()); + QPainter p(image); + QImage pageImage = m_doc.render(m_page, finalSize, options); + p.drawImage(0, 0, pageImage); + p.end(); + } + return true; + } + + return false; +} + +QVariant QPdfIOHandler::option(ImageOption option) const +{ + switch (option) { + case ImageFormat: + return QImage::Format_ARGB32_Premultiplied; + case Size: + const_cast(this)->load(device()); + return m_doc.pageSize(qMax(0, m_page)); + case ClipRect: + return m_clipRect; + case ScaledSize: + return m_scaledSize; + case ScaledClipRect: + return m_scaledClipRect; + case BackgroundColor: + return m_backColor; + case Name: + return m_doc.metaData(QPdfDocument::Title); + default: + break; + } + return QVariant(); +} + +void QPdfIOHandler::setOption(ImageOption option, const QVariant & value) +{ + switch (option) { + case ClipRect: + m_clipRect = value.toRect(); + break; + case ScaledSize: + m_scaledSize = value.toSize(); + break; + case ScaledClipRect: + m_scaledClipRect = value.toRect(); + break; + case BackgroundColor: + m_backColor = value.value(); + break; + default: + break; + } +} + +bool QPdfIOHandler::supportsOption(ImageOption option) const +{ + switch (option) + { + case ImageFormat: + case Size: + case ClipRect: + case ScaledSize: + case ScaledClipRect: + case BackgroundColor: + case Name: + return true; + default: + break; + } + return false; +} + +bool QPdfIOHandler::jumpToImage(int frame) +{ + qCDebug(qLcPdf) << Q_FUNC_INFO << frame; + if (frame < 0 || frame >= imageCount()) + return false; + m_page = frame; + return true; +} + +bool QPdfIOHandler::jumpToNextImage() +{ + return jumpToImage(m_page + 1); +} + +bool QPdfIOHandler::load(QIODevice *device) +{ + if (m_loaded) + return true; + if (format().isEmpty()) + if (!canRead()) + return false; + + m_doc.load(device); + m_loaded = (m_doc.error() == QPdfDocument::DocumentError::NoError); + + return m_loaded; +} + +QT_END_NAMESPACE diff --git a/src/pdf/plugins/imageformats/pdf/qpdfiohandler_p.h b/src/pdf/plugins/imageformats/pdf/qpdfiohandler_p.h new file mode 100644 index 000000000..99a91154c --- /dev/null +++ b/src/pdf/plugins/imageformats/pdf/qpdfiohandler_p.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFIOHANDLER_H +#define QPDFIOHANDLER_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPdfIOHandler : public QImageIOHandler +{ +public: + QPdfIOHandler(); + bool canRead() const override; + static bool canRead(QIODevice *device); + int currentImageNumber() const override; + QRect currentImageRect() const override; + int imageCount() const override; + bool read(QImage *image) override; + QVariant option(ImageOption option) const override; + void setOption(ImageOption option, const QVariant & value) override; + bool supportsOption(ImageOption option) const override; + bool jumpToImage(int frame) override; + bool jumpToNextImage() override; + +private: + bool load(QIODevice *device); + +private: + QPdfDocument m_doc; + int m_page = -1; + + QRect m_clipRect; + QSize m_scaledSize; + QRect m_scaledClipRect; + QColor m_backColor = Qt::transparent; + bool m_loaded = false; +}; + +QT_END_NAMESPACE + +#endif // QPDFIOHANDLER_H diff --git a/src/pdf/qpdfbookmarkmodel.cpp b/src/pdf/qpdfbookmarkmodel.cpp index b0e8bbecd..0450870a1 100644 --- a/src/pdf/qpdfbookmarkmodel.cpp +++ b/src/pdf/qpdfbookmarkmodel.cpp @@ -272,6 +272,7 @@ void QPdfBookmarkModel::setStructureMode(StructureMode mode) int QPdfBookmarkModel::columnCount(const QModelIndex &parent) const { + Q_UNUSED(parent); return 1; } diff --git a/src/pdf/qpdfbookmarkmodel.h b/src/pdf/qpdfbookmarkmodel.h new file mode 100644 index 000000000..8e06a1547 --- /dev/null +++ b/src/pdf/qpdfbookmarkmodel.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFBOOKMARKMODEL_H +#define QPDFBOOKMARKMODEL_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPdfDocument; +class QPdfBookmarkModelPrivate; + +class Q_PDF_EXPORT QPdfBookmarkModel : public QAbstractItemModel +{ + Q_OBJECT + + Q_PROPERTY(QPdfDocument* document READ document WRITE setDocument NOTIFY documentChanged) + Q_PROPERTY(StructureMode structureMode READ structureMode WRITE setStructureMode NOTIFY structureModeChanged) + +public: + enum StructureMode + { + TreeMode, + ListMode + }; + Q_ENUM(StructureMode) + + enum Role + { + TitleRole = Qt::DisplayRole, + LevelRole = Qt::UserRole, + PageNumberRole + }; + Q_ENUM(Role) + + explicit QPdfBookmarkModel(QObject *parent = nullptr); + + QPdfDocument* document() const; + void setDocument(QPdfDocument *document); + + StructureMode structureMode() const; + void setStructureMode(StructureMode mode); + + QVariant data(const QModelIndex &index, int role) const override; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex &index) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QHash roleNames() const override; + +Q_SIGNALS: + void documentChanged(QPdfDocument *document); + void structureModeChanged(QPdfBookmarkModel::StructureMode structureMode); + +private: + Q_DECLARE_PRIVATE(QPdfBookmarkModel) + + Q_PRIVATE_SLOT(d_func(), void _q_documentStatusChanged()) +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/pdf/qpdfdestination.h b/src/pdf/qpdfdestination.h new file mode 100644 index 000000000..f9c186ff6 --- /dev/null +++ b/src/pdf/qpdfdestination.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFDESTINATION_H +#define QPDFDESTINATION_H + +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPdfDestinationPrivate; + +class Q_PDF_EXPORT QPdfDestination +{ + Q_GADGET + Q_PROPERTY(bool valid READ isValid) + Q_PROPERTY(int page READ page) + Q_PROPERTY(QPointF location READ location) + Q_PROPERTY(qreal zoom READ zoom) + +public: + ~QPdfDestination(); + QPdfDestination(const QPdfDestination &other); + QPdfDestination &operator=(const QPdfDestination &other); + QPdfDestination(QPdfDestination &&other) noexcept; + QPdfDestination &operator=(QPdfDestination &&other) noexcept { swap(other); return *this; } + void swap(QPdfDestination &other) noexcept { d.swap(other.d); } + bool isValid() const; + int page() const; + QPointF location() const; + qreal zoom() const; + +protected: + QPdfDestination(); + QPdfDestination(int page, QPointF location, qreal zoom); + QPdfDestination(QPdfDestinationPrivate *d); + friend class QPdfDocument; + friend class QQuickPdfNavigationStack; + +protected: + QExplicitlySharedDataPointer d; +}; + +Q_PDF_EXPORT QDebug operator<<(QDebug, const QPdfDestination &); + +QT_END_NAMESPACE + +#endif // QPDFDESTINATION_H diff --git a/src/pdf/qpdfdestination_p.h b/src/pdf/qpdfdestination_p.h new file mode 100644 index 000000000..3520fb795 --- /dev/null +++ b/src/pdf/qpdfdestination_p.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFDESTINATION_P_H +#define QPDFDESTINATION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_NAMESPACE + +class QPdfDestinationPrivate : public QSharedData +{ +public: + QPdfDestinationPrivate() = default; + QPdfDestinationPrivate(int page, QPointF location, qreal zoom) + : page(page), + location(location), + zoom(zoom) { } + + int page = -1; + QPointF location; + qreal zoom = 1; +}; + +QT_END_NAMESPACE + +#endif // QPDFDESTINATION_P_H diff --git a/src/pdf/qpdfdocument.h b/src/pdf/qpdfdocument.h new file mode 100644 index 000000000..54ca687fa --- /dev/null +++ b/src/pdf/qpdfdocument.h @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFDOCUMENT_H +#define QPDFDOCUMENT_H + +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPdfDocumentPrivate; +class QNetworkReply; + +class Q_PDF_EXPORT QPdfDocument : public QObject +{ + Q_OBJECT + + Q_PROPERTY(int pageCount READ pageCount NOTIFY pageCountChanged FINAL) + Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged FINAL) + Q_PROPERTY(Status status READ status NOTIFY statusChanged FINAL) + +public: + enum Status { + Null, + Loading, + Ready, + Unloading, + Error + }; + Q_ENUM(Status) + + enum DocumentError { + NoError, + UnknownError, + DataNotYetAvailableError, + FileNotFoundError, + InvalidFileFormatError, + IncorrectPasswordError, + UnsupportedSecuritySchemeError + }; + Q_ENUM(DocumentError) + + enum MetaDataField { + Title, + Subject, + Author, + Keywords, + Producer, + Creator, + CreationDate, + ModificationDate + }; + Q_ENUM(MetaDataField) + + explicit QPdfDocument(QObject *parent = nullptr); + ~QPdfDocument(); + + DocumentError load(const QString &fileName); + + Status status() const; + + void load(QIODevice *device); + void setPassword(const QString &password); + QString password() const; + + QVariant metaData(MetaDataField field) const; + + DocumentError error() const; + + void close(); + + int pageCount() const; + + QSizeF pageSize(int page) const; + + QImage render(int page, QSize imageSize, QPdfDocumentRenderOptions options = QPdfDocumentRenderOptions()); + + Q_INVOKABLE QPdfSelection getSelection(int page, QPointF start, QPointF end); + Q_INVOKABLE QPdfSelection getSelectionAtIndex(int page, int startIndex, int maxLength); + Q_INVOKABLE QPdfSelection getAllText(int page); + +Q_SIGNALS: + void passwordChanged(); + void passwordRequired(); + void statusChanged(QPdfDocument::Status status); + void pageCountChanged(int pageCount); + +private: + friend class QPdfBookmarkModelPrivate; + friend class QPdfLinkModelPrivate; + friend class QPdfSearchModel; + friend class QPdfSearchModelPrivate; + friend class QQuickPdfSelection; + + Q_PRIVATE_SLOT(d, void _q_tryLoadingWithSizeFromContentHeader()) + Q_PRIVATE_SLOT(d, void _q_copyFromSequentialSourceDevice()) + QScopedPointer d; +}; + +QT_END_NAMESPACE + +#endif // QPDFDOCUMENT_H diff --git a/src/pdf/qpdfdocument_p.h b/src/pdf/qpdfdocument_p.h new file mode 100644 index 000000000..b6ee2dfd0 --- /dev/null +++ b/src/pdf/qpdfdocument_p.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFDOCUMENT_P_H +#define QPDFDOCUMENT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qpdfdocument.h" + +#include "third_party/pdfium/public/fpdfview.h" +#include "third_party/pdfium/public/fpdf_dataavail.h" + +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QPdfMutexLocker : public std::unique_lock +{ +public: + QPdfMutexLocker(); +}; + +class Q_PDF_PRIVATE_EXPORT QPdfDocumentPrivate: public FPDF_FILEACCESS, public FX_FILEAVAIL, public FX_DOWNLOADHINTS +{ +public: + QPdfDocumentPrivate(); + ~QPdfDocumentPrivate(); + + QPdfDocument *q; + + FPDF_AVAIL avail; + FPDF_DOCUMENT doc; + bool loadComplete; + + QPointer device; + QScopedPointer ownDevice; + QBuffer asyncBuffer; + QPointer sequentialSourceDevice; + QByteArray password; + + QPdfDocument::Status status; + QPdfDocument::DocumentError lastError; + int pageCount; + + void clear(); + + void load(QIODevice *device, bool ownDevice); + void loadAsync(QIODevice *device); + + void _q_tryLoadingWithSizeFromContentHeader(); + void initiateAsyncLoadWithTotalSizeKnown(quint64 totalSize); + void _q_copyFromSequentialSourceDevice(); + void tryLoadDocument(); + void checkComplete(); + bool checkPageComplete(int page); + void setStatus(QPdfDocument::Status status); + + static FPDF_BOOL fpdf_IsDataAvail(struct _FX_FILEAVAIL* pThis, size_t offset, size_t size); + static int fpdf_GetBlock(void* param, unsigned long position, unsigned char* pBuf, unsigned long size); + static void fpdf_AddSegment(struct _FX_DOWNLOADHINTS* pThis, size_t offset, size_t size); + void updateLastError(); + QString getText(FPDF_TEXTPAGE textPage, int startIndex, int count); + QPointF getCharPosition(FPDF_TEXTPAGE textPage, double pageHeight, int charIndex); + QRectF getCharBox(FPDF_TEXTPAGE textPage, double pageHeight, int charIndex); + + struct TextPosition { + QPointF position; + qreal height = 0; + int charIndex = -1; + }; + TextPosition hitTest(int page, QPointF position); +}; + +QT_END_NAMESPACE + +#endif // QPDFDOCUMENT_P_H diff --git a/src/pdf/qpdfdocumentrenderoptions.h b/src/pdf/qpdfdocumentrenderoptions.h new file mode 100644 index 000000000..cafb4716f --- /dev/null +++ b/src/pdf/qpdfdocumentrenderoptions.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias König +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFDOCUMENTRENDEROPTIONS_H +#define QPDFDOCUMENTRENDEROPTIONS_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPdfDocumentRenderOptions +{ +public: + Q_DECL_CONSTEXPR QPdfDocumentRenderOptions() noexcept : m_renderFlags(0), m_rotation(0), m_reserved(0) {} + + Q_DECL_CONSTEXPR QPdf::Rotation rotation() const noexcept { return static_cast(m_rotation); } + Q_DECL_RELAXED_CONSTEXPR void setRotation(QPdf::Rotation r) noexcept { m_rotation = r; } + + Q_DECL_CONSTEXPR QPdf::RenderFlags renderFlags() const noexcept { return static_cast(m_renderFlags); } + Q_DECL_RELAXED_CONSTEXPR void setRenderFlags(QPdf::RenderFlags r) noexcept { m_renderFlags = r; } + + Q_DECL_CONSTEXPR QRect scaledClipRect() const noexcept { return m_clipRect; } + Q_DECL_RELAXED_CONSTEXPR void setScaledClipRect(const QRect &r) noexcept { m_clipRect = r; } + + Q_DECL_CONSTEXPR QSize scaledSize() const noexcept { return m_scaledSize; } + Q_DECL_RELAXED_CONSTEXPR void setScaledSize(const QSize &s) noexcept { m_scaledSize = s; } + +private: + friend Q_DECL_CONSTEXPR inline bool operator==(QPdfDocumentRenderOptions lhs, QPdfDocumentRenderOptions rhs) noexcept; + + QRect m_clipRect; + QSize m_scaledSize; + + quint32 m_renderFlags : 8; + quint32 m_rotation : 3; + quint32 m_reserved : 21; + quint32 m_reserved2 = 0; +}; + +Q_DECLARE_TYPEINFO(QPdfDocumentRenderOptions, Q_PRIMITIVE_TYPE); + +Q_DECL_CONSTEXPR inline bool operator==(QPdfDocumentRenderOptions lhs, QPdfDocumentRenderOptions rhs) noexcept +{ + return lhs.m_clipRect == rhs.m_clipRect && lhs.m_scaledSize == rhs.m_scaledSize && + lhs.m_renderFlags == rhs.m_renderFlags && lhs.m_rotation == rhs.m_rotation && + lhs.m_reserved == rhs.m_reserved && lhs.m_reserved2 == rhs.m_reserved2; // fix -Wunused-private-field +} + +Q_DECL_CONSTEXPR inline bool operator!=(QPdfDocumentRenderOptions lhs, QPdfDocumentRenderOptions rhs) noexcept +{ + return !operator==(lhs, rhs); +} + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QPdfDocumentRenderOptions) + +#endif // QPDFDOCUMENTRENDEROPTIONS_H diff --git a/src/pdf/qpdflinkmodel_p.h b/src/pdf/qpdflinkmodel_p.h new file mode 100644 index 000000000..cf9c0aad4 --- /dev/null +++ b/src/pdf/qpdflinkmodel_p.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFLINKMODEL_P_H +#define QPDFLINKMODEL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qtpdfglobal.h" +#include "qpdfdocument.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPdfLinkModelPrivate; + +class Q_PDF_EXPORT QPdfLinkModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(QPdfDocument *document READ document WRITE setDocument NOTIFY documentChanged) + Q_PROPERTY(int page READ page WRITE setPage NOTIFY pageChanged) + +public: + enum class Role : int { + Rect = Qt::UserRole, + Url, + Page, + Location, + Zoom, + _Count + }; + Q_ENUM(Role) + explicit QPdfLinkModel(QObject *parent = nullptr); + ~QPdfLinkModel(); + + QPdfDocument *document() const; + + QHash roleNames() const override; + int rowCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role) const override; + + int page() const; + +public Q_SLOTS: + void setDocument(QPdfDocument *document); + void setPage(int page); + +Q_SIGNALS: + void documentChanged(); + void pageChanged(int page); + +private Q_SLOTS: + void onStatusChanged(QPdfDocument::Status status); + +private: + QHash m_roleNames; + Q_DECLARE_PRIVATE(QPdfLinkModel) +}; + +QT_END_NAMESPACE + +#endif // QPDFLINKMODEL_P_H diff --git a/src/pdf/qpdflinkmodel_p_p.h b/src/pdf/qpdflinkmodel_p_p.h new file mode 100644 index 000000000..0606b4746 --- /dev/null +++ b/src/pdf/qpdflinkmodel_p_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFLINKMODEL_P_P_H +#define QPDFLINKMODEL_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qpdflinkmodel_p.h" +#include + +#include "third_party/pdfium/public/fpdfview.h" + +#include + +QT_BEGIN_NAMESPACE + +class QPdfLinkModelPrivate: public QAbstractItemModelPrivate +{ + Q_DECLARE_PUBLIC(QPdfLinkModel) + +public: + QPdfLinkModelPrivate(); + + void update(); + + struct Link { + // where it is on the current page + QRectF rect; + int textStart = -1; + int textCharCount = 0; + // destination inside PDF + int page = -1; // -1 means look at the url instead + QPointF location; + qreal zoom = 0; // 0 means no specified zoom: don't change when clicking + // web destination + QUrl url; + + QString toString() const; + }; + + QPdfDocument *document = nullptr; + QList links; + int page = 0; +}; + +QT_END_NAMESPACE + +#endif // QPDFLINKMODEL_P_P_H diff --git a/src/pdf/qpdfnamespace.h b/src/pdf/qpdfnamespace.h new file mode 100644 index 000000000..e76d0abd9 --- /dev/null +++ b/src/pdf/qpdfnamespace.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias König +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFNAMESPACE_H +#define QPDFNAMESPACE_H + +#include + +QT_BEGIN_NAMESPACE + +namespace QPdf { + Q_NAMESPACE + + enum Rotation { + Rotate0, + Rotate90, + Rotate180, + Rotate270 + }; + Q_ENUM_NS(Rotation) + + enum RenderFlag { + NoRenderFlags = 0x000, + RenderAnnotations = 0x001, + RenderOptimizedForLcd = 0x002, + RenderGrayscale = 0x004, + RenderForceHalftone = 0x008, + RenderTextAliased = 0x010, + RenderImageAliased = 0x020, + RenderPathAliased = 0x040 + }; + Q_FLAG_NS(RenderFlag) + Q_DECLARE_FLAGS(RenderFlags, RenderFlag) +} + +Q_DECLARE_OPERATORS_FOR_FLAGS(QPdf::RenderFlags) + +QT_END_NAMESPACE +#endif diff --git a/src/pdf/qpdfpagenavigation.h b/src/pdf/qpdfpagenavigation.h new file mode 100644 index 000000000..dc412c33b --- /dev/null +++ b/src/pdf/qpdfpagenavigation.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias König +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFPAGENAVIGATION_H +#define QPDFPAGENAVIGATION_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPdfDocument; +class QPdfPageNavigationPrivate; + +class Q_PDF_EXPORT QPdfPageNavigation : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QPdfDocument* document READ document WRITE setDocument NOTIFY documentChanged) + + Q_PROPERTY(int currentPage READ currentPage WRITE setCurrentPage NOTIFY currentPageChanged) + Q_PROPERTY(int pageCount READ pageCount NOTIFY pageCountChanged) + Q_PROPERTY(bool canGoToPreviousPage READ canGoToPreviousPage NOTIFY canGoToPreviousPageChanged) + Q_PROPERTY(bool canGoToNextPage READ canGoToNextPage NOTIFY canGoToNextPageChanged) + +public: + explicit QPdfPageNavigation(QObject *parent = nullptr); + ~QPdfPageNavigation(); + + QPdfDocument* document() const; + void setDocument(QPdfDocument *document); + + int currentPage() const; + void setCurrentPage(int currentPage); + + int pageCount() const; + + bool canGoToPreviousPage() const; + bool canGoToNextPage() const; + +public Q_SLOTS: + void goToPreviousPage(); + void goToNextPage(); + +Q_SIGNALS: + void documentChanged(QPdfDocument *document); + void currentPageChanged(int currentPage); + void pageCountChanged(int pageCount); + void canGoToPreviousPageChanged(bool canGo); + void canGoToNextPageChanged(bool canGo); + +private: + QScopedPointer d_ptr; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/pdf/qpdfpagerenderer.h b/src/pdf/qpdfpagerenderer.h new file mode 100644 index 000000000..faeaef8af --- /dev/null +++ b/src/pdf/qpdfpagerenderer.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias König +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFPAGERENDERER_H +#define QPDFPAGERENDERER_H + +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPdfPageRendererPrivate; + +class Q_PDF_EXPORT QPdfPageRenderer : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QPdfDocument* document READ document WRITE setDocument NOTIFY documentChanged) + Q_PROPERTY(RenderMode renderMode READ renderMode WRITE setRenderMode NOTIFY renderModeChanged) + +public: + enum class RenderMode + { + MultiThreaded, + SingleThreaded + }; + Q_ENUM(RenderMode) + + explicit QPdfPageRenderer(QObject *parent = nullptr); + ~QPdfPageRenderer() override; + + RenderMode renderMode() const; + void setRenderMode(RenderMode mode); + + QPdfDocument* document() const; + void setDocument(QPdfDocument *document); + + quint64 requestPage(int pageNumber, QSize imageSize, + QPdfDocumentRenderOptions options = QPdfDocumentRenderOptions()); + +Q_SIGNALS: + void documentChanged(QPdfDocument *document); + void renderModeChanged(RenderMode renderMode); + + void pageRendered(int pageNumber, QSize imageSize, const QImage &image, + QPdfDocumentRenderOptions options, quint64 requestId); + +private: + QScopedPointer d_ptr; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/pdf/qpdfsearchmodel.h b/src/pdf/qpdfsearchmodel.h new file mode 100644 index 000000000..1a413c763 --- /dev/null +++ b/src/pdf/qpdfsearchmodel.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFSEARCHMODEL_H +#define QPDFSEARCHMODEL_H + +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPdfSearchModelPrivate; + +class Q_PDF_EXPORT QPdfSearchModel : public QAbstractListModel +{ + Q_OBJECT + Q_PROPERTY(QPdfDocument *document READ document WRITE setDocument NOTIFY documentChanged) + Q_PROPERTY(QString searchString READ searchString WRITE setSearchString NOTIFY searchStringChanged) + +public: + enum class Role : int { + Page = Qt::UserRole, + IndexOnPage, + Location, + ContextBefore, + ContextAfter, + _Count + }; + Q_ENUM(Role) + explicit QPdfSearchModel(QObject *parent = nullptr); + ~QPdfSearchModel(); + + QList resultsOnPage(int page) const; + QPdfSearchResult resultAtIndex(int index) const; + + QPdfDocument *document() const; + QString searchString() const; + + QHash roleNames() const override; + int rowCount(const QModelIndex &parent) const override; + QVariant data(const QModelIndex &index, int role) const override; + +public Q_SLOTS: + void setSearchString(QString searchString); + void setDocument(QPdfDocument *document); + +Q_SIGNALS: + void documentChanged(); + void searchStringChanged(); + +protected: + void updatePage(int page); + void timerEvent(QTimerEvent *event) override; + +private: + QHash m_roleNames; + Q_DECLARE_PRIVATE(QPdfSearchModel) +}; + +QT_END_NAMESPACE + +#endif // QPDFSEARCHMODEL_H diff --git a/src/pdf/qpdfsearchmodel_p.h b/src/pdf/qpdfsearchmodel_p.h new file mode 100644 index 000000000..551eff47c --- /dev/null +++ b/src/pdf/qpdfsearchmodel_p.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFSEARCHMODEL_P_H +#define QPDFSEARCHMODEL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qpdfsearchmodel.h" +#include "qpdfsearchresult_p.h" +#include + +#include "third_party/pdfium/public/fpdfview.h" + +QT_BEGIN_NAMESPACE + +class QPdfSearchModelPrivate : public QAbstractItemModelPrivate +{ + Q_DECLARE_PUBLIC(QPdfSearchModel) + +public: + QPdfSearchModelPrivate(); + void clearResults(); + bool doSearch(int page); + + struct PageAndIndex { + int page; + int index; + }; + PageAndIndex pageAndIndexForResult(int resultIndex); + int rowsBeforePage(int page); + + QPdfDocument *document = nullptr; + QString searchString; + QList pagesSearched; + QList> searchResults; + int rowCountSoFar = 0; + int updateTimerId = -1; + int nextPageToUpdate = 0; +}; + +QT_END_NAMESPACE + +#endif // QPDFSEARCHMODEL_P_H diff --git a/src/pdf/qpdfsearchresult.h b/src/pdf/qpdfsearchresult.h new file mode 100644 index 000000000..0acf03d52 --- /dev/null +++ b/src/pdf/qpdfsearchresult.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFSEARCHRESULT_H +#define QPDFSEARCHRESULT_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPdfSearchResultPrivate; + +class Q_PDF_EXPORT QPdfSearchResult : public QPdfDestination +{ + Q_GADGET + Q_PROPERTY(QString contextBefore READ contextBefore) + Q_PROPERTY(QString contextAfter READ contextAfter) + Q_PROPERTY(QList rectangles READ rectangles) + +public: + QPdfSearchResult(); + ~QPdfSearchResult() {} + + QString contextBefore() const; + QString contextAfter() const; + QList rectangles() const; + +private: + QPdfSearchResult(int page, QList rects, QString contextBefore, QString contextAfter); + QPdfSearchResult(QPdfSearchResultPrivate *d); + friend class QPdfDocument; + friend class QPdfSearchModelPrivate; + friend class QQuickPdfNavigationStack; +}; + +Q_PDF_EXPORT QDebug operator<<(QDebug, const QPdfSearchResult &); + +QT_END_NAMESPACE + +#endif // QPDFSEARCHRESULT_H diff --git a/src/pdf/qpdfsearchresult_p.h b/src/pdf/qpdfsearchresult_p.h new file mode 100644 index 000000000..eca37890e --- /dev/null +++ b/src/pdf/qpdfsearchresult_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFSEARCHRESULT_P_H +#define QPDFSEARCHRESULT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qpdfdestination_p.h" + +QT_BEGIN_NAMESPACE + +class QPdfSearchResultPrivate : public QPdfDestinationPrivate +{ +public: + QPdfSearchResultPrivate() = default; + QPdfSearchResultPrivate(int page, QList rects, QString contextBefore, QString contextAfter) : + QPdfDestinationPrivate(page, rects.first().topLeft(), 0), + contextBefore(contextBefore), + contextAfter(contextAfter), + rects(rects) {} + + QString contextBefore; + QString contextAfter; + QList rects; +}; + +QT_END_NAMESPACE + +#endif // QPDFSEARCHRESULT_P_H diff --git a/src/pdf/qpdfselection.h b/src/pdf/qpdfselection.h new file mode 100644 index 000000000..70077fdb0 --- /dev/null +++ b/src/pdf/qpdfselection.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFSELECTION_H +#define QPDFSELECTION_H + +#include + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QPdfSelectionPrivate; + +class Q_PDF_EXPORT QPdfSelection +{ + Q_GADGET + Q_PROPERTY(bool valid READ isValid) + Q_PROPERTY(QList bounds READ bounds) + Q_PROPERTY(QRectF boundingRectangle READ boundingRectangle) + Q_PROPERTY(QString text READ text) + Q_PROPERTY(int startIndex READ startIndex) + Q_PROPERTY(int endIndex READ endIndex) + +public: + ~QPdfSelection(); + QPdfSelection(const QPdfSelection &other); + QPdfSelection &operator=(const QPdfSelection &other); + QPdfSelection(QPdfSelection &&other) noexcept; + QPdfSelection &operator=(QPdfSelection &&other) noexcept { swap(other); return *this; } + void swap(QPdfSelection &other) noexcept { d.swap(other.d); } + bool isValid() const; + QList bounds() const; + QString text() const; + QRectF boundingRectangle() const; + int startIndex() const; + int endIndex() const; +#if QT_CONFIG(clipboard) + void copyToClipboard(QClipboard::Mode mode = QClipboard::Clipboard) const; +#endif + +private: + QPdfSelection(); + QPdfSelection(const QString &text, QList bounds, QRectF boundingRect, int startIndex, int endIndex); + QPdfSelection(QPdfSelectionPrivate *d); + friend class QPdfDocument; + friend class QQuickPdfSelection; + +private: + QExplicitlySharedDataPointer d; +}; + +QT_END_NAMESPACE + +#endif // QPDFSELECTION_H diff --git a/src/pdf/qpdfselection_p.h b/src/pdf/qpdfselection_p.h new file mode 100644 index 000000000..37ca3a3ce --- /dev/null +++ b/src/pdf/qpdfselection_p.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPDFSELECTION_P_H +#define QPDFSELECTION_P_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPdfSelectionPrivate : public QSharedData +{ +public: + QPdfSelectionPrivate() = default; + QPdfSelectionPrivate(const QString &text, QList bounds, QRectF boundingRect, int startIndex, int endIndex) + : text(text), + bounds(bounds), + boundingRect(boundingRect), + startIndex(startIndex), + endIndex(endIndex) { } + + QString text; + QList bounds; + QRectF boundingRect; + int startIndex; + int endIndex; +}; + +QT_END_NAMESPACE + +#endif // QPDFSELECTION_P_H diff --git a/src/pdf/qtpdf.gni b/src/pdf/qtpdf.gni deleted file mode 100644 index c31f3e9a0..000000000 --- a/src/pdf/qtpdf.gni +++ /dev/null @@ -1,7 +0,0 @@ -include_dirs = [ -] - -deps = [ - "//third_party/pdfium" -] - diff --git a/src/pdf/qtpdfglobal.h b/src/pdf/qtpdfglobal.h new file mode 100644 index 000000000..8b4b0c206 --- /dev/null +++ b/src/pdf/qtpdfglobal.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTPDFGLOBAL_H +#define QTPDFGLOBAL_H + +#include + +QT_BEGIN_NAMESPACE + +#ifndef Q_PDF_EXPORT +# ifndef QT_STATIC +# if defined(QT_BUILD_PDF_LIB) +# define Q_PDF_EXPORT Q_DECL_EXPORT +# else +# define Q_PDF_EXPORT Q_DECL_IMPORT +# endif +# else +# define Q_PDF_EXPORT +# endif +#endif + +#define Q_PDF_PRIVATE_EXPORT Q_PDF_EXPORT + +QT_END_NAMESPACE + +#endif // QTPDFGLOBAL_H + diff --git a/src/pdf/quick/plugin.cpp b/src/pdf/quick/plugin.cpp deleted file mode 100644 index b082fcb4a..000000000 --- a/src/pdf/quick/plugin.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include -#include "qquickpdfdocument_p.h" -#include "qquickpdflinkmodel_p.h" -#include "qquickpdfnavigationstack_p.h" -#include "qquickpdfsearchmodel_p.h" -#include "qquickpdfselection_p.h" -#include "qquicktableviewextra_p.h" - -QT_BEGIN_NAMESPACE - -/*! - \qmlmodule QtQuick.Pdf 5.15 - \title Qt Quick PDF QML Types - \ingroup qmlmodules - \brief Provides QML types for handling PDF documents. - - This QML module contains types for handling PDF documents. - - To use the types in this module, import the module with the following line: - - \code - import QtQuick.Pdf 5.15 - \endcode -*/ - -class QtQuick2PdfPlugin : public QQmlExtensionPlugin -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) - -public: - QtQuick2PdfPlugin() : QQmlExtensionPlugin() { } - - void initializeEngine(QQmlEngine *engine, const char *uri) override { - Q_UNUSED(uri); -#ifdef QT_STATIC - Q_UNUSED(engine); -#else - engine->addImportPath(QStringLiteral("qrc:/")); -#endif - } - - void registerTypes(const char *uri) override { - Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.Pdf")); - - // Register the latest version, even if there are no new types or new revisions for existing types yet. - qmlRegisterModule(uri, 2, QT_VERSION_MINOR); - - qmlRegisterType(uri, 5, 15, "PdfDocument"); - qmlRegisterType(uri, 5, 15, "PdfLinkModel"); - qmlRegisterType(uri, 5, 15, "PdfNavigationStack"); - qmlRegisterType(uri, 5, 15, "PdfSearchModel"); - qmlRegisterType(uri, 5, 15, "PdfSelection"); - qmlRegisterType(uri, 5, 15, "TableViewExtra"); - - qmlRegisterType(QUrl("qrc:/qt-project.org/qtpdf/qml/PdfPageView.qml"), uri, 5, 15, "PdfPageView"); - qmlRegisterType(QUrl("qrc:/qt-project.org/qtpdf/qml/PdfMultiPageView.qml"), uri, 5, 15, "PdfMultiPageView"); - qmlRegisterType(QUrl("qrc:/qt-project.org/qtpdf/qml/PdfScrollablePageView.qml"), uri, 5, 15, "PdfScrollablePageView"); - } -}; - -QT_END_NAMESPACE - -#include "plugin.moc" diff --git a/src/pdf/quick/plugins.qmltypes b/src/pdf/quick/plugins.qmltypes deleted file mode 100644 index a30361d33..000000000 --- a/src/pdf/quick/plugins.qmltypes +++ /dev/null @@ -1,52 +0,0 @@ -import QtQuick.tooling 1.2 - -// This file describes the plugin-supplied types contained in the library. -// It is used for QML tooling purposes only. -// -// This file was auto-generated by: -// 'qmlplugindump -nonrelocatable QtQuick.Pdf 5.14' - -Module { - dependencies: [ - "QtGraphicalEffects 1.12", - "QtQuick 2.14", - "QtQuick.Controls 2.14", - "QtQuick.Controls.Fusion 2.14", - "QtQuick.Controls.Fusion.impl 2.14", - "QtQuick.Controls.Imagine 2.14", - "QtQuick.Controls.Imagine.impl 2.14", - "QtQuick.Controls.Material 2.14", - "QtQuick.Controls.Material.impl 2.14", - "QtQuick.Controls.Universal 2.14", - "QtQuick.Controls.Universal.impl 2.12", - "QtQuick.Controls.impl 2.14", - "QtQuick.Shapes 1.14", - "QtQuick.Templates 2.14", - "QtQuick.Window 2.2" - ] - Component { - name: "QQuickPdfDocument" - prototype: "QObject" - exports: ["QtQuick.Pdf/PdfDocument 5.14"] - exportMetaObjectRevisions: [0] - Property { name: "source"; type: "QUrl" } - Property { name: "pageCount"; type: "int"; isReadonly: true } - Property { name: "password"; type: "string" } - Property { name: "status"; type: "QPdfDocument::Status"; isReadonly: true } - Property { name: "title"; type: "string"; isReadonly: true } - Property { name: "subject"; type: "string"; isReadonly: true } - Property { name: "author"; type: "string"; isReadonly: true } - Property { name: "keywords"; type: "string"; isReadonly: true } - Property { name: "producer"; type: "string"; isReadonly: true } - Property { name: "creator"; type: "string"; isReadonly: true } - Property { name: "creationDate"; type: "QDateTime"; isReadonly: true } - Property { name: "modificationDate"; type: "QDateTime"; isReadonly: true } - Signal { name: "passwordRequired" } - Signal { name: "metaDataLoaded" } - Method { - name: "pagePointSize" - type: "QSizeF" - Parameter { name: "page"; type: "int" } - } - } -} diff --git a/src/pdf/quick/qml/+material/PdfStyle.qml b/src/pdf/quick/qml/+material/PdfStyle.qml deleted file mode 100644 index 12df30466..000000000 --- a/src/pdf/quick/qml/+material/PdfStyle.qml +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -import QtQml 2.14 -import QtQuick.Controls 2.14 -import QtQuick.Controls.Material 2.14 -import QtQuick.Shapes 1.14 - -QtObject { - property Control prototypeControl: Control { } - function withAlpha(color, alpha) { - return Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, alpha) - } - property color selectionColor: withAlpha(prototypeControl.palette.highlight, 0.5) - property color pageSearchResultsColor: withAlpha(Qt.lighter(Material.accentColor, 1.5), 0.5) - property color currentSearchResultStrokeColor: Material.accentColor - property real currentSearchResultStrokeWidth: 2 - property color linkUnderscoreColor: prototypeControl.palette.link - property real linkUnderscoreStrokeWidth: 1 - property var linkUnderscoreStrokeStyle: ShapePath.DashLine - property var linkUnderscoreDashPattern: [ 1, 4 ] -} diff --git a/src/pdf/quick/qml/+universal/PdfStyle.qml b/src/pdf/quick/qml/+universal/PdfStyle.qml deleted file mode 100644 index e92f2a080..000000000 --- a/src/pdf/quick/qml/+universal/PdfStyle.qml +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -import QtQml 2.14 -import QtQuick 2.14 -import QtQuick.Controls 2.14 -import QtQuick.Controls.Universal 2.14 -import QtQuick.Shapes 1.14 - -QtObject { - property Control prototypeControl: Control { } - function withAlpha(color, alpha) { - return Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, alpha) - } - property color selectionColor: withAlpha(prototypeControl.palette.highlight, 0.5) - property color pageSearchResultsColor: withAlpha(Qt.lighter(Universal.accent, 1.5), 0.5) - property color currentSearchResultStrokeColor: Universal.accent - property real currentSearchResultStrokeWidth: 2 - property color linkUnderscoreColor: prototypeControl.palette.link - property real linkUnderscoreStrokeWidth: 1 - property var linkUnderscoreStrokeStyle: ShapePath.DashLine - property var linkUnderscoreDashPattern: [ 1, 4 ] -} diff --git a/src/pdf/quick/qml/PdfMultiPageView.qml b/src/pdf/quick/qml/PdfMultiPageView.qml deleted file mode 100644 index 71485c214..000000000 --- a/src/pdf/quick/qml/PdfMultiPageView.qml +++ /dev/null @@ -1,434 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -import QtQuick 2.14 -import QtQuick.Controls 2.14 -import QtQuick.Layouts 1.14 -import QtQuick.Pdf 5.15 -import QtQuick.Shapes 1.14 -import QtQuick.Window 2.14 - -Item { - // public API - // TODO 5.15: required property - property var document: undefined - property bool debug: false - - property string selectedText - function selectAll() { - var currentItem = tableHelper.itemAtCell(tableHelper.cellAtPos(root.width / 2, root.height / 2)) - if (currentItem) - currentItem.selection.selectAll() - } - function copySelectionToClipboard() { - var currentItem = tableHelper.itemAtCell(tableHelper.cellAtPos(root.width / 2, root.height / 2)) - if (debug) - console.log("currentItem", currentItem, "sel", currentItem.selection.text) - if (currentItem) - currentItem.selection.copyToClipboard() - } - - // page navigation - property alias currentPage: navigationStack.currentPage - property alias backEnabled: navigationStack.backAvailable - property alias forwardEnabled: navigationStack.forwardAvailable - function back() { navigationStack.back() } - function forward() { navigationStack.forward() } - function goToPage(page) { - if (page === navigationStack.currentPage) - return - goToLocation(page, Qt.point(-1, -1), 0) - } - function goToLocation(page, location, zoom) { - if (zoom > 0) { - navigationStack.jumping = true // don't call navigationStack.update() because we will push() instead - root.renderScale = zoom - tableView.forceLayout() // but do ensure that the table layout is correct before we try to jump - navigationStack.jumping = false - } - navigationStack.push(page, location, zoom) // actually jump - } - property vector2d jumpLocationMargin: Qt.vector2d(10, 10) // px from top-left corner - property int currentPageRenderingStatus: Image.Null - - // page scaling - property real renderScale: 1 - property real pageRotation: 0 - function resetScale() { root.renderScale = 1 } - function scaleToWidth(width, height) { - root.renderScale = width / (tableView.rot90 ? tableView.firstPagePointSize.height : tableView.firstPagePointSize.width) - } - function scaleToPage(width, height) { - var windowAspect = width / height - var pageAspect = tableView.firstPagePointSize.width / tableView.firstPagePointSize.height - if (tableView.rot90) { - if (windowAspect > pageAspect) { - root.renderScale = height / tableView.firstPagePointSize.width - } else { - root.renderScale = width / tableView.firstPagePointSize.height - } - } else { - if (windowAspect > pageAspect) { - root.renderScale = height / tableView.firstPagePointSize.height - } else { - root.renderScale = width / tableView.firstPagePointSize.width - } - } - } - - // text search - property alias searchModel: searchModel - property alias searchString: searchModel.searchString - function searchBack() { --searchModel.currentResult } - function searchForward() { ++searchModel.currentResult } - - id: root - PdfStyle { id: style } - TableView { - id: tableView - anchors.fill: parent - anchors.leftMargin: 2 - model: modelInUse && root.document !== undefined ? root.document.pageCount : 0 - // workaround to make TableView do scheduleRebuildTable(RebuildOption::All) in cases when forceLayout() doesn't - property bool modelInUse: true - function rebuild() { - modelInUse = false - modelInUse = true - } - // end workaround - rowSpacing: 6 - property real rotationNorm: Math.round((360 + (root.pageRotation % 360)) % 360) - property bool rot90: rotationNorm == 90 || rotationNorm == 270 - onRot90Changed: forceLayout() - property size firstPagePointSize: document === undefined ? Qt.size(0, 0) : document.pagePointSize(0) - property real pageHolderWidth: Math.max(root.width, document === undefined ? 0 : - (rot90 ? document.maxPageHeight : document.maxPageWidth) * root.renderScale) - contentWidth: document === undefined ? 0 : pageHolderWidth + vscroll.width + 2 - rowHeightProvider: function(row) { return (rot90 ? document.pagePointSize(row).width : document.pagePointSize(row).height) * root.renderScale } - TableViewExtra { - id: tableHelper - tableView: tableView - } - delegate: Rectangle { - id: pageHolder - color: root.debug ? "beige" : "transparent" - Text { - visible: root.debug - anchors { right: parent.right; verticalCenter: parent.verticalCenter } - rotation: -90; text: pageHolder.width.toFixed(1) + "x" + pageHolder.height.toFixed(1) + "\n" + - image.width.toFixed(1) + "x" + image.height.toFixed(1) - } - implicitWidth: tableView.pageHolderWidth - implicitHeight: tableView.rot90 ? image.width : image.height - property alias selection: selection - Rectangle { - id: paper - width: image.width - height: image.height - rotation: root.pageRotation - anchors.centerIn: pinch.active ? undefined : parent - property size pagePointSize: document.pagePointSize(index) - property real pageScale: image.paintedWidth / pagePointSize.width - Image { - id: image - source: document.source - currentFrame: index - asynchronous: true - fillMode: Image.PreserveAspectFit - width: paper.pagePointSize.width * root.renderScale - height: paper.pagePointSize.height * root.renderScale - property real renderScale: root.renderScale - property real oldRenderScale: 1 - onRenderScaleChanged: { - image.sourceSize.width = paper.pagePointSize.width * renderScale - image.sourceSize.height = 0 - paper.scale = 1 - searchHighlights.update() - } - onStatusChanged: { - if (index === navigationStack.currentPage) - root.currentPageRenderingStatus = status - } - } - Shape { - anchors.fill: parent - visible: image.status === Image.Ready - onVisibleChanged: searchHighlights.update() - ShapePath { - strokeWidth: -1 - fillColor: style.pageSearchResultsColor - scale: Qt.size(paper.pageScale, paper.pageScale) - PathMultiline { - id: searchHighlights - function update() { - // paths could be a binding, but we need to be able to "kick" it sometimes - paths = searchModel.boundingPolygonsOnPage(index) - } - } - } - Connections { - target: searchModel - // whenever the highlights on the _current_ page change, they actually need to change on _all_ pages - // (usually because the search string has changed) - function onCurrentPageBoundingPolygonsChanged() { searchHighlights.update() } - } - ShapePath { - strokeWidth: -1 - fillColor: style.selectionColor - scale: Qt.size(paper.pageScale, paper.pageScale) - PathMultiline { - paths: selection.geometry - } - } - } - Shape { - anchors.fill: parent - visible: image.status === Image.Ready && searchModel.currentPage === index - ShapePath { - strokeWidth: style.currentSearchResultStrokeWidth - strokeColor: style.currentSearchResultStrokeColor - fillColor: "transparent" - scale: Qt.size(paper.pageScale, paper.pageScale) - PathMultiline { - paths: searchModel.currentResultBoundingPolygons - } - } - } - PinchHandler { - id: pinch - minimumScale: 0.1 - maximumScale: root.renderScale < 4 ? 2 : 1 - minimumRotation: root.pageRotation - maximumRotation: root.pageRotation - enabled: image.sourceSize.width < 5000 - onActiveChanged: - if (active) { - paper.z = 10 - } else { - paper.z = 0 - var centroidInPoints = Qt.point(pinch.centroid.position.x / root.renderScale, - pinch.centroid.position.y / root.renderScale) - var centroidInFlickable = tableView.mapFromItem(paper, pinch.centroid.position.x, pinch.centroid.position.y) - var newSourceWidth = image.sourceSize.width * paper.scale - var ratio = newSourceWidth / image.sourceSize.width - if (root.debug) - console.log("pinch ended on page", index, "with centroid", pinch.centroid.position, centroidInPoints, "wrt flickable", centroidInFlickable, - "page at", pageHolder.x.toFixed(2), pageHolder.y.toFixed(2), - "contentX/Y were", tableView.contentX.toFixed(2), tableView.contentY.toFixed(2)) - if (ratio > 1.1 || ratio < 0.9) { - var centroidOnPage = Qt.point(centroidInPoints.x * root.renderScale * ratio, centroidInPoints.y * root.renderScale * ratio) - paper.scale = 1 - paper.x = 0 - paper.y = 0 - root.renderScale *= ratio - tableView.forceLayout() - if (tableView.rotationNorm == 0) { - tableView.contentX = pageHolder.x + tableView.originX + centroidOnPage.x - centroidInFlickable.x - tableView.contentY = pageHolder.y + tableView.originY + centroidOnPage.y - centroidInFlickable.y - } else if (tableView.rotationNorm == 90) { - tableView.contentX = pageHolder.x + tableView.originX + image.height - centroidOnPage.y - centroidInFlickable.x - tableView.contentY = pageHolder.y + tableView.originY + centroidOnPage.x - centroidInFlickable.y - } else if (tableView.rotationNorm == 180) { - tableView.contentX = pageHolder.x + tableView.originX + image.width - centroidOnPage.x - centroidInFlickable.x - tableView.contentY = pageHolder.y + tableView.originY + image.height - centroidOnPage.y - centroidInFlickable.y - } else if (tableView.rotationNorm == 270) { - tableView.contentX = pageHolder.x + tableView.originX + centroidOnPage.y - centroidInFlickable.x - tableView.contentY = pageHolder.y + tableView.originY + image.width - centroidOnPage.x - centroidInFlickable.y - } - if (root.debug) - console.log("contentX/Y adjusted to", tableView.contentX.toFixed(2), tableView.contentY.toFixed(2), "y @top", pageHolder.y) - tableView.returnToBounds() - } - } - grabPermissions: PointerHandler.CanTakeOverFromAnything - } - DragHandler { - id: textSelectionDrag - acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus - target: null - } - TapHandler { - id: mouseClickHandler - acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus - } - TapHandler { - id: touchTapHandler - acceptedDevices: PointerDevice.TouchScreen - onTapped: { - selection.clear() - selection.forceActiveFocus() - } - } - Repeater { - model: PdfLinkModel { - id: linkModel - document: root.document - page: image.currentFrame - } - delegate: Shape { - x: rect.x * paper.pageScale - y: rect.y * paper.pageScale - width: rect.width * paper.pageScale - height: rect.height * paper.pageScale - visible: image.status === Image.Ready - ShapePath { - strokeWidth: style.linkUnderscoreStrokeWidth - strokeColor: style.linkUnderscoreColor - strokeStyle: style.linkUnderscoreStrokeStyle - dashPattern: style.linkUnderscoreDashPattern - startX: 0; startY: height - PathLine { x: width; y: height } - } - MouseArea { // TODO switch to TapHandler / HoverHandler in 5.15 - id: linkMA - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - hoverEnabled: true - onClicked: { - if (page >= 0) - root.goToLocation(page, location, zoom) - else - Qt.openUrlExternally(url) - } - } - ToolTip { - visible: linkMA.containsMouse - delay: 1000 - text: page >= 0 ? - ("page " + (page + 1) + - " location " + location.x.toFixed(1) + ", " + location.y.toFixed(1) + - " zoom " + zoom) : url - } - } - } - PdfSelection { - id: selection - anchors.fill: parent - document: root.document - page: image.currentFrame - renderScale: image.renderScale - fromPoint: textSelectionDrag.centroid.pressPosition - toPoint: textSelectionDrag.centroid.position - hold: !textSelectionDrag.active && !mouseClickHandler.pressed - onTextChanged: root.selectedText = text - focus: true - } - } - } - ScrollBar.vertical: ScrollBar { - id: vscroll - property bool moved: false - onPositionChanged: moved = true - onActiveChanged: { - var cell = tableHelper.cellAtPos(root.width / 2, root.height / 2) - var currentItem = tableHelper.itemAtCell(cell) - var currentLocation = Qt.point(0, 0) - if (currentItem) { // maybe the delegate wasn't loaded yet - currentLocation = Qt.point((tableView.contentX - currentItem.x + jumpLocationMargin.x) / root.renderScale, - (tableView.contentY - currentItem.y + jumpLocationMargin.y) / root.renderScale) - } - if (active) { - moved = false - // emitJumped false to avoid interrupting a pinch if TableView thinks it should scroll at the same time - navigationStack.push(cell.y, currentLocation, root.renderScale, false) - } else if (moved) { - navigationStack.update(cell.y, currentLocation, root.renderScale) - } - } - } - ScrollBar.horizontal: ScrollBar { } - } - onRenderScaleChanged: { - // if navigationStack.jumped changes the scale, don't turn around and update the stack again; - // and don't force layout either, because positionViewAtCell() will do that - if (navigationStack.jumping) - return - // make TableView rebuild from scratch, because otherwise it doesn't know the delegates are changing size - tableView.rebuild() - var cell = tableHelper.cellAtPos(root.width / 2, root.height / 2) - var currentItem = tableHelper.itemAtCell(cell) - if (currentItem) { - var currentLocation = Qt.point((tableView.contentX - currentItem.x + jumpLocationMargin.x) / root.renderScale, - (tableView.contentY - currentItem.y + jumpLocationMargin.y) / root.renderScale) - navigationStack.update(cell.y, currentLocation, renderScale) - } - } - PdfNavigationStack { - id: navigationStack - property bool jumping: false - property int previousPage: 0 - onJumped: { - jumping = true - root.renderScale = zoom - if (location.y < 0) { - // invalid to indicate that a specific location was not needed, - // so attempt to position the new page just as the current page is - var currentYOffset = 0 - var previousPageDelegate = tableHelper.itemAtCell(0, previousPage) - if (previousPageDelegate) - currentYOffset = tableView.contentY - previousPageDelegate.y - tableHelper.positionViewAtRow(page, Qt.AlignTop, currentYOffset) - if (root.debug) { - console.log("going from page", previousPage, "to", page, "offset", currentYOffset, - "ended up @", tableView.contentX.toFixed(1) + ", " + tableView.contentY.toFixed(1)) - } - } else { - // jump to a page and position the given location relative to the top-left corner of the viewport - var pageSize = root.document.pagePointSize(page) - pageSize.width *= root.renderScale - pageSize.height *= root.renderScale - var xOffsetLimit = Math.max(0, pageSize.width - root.width) / 2 - var offset = Qt.point(Math.max(-xOffsetLimit, Math.min(xOffsetLimit, - location.x * root.renderScale - jumpLocationMargin.x)), - Math.max(0, location.y * root.renderScale - jumpLocationMargin.y)) - tableHelper.positionViewAtCell(0, page, Qt.AlignLeft | Qt.AlignTop, offset) - if (root.debug) { - console.log("going to zoom", zoom, "loc", location, "on page", page, - "ended up @", tableView.contentX.toFixed(1) + ", " + tableView.contentY.toFixed(1)) - } - } - jumping = false - previousPage = page - } - onCurrentPageChanged: searchModel.currentPage = currentPage - } - PdfSearchModel { - id: searchModel - document: root.document === undefined ? null : root.document - // TODO maybe avoid jumping if the result is already fully visible in the viewport - onCurrentResultBoundingRectChanged: root.goToLocation(currentPage, - Qt.point(currentResultBoundingRect.x, currentResultBoundingRect.y), 0) - } -} diff --git a/src/pdf/quick/qml/PdfPageView.qml b/src/pdf/quick/qml/PdfPageView.qml deleted file mode 100644 index b90ad2d7f..000000000 --- a/src/pdf/quick/qml/PdfPageView.qml +++ /dev/null @@ -1,276 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -import QtQuick 2.14 -import QtQuick.Controls 2.14 -import QtQuick.Pdf 5.15 -import QtQuick.Shapes 1.14 -import Qt.labs.animation 1.0 - -Rectangle { - // public API - // TODO 5.15: required property - property var document: undefined - property alias status: image.status - - property alias selectedText: selection.text - function selectAll() { - selection.selectAll() - } - function copySelectionToClipboard() { - selection.copyToClipboard() - } - - // page navigation - property alias currentPage: navigationStack.currentPage - property alias backEnabled: navigationStack.backAvailable - property alias forwardEnabled: navigationStack.forwardAvailable - function back() { navigationStack.back() } - function forward() { navigationStack.forward() } - function goToPage(page) { goToLocation(page, Qt.point(0, 0), 0) } - function goToLocation(page, location, zoom) { - if (zoom > 0) - root.renderScale = zoom - navigationStack.push(page, location, zoom) - } - - // page scaling - property real renderScale: 1 - property alias sourceSize: image.sourceSize - function resetScale() { - image.sourceSize.width = 0 - image.sourceSize.height = 0 - root.x = 0 - root.y = 0 - root.scale = 1 - } - function scaleToWidth(width, height) { - var halfRotation = Math.abs(root.rotation % 180) - image.sourceSize = Qt.size((halfRotation > 45 && halfRotation < 135) ? height : width, 0) - root.x = 0 - root.y = 0 - image.centerInSize = Qt.size(width, height) - image.centerOnLoad = true - image.vCenterOnLoad = (halfRotation > 45 && halfRotation < 135) - root.scale = 1 - } - function scaleToPage(width, height) { - var windowAspect = width / height - var halfRotation = Math.abs(root.rotation % 180) - var pagePointSize = document.pagePointSize(navigationStack.currentPage) - if (halfRotation > 45 && halfRotation < 135) { - // rotated 90 or 270º - var pageAspect = pagePointSize.height / pagePointSize.width - if (windowAspect > pageAspect) { - image.sourceSize = Qt.size(height, 0) - } else { - image.sourceSize = Qt.size(0, width) - } - } else { - var pageAspect = pagePointSize.width / pagePointSize.height - if (windowAspect > pageAspect) { - image.sourceSize = Qt.size(0, height) - } else { - image.sourceSize = Qt.size(width, 0) - } - } - image.centerInSize = Qt.size(width, height) - image.centerOnLoad = true - image.vCenterOnLoad = true - root.scale = 1 - } - - // text search - property alias searchModel: searchModel - property alias searchString: searchModel.searchString - function searchBack() { --searchModel.currentResult } - function searchForward() { ++searchModel.currentResult } - - // implementation - id: root - width: image.width - height: image.height - - PdfSelection { - id: selection - document: root.document - page: navigationStack.currentPage - fromPoint: Qt.point(textSelectionDrag.centroid.pressPosition.x / image.pageScale, textSelectionDrag.centroid.pressPosition.y / image.pageScale) - toPoint: Qt.point(textSelectionDrag.centroid.position.x / image.pageScale, textSelectionDrag.centroid.position.y / image.pageScale) - hold: !textSelectionDrag.active && !tapHandler.pressed - } - - PdfSearchModel { - id: searchModel - document: root.document === undefined ? null : root.document - onCurrentPageChanged: root.goToPage(currentPage) - } - - PdfNavigationStack { - id: navigationStack - onCurrentPageChanged: searchModel.currentPage = currentPage - // TODO onCurrentLocationChanged: position currentLocation.x and .y in middle // currentPageChanged() MUST occur first! - onCurrentZoomChanged: root.renderScale = currentZoom - // TODO deal with horizontal location (need WheelHandler or Flickable probably) - } - - Image { - id: image - currentFrame: navigationStack.currentPage - source: document.status === PdfDocument.Ready ? document.source : "" - asynchronous: true - fillMode: Image.PreserveAspectFit - property bool centerOnLoad: false - property bool vCenterOnLoad: false - property size centerInSize - property real pageScale: image.paintedWidth / document.pagePointSize(navigationStack.currentPage).width - function reRenderIfNecessary() { - var newSourceWidth = image.sourceSize.width * root.scale - var ratio = newSourceWidth / image.sourceSize.width - if (ratio > 1.1 || ratio < 0.9) { - image.sourceSize.width = newSourceWidth - image.sourceSize.height = 0 - root.scale = 1 - } - } - onStatusChanged: - if (status == Image.Ready && centerOnLoad) { - root.x = (centerInSize.width - image.implicitWidth) / 2 - root.y = vCenterOnLoad ? (centerInSize.height - image.implicitHeight) / 2 : 0 - centerOnLoad = false - vCenterOnLoad = false - } - } - onRenderScaleChanged: { - image.sourceSize.width = document.pagePointSize(navigationStack.currentPage).width * renderScale - image.sourceSize.height = 0 - root.scale = 1 - } - - Shape { - anchors.fill: parent - opacity: 0.25 - visible: image.status === Image.Ready - ShapePath { - strokeWidth: 1 - strokeColor: "cyan" - fillColor: "steelblue" - scale: Qt.size(image.pageScale, image.pageScale) - PathMultiline { - paths: searchModel.currentPageBoundingPolygons - } - } - ShapePath { - strokeWidth: 1 - strokeColor: "orange" - fillColor: "cyan" - scale: Qt.size(image.pageScale, image.pageScale) - PathMultiline { - paths: searchModel.currentResultBoundingPolygons - } - } - ShapePath { - fillColor: "orange" - scale: Qt.size(image.pageScale, image.pageScale) - PathMultiline { - paths: selection.geometry - } - } - } - - Repeater { - model: PdfLinkModel { - id: linkModel - document: root.document - page: navigationStack.currentPage - } - delegate: Rectangle { - color: "transparent" - border.color: "lightgrey" - x: rect.x * image.pageScale - y: rect.y * image.pageScale - width: rect.width * image.pageScale - height: rect.height * image.pageScale - MouseArea { // TODO switch to TapHandler / HoverHandler in 5.15 - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: { - if (page >= 0) - navigationStack.push(page, Qt.point(0, 0), root.renderScale) - else - Qt.openUrlExternally(url) - } - } - } - } - - PinchHandler { - id: pinch - minimumScale: 0.1 - maximumScale: 10 - minimumRotation: 0 - maximumRotation: 0 - onActiveChanged: if (!active) image.reRenderIfNecessary() - grabPermissions: PinchHandler.TakeOverForbidden // don't allow takeover if pinch has started - } - DragHandler { - id: pageMovingTouchDrag - acceptedDevices: PointerDevice.TouchScreen - } - DragHandler { - id: pageMovingMiddleMouseDrag - acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus - acceptedButtons: Qt.MiddleButton - snapMode: DragHandler.NoSnap - } - DragHandler { - id: textSelectionDrag - acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus - target: null - } - TapHandler { - id: tapHandler - acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus - } - // prevent it from being scrolled out of view - BoundaryRule on x { - minimum: 100 - root.width - maximum: root.parent.width - 100 - } - BoundaryRule on y { - minimum: 100 - root.height - maximum: root.parent.height - 100 - } -} diff --git a/src/pdf/quick/qml/PdfScrollablePageView.qml b/src/pdf/quick/qml/PdfScrollablePageView.qml deleted file mode 100644 index 51d9e530d..000000000 --- a/src/pdf/quick/qml/PdfScrollablePageView.qml +++ /dev/null @@ -1,307 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -import QtQuick 2.14 -import QtQuick.Controls 2.14 -import QtQuick.Pdf 5.15 -import QtQuick.Shapes 1.14 -import Qt.labs.animation 1.0 - -Flickable { - // public API - // TODO 5.15: required property - property var document: undefined - property bool debug: false - property alias status: image.status - - property alias selectedText: selection.text - function selectAll() { - selection.selectAll() - } - function copySelectionToClipboard() { - selection.copyToClipboard() - } - - // page navigation - property alias currentPage: navigationStack.currentPage - property alias backEnabled: navigationStack.backAvailable - property alias forwardEnabled: navigationStack.forwardAvailable - function back() { navigationStack.back() } - function forward() { navigationStack.forward() } - function goToPage(page) { - if (page === navigationStack.currentPage) - return - goToLocation(page, Qt.point(0, 0), 0) - } - function goToLocation(page, location, zoom) { - if (zoom > 0) - root.renderScale = zoom - navigationStack.push(page, location, zoom) - } - - // page scaling - property real renderScale: 1 - property real pageRotation: 0 - property alias sourceSize: image.sourceSize - function resetScale() { - paper.scale = 1 - root.renderScale = 1 - } - function scaleToWidth(width, height) { - var pagePointSize = document.pagePointSize(navigationStack.currentPage) - root.renderScale = root.width / (paper.rot90 ? pagePointSize.height : pagePointSize.width) - if (debug) - console.log("scaling", pagePointSize, "to fit", root.width, "rotated?", paper.rot90, "scale", root.renderScale) - root.contentX = 0 - root.contentY = 0 - } - function scaleToPage(width, height) { - var pagePointSize = document.pagePointSize(navigationStack.currentPage) - root.renderScale = Math.min( - root.width / (paper.rot90 ? pagePointSize.height : pagePointSize.width), - root.height / (paper.rot90 ? pagePointSize.width : pagePointSize.height) ) - root.contentX = 0 - root.contentY = 0 - } - - // text search - property alias searchModel: searchModel - property alias searchString: searchModel.searchString - function searchBack() { --searchModel.currentResult } - function searchForward() { ++searchModel.currentResult } - - // implementation - id: root - PdfStyle { id: style } - contentWidth: paper.width - contentHeight: paper.height - ScrollBar.vertical: ScrollBar { - onActiveChanged: - if (!active ) { - var currentLocation = Qt.point((root.contentX + root.width / 2) / root.renderScale, - (root.contentY + root.height / 2) / root.renderScale) - navigationStack.update(navigationStack.currentPage, currentLocation, root.renderScale) - } - } - ScrollBar.horizontal: ScrollBar { - onActiveChanged: - if (!active ) { - var currentLocation = Qt.point((root.contentX + root.width / 2) / root.renderScale, - (root.contentY + root.height / 2) / root.renderScale) - navigationStack.update(navigationStack.currentPage, currentLocation, root.renderScale) - } - } - - onRenderScaleChanged: { - image.sourceSize.width = document.pagePointSize(navigationStack.currentPage).width * renderScale - image.sourceSize.height = 0 - paper.scale = 1 - var currentLocation = Qt.point((root.contentX + root.width / 2) / root.renderScale, - (root.contentY + root.height / 2) / root.renderScale) - navigationStack.update(navigationStack.currentPage, currentLocation, root.renderScale) - } - - PdfSearchModel { - id: searchModel - document: root.document === undefined ? null : root.document - // TODO maybe avoid jumping if the result is already fully visible in the viewport - onCurrentResultBoundingRectChanged: root.goToLocation(currentPage, - Qt.point(currentResultBoundingRect.x, currentResultBoundingRect.y), 0) - } - - PdfNavigationStack { - id: navigationStack - onJumped: { - root.renderScale = zoom - var dx = Math.max(0, location.x * root.renderScale - root.width / 2) - root.contentX - var dy = Math.max(0, location.y * root.renderScale - root.height / 2) - root.contentY - // don't jump if location is in the viewport already, i.e. if the "error" between desired and actual contentX/Y is small - if (Math.abs(dx) > root.width / 3) - root.contentX += dx - if (Math.abs(dy) > root.height / 3) - root.contentY += dy - if (root.debug) { - console.log("going to zoom", zoom, "loc", location, - "on page", page, "ended up @", root.contentX + ", " + root.contentY) - } - } - onCurrentPageChanged: searchModel.currentPage = currentPage - } - - Rectangle { - id: paper - width: rot90 ? image.height : image.width - height: rot90 ? image.width : image.height - property real rotationModulus: Math.abs(root.pageRotation % 180) - property bool rot90: rotationModulus > 45 && rotationModulus < 135 - - Image { - id: image - currentFrame: navigationStack.currentPage - source: document.status === PdfDocument.Ready ? document.source : "" - asynchronous: true - fillMode: Image.PreserveAspectFit - rotation: root.pageRotation - anchors.centerIn: parent - property real pageScale: image.paintedWidth / document.pagePointSize(navigationStack.currentPage).width - - Shape { - anchors.fill: parent - visible: image.status === Image.Ready - ShapePath { - strokeWidth: -1 - fillColor: style.pageSearchResultsColor - scale: Qt.size(image.pageScale, image.pageScale) - PathMultiline { - paths: searchModel.currentPageBoundingPolygons - } - } - ShapePath { - strokeWidth: style.currentSearchResultStrokeWidth - strokeColor: style.currentSearchResultStrokeColor - fillColor: "transparent" - scale: Qt.size(image.pageScale, image.pageScale) - PathMultiline { - paths: searchModel.currentResultBoundingPolygons - } - } - ShapePath { - fillColor: style.selectionColor - scale: Qt.size(image.pageScale, image.pageScale) - PathMultiline { - paths: selection.geometry - } - } - } - - Repeater { - model: PdfLinkModel { - id: linkModel - document: root.document - page: navigationStack.currentPage - } - delegate: Shape { - x: rect.x * image.pageScale - y: rect.y * image.pageScale - width: rect.width * image.pageScale - height: rect.height * image.pageScale - ShapePath { - strokeWidth: style.linkUnderscoreStrokeWidth - strokeColor: style.linkUnderscoreColor - strokeStyle: style.linkUnderscoreStrokeStyle - dashPattern: style.linkUnderscoreDashPattern - startX: 0; startY: height - PathLine { x: width; y: height } - } - MouseArea { // TODO switch to TapHandler / HoverHandler in 5.15 - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: { - if (page >= 0) - navigationStack.push(page, Qt.point(0, 0), root.renderScale) - else - Qt.openUrlExternally(url) - } - } - } - } - DragHandler { - id: textSelectionDrag - acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus - target: null - } - TapHandler { - id: mouseClickHandler - acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus - } - TapHandler { - id: touchTapHandler - acceptedDevices: PointerDevice.TouchScreen - onTapped: { - selection.clear() - selection.focus = true - } - } - } - - PdfSelection { - id: selection - anchors.fill: parent - document: root.document - page: navigationStack.currentPage - renderScale: image.pageScale - fromPoint: textSelectionDrag.centroid.pressPosition - toPoint: textSelectionDrag.centroid.position - hold: !textSelectionDrag.active && !mouseClickHandler.pressed - focus: true - } - - PinchHandler { - id: pinch - minimumScale: 0.1 - maximumScale: root.renderScale < 4 ? 2 : 1 - minimumRotation: 0 - maximumRotation: 0 - enabled: image.sourceSize.width < 5000 - onActiveChanged: - if (!active) { - var centroidInPoints = Qt.point(pinch.centroid.position.x / root.renderScale, - pinch.centroid.position.y / root.renderScale) - var centroidInFlickable = root.mapFromItem(paper, pinch.centroid.position.x, pinch.centroid.position.y) - var newSourceWidth = image.sourceSize.width * paper.scale - var ratio = newSourceWidth / image.sourceSize.width - if (root.debug) - console.log("pinch ended with centroid", pinch.centroid.position, centroidInPoints, "wrt flickable", centroidInFlickable, - "page at", paper.x.toFixed(2), paper.y.toFixed(2), - "contentX/Y were", root.contentX.toFixed(2), root.contentY.toFixed(2)) - if (ratio > 1.1 || ratio < 0.9) { - var centroidOnPage = Qt.point(centroidInPoints.x * root.renderScale * ratio, centroidInPoints.y * root.renderScale * ratio) - paper.scale = 1 - paper.x = 0 - paper.y = 0 - root.contentX = centroidOnPage.x - centroidInFlickable.x - root.contentY = centroidOnPage.y - centroidInFlickable.y - root.renderScale *= ratio // onRenderScaleChanged calls navigationStack.update() so we don't need to here - if (root.debug) - console.log("contentX/Y adjusted to", root.contentX.toFixed(2), root.contentY.toFixed(2)) - } else { - paper.x = 0 - paper.y = 0 - } - } - grabPermissions: PointerHandler.CanTakeOverFromAnything - } - } -} diff --git a/src/pdf/quick/qml/PdfStyle.qml b/src/pdf/quick/qml/PdfStyle.qml deleted file mode 100644 index 090465ce6..000000000 --- a/src/pdf/quick/qml/PdfStyle.qml +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -import QtQml 2.14 -import QtQuick 2.14 -import QtQuick.Controls 2.14 -import QtQuick.Shapes 1.14 - -QtObject { - property Control prototypeControl: Control { } - function withAlpha(color, alpha) { - return Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, alpha) - } - property color selectionColor: withAlpha(prototypeControl.palette.highlight, 0.5) - property color pageSearchResultsColor: "#80B0C4DE" - property color currentSearchResultStrokeColor: "cyan" - property real currentSearchResultStrokeWidth: 2 - property color linkUnderscoreColor: prototypeControl.palette.link - property real linkUnderscoreStrokeWidth: 1 - property var linkUnderscoreStrokeStyle: ShapePath.DashLine - property var linkUnderscoreDashPattern: [ 1, 4 ] -} diff --git a/src/pdf/quick/qmldir b/src/pdf/quick/qmldir deleted file mode 100644 index 65fa95cda..000000000 --- a/src/pdf/quick/qmldir +++ /dev/null @@ -1,4 +0,0 @@ -module QtQuick.Pdf -plugin pdfplugin -classname QtQuick2PdfPlugin -typeinfo plugins.qmltypes diff --git a/src/pdf/quick/qquickpdfdocument.cpp b/src/pdf/quick/qquickpdfdocument.cpp deleted file mode 100644 index 79b23ca84..000000000 --- a/src/pdf/quick/qquickpdfdocument.cpp +++ /dev/null @@ -1,305 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qquickpdfdocument_p.h" -#include -#include -#include - -QT_BEGIN_NAMESPACE - -/*! - \qmltype PdfDocument - \instantiates QQuickPdfDocument - \inqmlmodule QtQuick.Pdf - \ingroup pdf - \brief A representation of a PDF document. - \since 5.15 - - PdfDocument provides access to PDF document meta-information. - It is not necessary for rendering, as it is enough to use an - \l Image with source set to the URL of the PDF. -*/ - -/*! - Constructs a PDF document. -*/ -QQuickPdfDocument::QQuickPdfDocument(QObject *parent) - : QObject(parent) -{ - connect(&m_doc, &QPdfDocument::passwordChanged, this, &QQuickPdfDocument::passwordChanged); - connect(&m_doc, &QPdfDocument::passwordRequired, this, &QQuickPdfDocument::passwordRequired); - connect(&m_doc, &QPdfDocument::statusChanged, [=] (QPdfDocument::Status status) { - emit statusChanged(); - if (status == QPdfDocument::Ready) - emit metaDataChanged(); - }); - connect(&m_doc, &QPdfDocument::pageCountChanged, this, &QQuickPdfDocument::pageCountChanged); -} - -void QQuickPdfDocument::componentComplete() -{ - if (m_doc.error() == QPdfDocument::IncorrectPasswordError) - emit passwordRequired(); -} - -/*! - \qmlproperty url PdfDocument::source - - This property holds a URL pointing to the PDF file to be loaded. - - \note At this time, only local filesystem URLs are supported. -*/ -void QQuickPdfDocument::setSource(QUrl source) -{ - if (m_source == source) - return; - - m_source = source; - m_maxPageWidthHeight = QSizeF(); - emit sourceChanged(); - if (source.scheme() == QLatin1String("qrc")) - m_doc.load(QLatin1Char(':') + source.path()); - else - m_doc.load(source.toLocalFile()); -} - -/*! - \qmlproperty string PdfDocument::error - - This property holds a translated string representation of the current - error, if any. - - \sa status -*/ -QString QQuickPdfDocument::error() const -{ - switch (m_doc.error()) { - case QPdfDocument::NoError: - return tr("no error"); - break; - case QPdfDocument::UnknownError: - break; - case QPdfDocument::DataNotYetAvailableError: - return tr("data not yet available"); - break; - case QPdfDocument::FileNotFoundError: - return tr("file not found"); - break; - case QPdfDocument::InvalidFileFormatError: - return tr("invalid file format"); - break; - case QPdfDocument::IncorrectPasswordError: - return tr("incorrect password"); - break; - case QPdfDocument::UnsupportedSecuritySchemeError: - return tr("unsupported security scheme"); - break; - } - return tr("unknown error"); -} - -/*! - \qmlproperty bool PdfDocument::password - - This property holds the document password. If the passwordRequired() - signal is emitted, the UI should prompt the user and then set this - property so that document opening can continue. -*/ -void QQuickPdfDocument::setPassword(const QString &password) -{ - if (m_doc.password() == password) - return; - m_doc.setPassword(password); - if (source().isValid() && source().isLocalFile()) - m_doc.load(source().path()); -} - -/*! - \qmlproperty int PdfDocument::pageCount - - This property holds the number of pages the PDF contains. -*/ - -/*! - \qmlsignal PdfDocument::passwordRequired() - - This signal is emitted when the PDF requires a password in order to open. - The UI in a typical PDF viewer should prompt the user for the password - and then set the password property when the user has provided it. -*/ - -/*! - \qmlmethod size PdfDocument::pagePointSize(int page) - - Returns the size of the given \a page in points. -*/ -QSizeF QQuickPdfDocument::pagePointSize(int page) const -{ - return m_doc.pageSize(page); -} - -qreal QQuickPdfDocument::maxPageWidth() const -{ - const_cast(this)->updateMaxPageSize(); - return m_maxPageWidthHeight.width(); -} - -qreal QQuickPdfDocument::maxPageHeight() const -{ - const_cast(this)->updateMaxPageSize(); - return m_maxPageWidthHeight.height(); -} - -/*! - \internal - \qmlmethod size PdfDocument::heightSumBeforePage(int page) - - Returns the sum of the heights, in points, of all sets of \a facingPages - pages from 0 to the given \a page, exclusive. - - That is, if the pages were laid out end-to-end in adjacent sets of - \a facingPages, what would be the distance in points from the top of the - first page to the top of the given page. -*/ -// Workaround for lack of something analogous to ListView.positionViewAtIndex() in TableView -qreal QQuickPdfDocument::heightSumBeforePage(int page, qreal spacing, int facingPages) const -{ - qreal ret = 0; - for (int i = 0; i < page; i+= facingPages) { - if (i + facingPages > page) - break; - qreal facingPagesHeight = 0; - for (int j = i; j < i + facingPages; ++j) - facingPagesHeight = qMax(facingPagesHeight, pagePointSize(j).height()); - ret += facingPagesHeight + spacing; - } - return ret; -} - -void QQuickPdfDocument::updateMaxPageSize() -{ - if (m_maxPageWidthHeight.isValid()) - return; - qreal w = 0; - qreal h = 0; - const int count = pageCount(); - for (int i = 0; i < count; ++i) { - auto size = pagePointSize(i); - w = qMax(w, size.width()); - h = qMax(w, size.height()); - } - m_maxPageWidthHeight = QSizeF(w, h); -} - -/*! - \qmlproperty real PdfDocument::maxPageWidth - - This property holds the width of the widest page in the document, in points. -*/ - -/*! - \qmlproperty real PdfDocument::maxPageHeight - - This property holds the height of the tallest page in the document, in points. -*/ - -/*! - \qmlproperty string PdfDocument::title - - This property holds the document's title. A typical viewer UI can bind this - to the \c Window.title property. -*/ - -/*! - \qmlproperty string PdfDocument::author - - This property holds the name of the person who created the document. -*/ - -/*! - \qmlproperty string PdfDocument::subject - - This property holds the subject of the document. -*/ - -/*! - \qmlproperty string PdfDocument::keywords - - This property holds the keywords associated with the document. -*/ - -/*! - \qmlproperty string PdfDocument::creator - - If the document was converted to PDF from another format, this property - holds the name of the software that created the original document. -*/ - -/*! - \qmlproperty string PdfDocument::producer - - If the document was converted to PDF from another format, this property - holds the name of the software that converted it to PDF. -*/ - -/*! - \qmlproperty string PdfDocument::creationDate - - This property holds the date and time the document was created. -*/ - -/*! - \qmlproperty string PdfDocument::modificationDate - - This property holds the date and time the document was most recently - modified. -*/ - -/*! - \qmlproperty enum PdfDocument::status - - This property tells the current status of the document. The possible values are: - - \value PdfDocument.Null The initial status after the document has been created or after it has been closed. - \value PdfDocument.Loading The status after load() has been called and before the document is fully loaded. - \value PdfDocument.Ready The status when the document is fully loaded and its data can be accessed. - \value PdfDocument.Unloading The status after close() has been called on an open document. - At this point the document is still valid and all its data can be accessed. - \value PdfDocument.Error The status after Loading, if loading has failed. -*/ - -QT_END_NAMESPACE diff --git a/src/pdf/quick/qquickpdfdocument_p.h b/src/pdf/quick/qquickpdfdocument_p.h deleted file mode 100644 index cefa4f756..000000000 --- a/src/pdf/quick/qquickpdfdocument_p.h +++ /dev/null @@ -1,137 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQUICKPDFDOCUMENT_P_H -#define QQUICKPDFDOCUMENT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QQuickPdfDocument : public QObject, public QQmlParserStatus -{ - Q_OBJECT - Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) - Q_PROPERTY(int pageCount READ pageCount NOTIFY pageCountChanged FINAL) - Q_PROPERTY(qreal maxPageWidth READ maxPageWidth NOTIFY metaDataChanged) - Q_PROPERTY(qreal maxPageHeight READ maxPageHeight NOTIFY metaDataChanged) - Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged FINAL) - Q_PROPERTY(QPdfDocument::Status status READ status NOTIFY statusChanged FINAL) - Q_PROPERTY(QString error READ error NOTIFY statusChanged FINAL) - - Q_PROPERTY(QString title READ title NOTIFY metaDataChanged) - Q_PROPERTY(QString subject READ subject NOTIFY metaDataChanged) - Q_PROPERTY(QString author READ author NOTIFY metaDataChanged) - Q_PROPERTY(QString keywords READ keywords NOTIFY metaDataChanged) - Q_PROPERTY(QString producer READ producer NOTIFY metaDataChanged) - Q_PROPERTY(QString creator READ creator NOTIFY metaDataChanged) - Q_PROPERTY(QDateTime creationDate READ creationDate NOTIFY metaDataChanged) - Q_PROPERTY(QDateTime modificationDate READ modificationDate NOTIFY metaDataChanged) - -public: - explicit QQuickPdfDocument(QObject *parent = nullptr); - - void classBegin() override {} - void componentComplete() override; - - QUrl source() const { return m_source; } - void setSource(QUrl source); - - int pageCount() const { return m_doc.pageCount(); } - QPdfDocument::Status status() const { return m_doc.status(); } - - QString error() const; - - QString password() const { return m_doc.password(); } - void setPassword(const QString &password); - - QString title() { return m_doc.metaData(QPdfDocument::Title).toString(); } - QString author() { return m_doc.metaData(QPdfDocument::Author).toString(); } - QString subject() { return m_doc.metaData(QPdfDocument::Subject).toString(); } - QString keywords() { return m_doc.metaData(QPdfDocument::Keywords).toString(); } - QString producer() { return m_doc.metaData(QPdfDocument::Producer).toString(); } - QString creator() { return m_doc.metaData(QPdfDocument::Creator).toString(); } - QDateTime creationDate() { return m_doc.metaData(QPdfDocument::CreationDate).toDateTime(); } - QDateTime modificationDate() { return m_doc.metaData(QPdfDocument::ModificationDate).toDateTime(); } - - Q_INVOKABLE QSizeF pagePointSize(int page) const; - qreal maxPageWidth() const; - qreal maxPageHeight() const; - Q_INVOKABLE qreal heightSumBeforePage(int page, qreal spacing = 0, int facingPages = 1) const; - -Q_SIGNALS: - void sourceChanged(); - void passwordChanged(); - void passwordRequired(); - void statusChanged(); - void pageCountChanged(); - void metaDataChanged(); - -private: - QPdfDocument &document() { return m_doc; } - void updateMaxPageSize(); - -private: - QUrl m_source; - QPdfDocument m_doc; - QSizeF m_maxPageWidthHeight; - - friend class QQuickPdfLinkModel; - friend class QQuickPdfSearchModel; - friend class QQuickPdfSelection; - - Q_DISABLE_COPY(QQuickPdfDocument) -}; - -QT_END_NAMESPACE - -#endif // QQUICKPDFDOCUMENT_P_H diff --git a/src/pdf/quick/qquickpdflinkmodel.cpp b/src/pdf/quick/qquickpdflinkmodel.cpp deleted file mode 100644 index 4f3958337..000000000 --- a/src/pdf/quick/qquickpdflinkmodel.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qquickpdflinkmodel_p.h" -#include -#include -#include - -QT_BEGIN_NAMESPACE - -/*! - \qmltype PdfLinkModel - \instantiates QQuickPdfLinkModel - \inqmlmodule QtQuick.Pdf - \ingroup pdf - \brief A representation of links within a PDF document. - \since 5.15 - - PdfLinkModel provides the geometry and the destination for each link - that the specified \l page contains. - - The available model roles are: - - \value rect - Bounding rectangle around the link. - \value url - If the link is a web link, the URL for that; otherwise an empty URL. - \value page - If the link is an internal link, the page number to which the link should jump; otherwise \c {-1}. - \value location - If the link is an internal link, the location on the page to which the link should jump. - \value zoom - If the link is an internal link, the intended zoom level on the destination page. - - Normally it will be used with \l {QtQuick::Repeater}{Repeater} to visualize - the links and provide the ability to click them: - - \qml - Repeater { - model: PdfLinkModel { - document: root.document - page: image.currentFrame - } - delegate: Rectangle { - color: "transparent" - border.color: "lightgrey" - x: rect.x - y: rect.y - width: rect.width - height: rect.height - HoverHandler { cursorShape: Qt.PointingHandCursor } - TapHandler { - onTapped: { - if (page >= 0) - image.currentFrame = page - else - Qt.openUrlExternally(url) - } - } - } - } - \endqml - - \note General-purpose PDF viewing capabilities are provided by - \l PdfScrollablePageView and \l PdfMultiPageView. PdfLinkModel is only needed - when building PDF view components from scratch. -*/ - -QQuickPdfLinkModel::QQuickPdfLinkModel(QObject *parent) - : QPdfLinkModel(parent) -{ -} - -/*! - \qmlproperty PdfDocument PdfLinkModel::document - - This property holds the PDF document in which links are to be found. -*/ -QQuickPdfDocument *QQuickPdfLinkModel::document() const -{ - return m_quickDocument; -} - -void QQuickPdfLinkModel::setDocument(QQuickPdfDocument *document) -{ - if (document == m_quickDocument) - return; - m_quickDocument = document; - QPdfLinkModel::setDocument(&document->m_doc); -} - -/*! - \qmlproperty int PdfLinkModel::page - - This property holds the page number on which links are to be found. -*/ - -QT_END_NAMESPACE diff --git a/src/pdf/quick/qquickpdflinkmodel_p.h b/src/pdf/quick/qquickpdflinkmodel_p.h deleted file mode 100644 index 6f19daa28..000000000 --- a/src/pdf/quick/qquickpdflinkmodel_p.h +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQUICKPDFLINKMODEL_P_H -#define QQUICKPDFLINKMODEL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qquickpdfdocument_p.h" -#include "../api/qpdflinkmodel_p.h" - -#include -#include - -QT_BEGIN_NAMESPACE - -class QQuickPdfLinkModel : public QPdfLinkModel -{ - Q_OBJECT - Q_PROPERTY(QQuickPdfDocument *document READ document WRITE setDocument NOTIFY documentChanged) - -public: - explicit QQuickPdfLinkModel(QObject *parent = nullptr); - - QQuickPdfDocument *document() const; - void setDocument(QQuickPdfDocument *document); - -signals: - void documentChanged(); - -private: - void updateResults(); - -private: - QQuickPdfDocument *m_quickDocument; - QList m_linksGeometry; - - Q_DISABLE_COPY(QQuickPdfLinkModel) -}; - -QT_END_NAMESPACE - -QML_DECLARE_TYPE(QQuickPdfLinkModel) - -#endif // QQUICKPDFLINKMODEL_P_H diff --git a/src/pdf/quick/qquickpdfnavigationstack.cpp b/src/pdf/quick/qquickpdfnavigationstack.cpp deleted file mode 100644 index 044023ef6..000000000 --- a/src/pdf/quick/qquickpdfnavigationstack.cpp +++ /dev/null @@ -1,272 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qquickpdfnavigationstack_p.h" -#include - -QT_BEGIN_NAMESPACE - -Q_LOGGING_CATEGORY(qLcNav, "qt.pdf.navigationstack") - -/*! - \qmltype PdfNavigationStack - \instantiates QQuickPdfNavigationStack - \inqmlmodule QtQuick.Pdf - \ingroup pdf - \brief History of the destinations visited within a PDF Document. - \since 5.15 - - PdfNavigationStack remembers which destinations the user has visited in a PDF - document, and provides the ability to traverse backward and forward. -*/ - -QQuickPdfNavigationStack::QQuickPdfNavigationStack(QObject *parent) - : QObject(parent) -{ - push(0, QPointF(), 1); -} - -/*! - \qmlmethod void PdfNavigationStack::forward() - - Goes back to the page, location and zoom level that was being viewed before - back() was called, and then emits the \l jumped() signal. - - If a new destination was pushed since the last time \l back() was called, - the forward() function does nothing, because there is a branch in the - timeline which causes the "future" to be lost. -*/ -void QQuickPdfNavigationStack::forward() -{ - if (m_currentHistoryIndex >= m_pageHistory.count() - 1) - return; - bool backAvailableWas = backAvailable(); - bool forwardAvailableWas = forwardAvailable(); - QPointF currentLocationWas = currentLocation(); - qreal currentZoomWas = currentZoom(); - ++m_currentHistoryIndex; - m_changing = true; - emit jumped(currentPage(), currentLocation(), currentZoom()); - if (currentZoomWas != currentZoom()) - emit currentZoomChanged(); - emit currentPageChanged(); - if (currentLocationWas != currentLocation()) - emit currentLocationChanged(); - if (!backAvailableWas) - emit backAvailableChanged(); - if (forwardAvailableWas != forwardAvailable()) - emit forwardAvailableChanged(); - m_changing = false; - qCDebug(qLcNav) << "forward: index" << m_currentHistoryIndex << "page" << currentPage() - << "@" << currentLocation() << "zoom" << currentZoom(); -} - -/*! - \qmlmethod void PdfNavigationStack::back() - - Pops the stack, updates the \l currentPage, \l currentLocation and - \l currentZoom properties to the most-recently-viewed destination, and then - emits the \l jumped() signal. -*/ -void QQuickPdfNavigationStack::back() -{ - if (m_currentHistoryIndex <= 0) - return; - bool backAvailableWas = backAvailable(); - bool forwardAvailableWas = forwardAvailable(); - QPointF currentLocationWas = currentLocation(); - qreal currentZoomWas = currentZoom(); - --m_currentHistoryIndex; - m_changing = true; - emit jumped(currentPage(), currentLocation(), currentZoom()); - if (currentZoomWas != currentZoom()) - emit currentZoomChanged(); - emit currentPageChanged(); - if (currentLocationWas != currentLocation()) - emit currentLocationChanged(); - if (backAvailableWas != backAvailable()) - emit backAvailableChanged(); - if (!forwardAvailableWas) - emit forwardAvailableChanged(); - m_changing = false; - qCDebug(qLcNav) << "back: index" << m_currentHistoryIndex << "page" << currentPage() - << "@" << currentLocation() << "zoom" << currentZoom(); -} - -/*! - \qmlproperty int PdfNavigationStack::currentPage - - This property holds the current page that is being viewed. - If there is no current page, it holds \c -1. -*/ -int QQuickPdfNavigationStack::currentPage() const -{ - if (m_currentHistoryIndex < 0 || m_currentHistoryIndex >= m_pageHistory.count()) - return -1; - return m_pageHistory.at(m_currentHistoryIndex)->page; -} - -/*! - \qmlproperty point PdfNavigationStack::currentLocation - - This property holds the current location on the page that is being viewed. -*/ -QPointF QQuickPdfNavigationStack::currentLocation() const -{ - if (m_currentHistoryIndex < 0 || m_currentHistoryIndex >= m_pageHistory.count()) - return QPointF(); - return m_pageHistory.at(m_currentHistoryIndex)->location; -} - -/*! - \qmlproperty real PdfNavigationStack::currentZoom - - This property holds the magnification scale on the page that is being viewed. -*/ -qreal QQuickPdfNavigationStack::currentZoom() const -{ - if (m_currentHistoryIndex < 0 || m_currentHistoryIndex >= m_pageHistory.count()) - return 1; - return m_pageHistory.at(m_currentHistoryIndex)->zoom; -} - -/*! - \qmlmethod void PdfNavigationStack::push(int page, point location, qreal zoom) - - Adds the given destination, consisting of \a page, \a location and \a zoom, - to the history of visited locations. If \a emitJumped is \c false, the - \l jumped() signal will not be emitted. - - If forwardAvailable is \c true, calling this function represents a branch - in the timeline which causes the "future" to be lost, and therefore - forwardAvailable will change to \c false. -*/ -void QQuickPdfNavigationStack::push(int page, QPointF location, qreal zoom, bool emitJumped) -{ - if (page == currentPage() && location == currentLocation() && zoom == currentZoom()) - return; - if (qFuzzyIsNull(zoom)) - zoom = currentZoom(); - bool backAvailableWas = backAvailable(); - bool forwardAvailableWas = forwardAvailable(); - if (!m_changing) { - if (m_currentHistoryIndex >= 0 && forwardAvailableWas) - m_pageHistory.remove(m_currentHistoryIndex + 1, m_pageHistory.count() - m_currentHistoryIndex - 1); - m_pageHistory.append(QExplicitlySharedDataPointer(new QPdfDestinationPrivate(page, location, zoom))); - m_currentHistoryIndex = m_pageHistory.count() - 1; - } - emit currentZoomChanged(); - emit currentPageChanged(); - emit currentLocationChanged(); - if (m_changing) - return; - if (!backAvailableWas) - emit backAvailableChanged(); - if (forwardAvailableWas) - emit forwardAvailableChanged(); - if (emitJumped) - emit jumped(page, location, zoom); - qCDebug(qLcNav) << "push: index" << m_currentHistoryIndex << "page" << page - << "@" << location << "zoom" << zoom << "-> history" << - [this]() { - QStringList ret; - for (auto d : m_pageHistory) - ret << QString::number(d->page); - return ret.join(','); - }(); -} - -/*! - \qmlmethod void PdfNavigationStack::update(int page, point location, qreal zoom) - - Modifies the current destination, consisting of \a page, \a location and \a zoom. - - This can be called periodically while the user is manually moving around - the document, so that after back() is called, forward() will jump back to - the most-recently-viewed destination rather than the destination that was - last specified by push(). - - The \c currentZoomChanged, \c currentPageChanged and \c currentLocationChanged - signals will be emitted if the respective properties are actually changed. - The \l jumped signal is not emitted, because this operation - represents smooth movement rather than a navigational jump. -*/ -void QQuickPdfNavigationStack::update(int page, QPointF location, qreal zoom) -{ - if (m_currentHistoryIndex < 0 || m_currentHistoryIndex >= m_pageHistory.count()) - return; - int currentPageWas = currentPage(); - QPointF currentLocationWas = currentLocation(); - qreal currentZoomWas = currentZoom(); - if (page == currentPageWas && location == currentLocationWas && zoom == currentZoomWas) - return; - m_pageHistory[m_currentHistoryIndex]->page = page; - m_pageHistory[m_currentHistoryIndex]->location = location; - m_pageHistory[m_currentHistoryIndex]->zoom = zoom; - if (currentZoomWas != zoom) - emit currentZoomChanged(); - if (currentPageWas != page) - emit currentPageChanged(); - if (currentLocationWas != location) - emit currentLocationChanged(); - qCDebug(qLcNav) << "update: index" << m_currentHistoryIndex << "page" << page - << "@" << location << "zoom" << zoom << "-> history" << - [this]() { - QStringList ret; - for (auto d : m_pageHistory) - ret << QString::number(d->page); - return ret.join(','); - }(); -} - -bool QQuickPdfNavigationStack::backAvailable() const -{ - return m_currentHistoryIndex > 0; -} - -bool QQuickPdfNavigationStack::forwardAvailable() const -{ - return m_currentHistoryIndex < m_pageHistory.count() - 1; -} - -/*! - \qmlsignal PdfNavigationStack::jumped(int page, point location, qreal zoom) - - This signal is emitted when forward(), back() or push() is called, but not - when update() is called. -*/ - -QT_END_NAMESPACE diff --git a/src/pdf/quick/qquickpdfnavigationstack_p.h b/src/pdf/quick/qquickpdfnavigationstack_p.h deleted file mode 100644 index 5df00add5..000000000 --- a/src/pdf/quick/qquickpdfnavigationstack_p.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQUICKPDFNAVIGATIONSTACK_P_H -#define QQUICKPDFNAVIGATIONSTACK_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qquickpdfdocument_p.h" -#include "../api/qpdfdestination_p.h" - -#include - -QT_BEGIN_NAMESPACE - -class QQuickPdfNavigationStack : public QObject -{ - Q_OBJECT - Q_PROPERTY(int currentPage READ currentPage NOTIFY currentPageChanged) - Q_PROPERTY(QPointF currentLocation READ currentLocation NOTIFY currentLocationChanged) - Q_PROPERTY(qreal currentZoom READ currentZoom NOTIFY currentZoomChanged) - Q_PROPERTY(bool backAvailable READ backAvailable NOTIFY backAvailableChanged) - Q_PROPERTY(bool forwardAvailable READ forwardAvailable NOTIFY forwardAvailableChanged) - -public: - explicit QQuickPdfNavigationStack(QObject *parent = nullptr); - - Q_INVOKABLE void push(int page, QPointF location, qreal zoom, bool emitJumped = true); - Q_INVOKABLE void update(int page, QPointF location, qreal zoom); - Q_INVOKABLE void forward(); - Q_INVOKABLE void back(); - - int currentPage() const; - QPointF currentLocation() const; - qreal currentZoom() const; - - bool backAvailable() const; - bool forwardAvailable() const; - -Q_SIGNALS: - void currentPageChanged(); - void currentLocationChanged(); - void currentZoomChanged(); - void backAvailableChanged(); - void forwardAvailableChanged(); - void jumped(int page, QPointF location, qreal zoom); - -private: - QList> m_pageHistory; - int m_currentHistoryIndex = 0; - bool m_changing = false; - - Q_DISABLE_COPY(QQuickPdfNavigationStack) -}; - -QT_END_NAMESPACE - -QML_DECLARE_TYPE(QQuickPdfNavigationStack) - -#endif // QQUICKPDFNAVIGATIONSTACK_P_H diff --git a/src/pdf/quick/qquickpdfsearchmodel.cpp b/src/pdf/quick/qquickpdfsearchmodel.cpp deleted file mode 100644 index d91ca69f8..000000000 --- a/src/pdf/quick/qquickpdfsearchmodel.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qquickpdfsearchmodel_p.h" -#include - -QT_BEGIN_NAMESPACE - -Q_LOGGING_CATEGORY(qLcSearch, "qt.pdf.search") - -/*! - \qmltype PdfSearchModel - \instantiates QQuickPdfSearchModel - \inqmlmodule QtQuick.Pdf - \ingroup pdf - \brief A representation of text search results within a PDF Document. - \since 5.15 - - PdfSearchModel provides the ability to search for text strings within a - document and get the geometric locations of matches on each page. -*/ - -QQuickPdfSearchModel::QQuickPdfSearchModel(QObject *parent) - : QPdfSearchModel(parent) -{ - connect(this, &QPdfSearchModel::searchStringChanged, - this, &QQuickPdfSearchModel::onResultsChanged); -} - -QQuickPdfDocument *QQuickPdfSearchModel::document() const -{ - return m_quickDocument; -} - -void QQuickPdfSearchModel::setDocument(QQuickPdfDocument *document) -{ - if (document == m_quickDocument || !document) - return; - - m_quickDocument = document; - QPdfSearchModel::setDocument(&document->m_doc); -} - -/*! - \qmlproperty list> PdfSearchModel::currentResultBoundingPolygons - - A set of paths in a form that can be bound to the \c paths property of a - \l {QtQuick::PathMultiline}{PathMultiline} instance to render a batch of - rectangles around the regions comprising the search result \l currentResult - on \l currentPage. This is normally used to highlight one search result - at a time, in a UI that allows stepping through the results: - - \qml - PdfDocument { - id: doc - } - PdfSearchModel { - id: searchModel - document: doc - currentPage: view.currentPage - currentResult: ... - } - Shape { - ShapePath { - PathMultiline { - paths: searchModel.currentResultBoundingPolygons - } - } - } - \endqml - - \sa PathMultiline -*/ -QList QQuickPdfSearchModel::currentResultBoundingPolygons() const -{ - QList ret; - const auto &results = const_cast(this)->resultsOnPage(m_currentPage); - if (m_currentResult < 0 || m_currentResult >= results.count()) - return ret; - const auto result = results[m_currentResult]; - for (auto rect : result.rectangles()) - ret << QPolygonF(rect); - return ret; -} - -/*! - \qmlproperty point PdfSearchModel::currentResultBoundingRect - - The bounding box containing all \l currentResultBoundingPolygons. - - When this property changes, a scrollable view should automatically scroll - itself in such a way as to ensure that this region is visible; for example, - it could try to position the upper-left corner near the upper-left of its - own viewport, subject to the constraints of the scrollable area. -*/ -QRectF QQuickPdfSearchModel::currentResultBoundingRect() const -{ - QRectF ret; - const auto &results = const_cast(this)->resultsOnPage(m_currentPage); - if (m_currentResult < 0 || m_currentResult >= results.count()) - return ret; - auto rects = results[m_currentResult].rectangles(); - ret = rects.takeFirst(); - for (auto rect : rects) - ret = ret.united(rect); - return ret; -} - -void QQuickPdfSearchModel::onResultsChanged() -{ - emit currentPageBoundingPolygonsChanged(); - emit currentResultBoundingPolygonsChanged(); -} - -/*! - \qmlproperty list> PdfSearchModel::currentPageBoundingPolygons - - A set of paths in a form that can be bound to the \c paths property of a - \l {QtQuick::PathMultiline}{PathMultiline} instance to render a batch of - rectangles around all the regions where search results are found on - \l currentPage: - - \qml - PdfDocument { - id: doc - } - PdfSearchModel { - id: searchModel - document: doc - } - Shape { - ShapePath { - PathMultiline { - paths: searchModel.matchGeometry(view.currentPage) - } - } - } - \endqml - - \sa PathMultiline -*/ -QList QQuickPdfSearchModel::currentPageBoundingPolygons() const -{ - return const_cast(this)->boundingPolygonsOnPage(m_currentPage); -} - -/*! - \qmlfunction list> PdfSearchModel::boundingPolygonsOnPage(int page) - - Returns a set of paths in a form that can be bound to the \c paths property of a - \l {QtQuick::PathMultiline}{PathMultiline} instance to render a batch of - rectangles around all the locations where search results are found: - - \qml - PdfDocument { - id: doc - } - PdfSearchModel { - id: searchModel - document: doc - } - Shape { - ShapePath { - PathMultiline { - paths: searchModel.matchGeometry(view.currentPage) - } - } - } - \endqml - - \sa PathMultiline -*/ -QList QQuickPdfSearchModel::boundingPolygonsOnPage(int page) -{ - if (!document() || searchString().isEmpty() || page < 0 || page > document()->pageCount()) - return {}; - - updatePage(page); - - QList ret; - auto m = QPdfSearchModel::resultsOnPage(page); - for (auto result : m) { - for (auto rect : result.rectangles()) - ret << QPolygonF(rect); - } - - return ret; -} - -/*! - \qmlproperty int PdfSearchModel::currentPage - - The page on which \l currentMatchGeometry should provide filtered search results. -*/ -void QQuickPdfSearchModel::setCurrentPage(int currentPage) -{ - if (m_currentPage == currentPage) - return; - - if (currentPage < 0) - currentPage = document()->pageCount() - 1; - else if (currentPage >= document()->pageCount()) - currentPage = 0; - - m_currentPage = currentPage; - if (!m_suspendSignals) { - emit currentPageChanged(); - onResultsChanged(); - } -} - -/*! - \qmlproperty int PdfSearchModel::currentResult - - The result index on \l currentPage for which \l currentResultBoundingPolygons - should provide the regions to highlight. -*/ -void QQuickPdfSearchModel::setCurrentResult(int currentResult) -{ - if (m_currentResult == currentResult) - return; - - int currentResultWas = currentResult; - int currentPageWas = m_currentPage; - if (currentResult < 0) { - setCurrentPage(m_currentPage - 1); - while (resultsOnPage(m_currentPage).count() == 0 && m_currentPage != currentPageWas) { - m_suspendSignals = true; - setCurrentPage(m_currentPage - 1); - } - if (m_suspendSignals) { - emit currentPageChanged(); - m_suspendSignals = false; - } - const auto results = resultsOnPage(m_currentPage); - currentResult = results.count() - 1; - } else { - const auto results = resultsOnPage(m_currentPage); - if (currentResult >= results.count()) { - setCurrentPage(m_currentPage + 1); - while (resultsOnPage(m_currentPage).count() == 0 && m_currentPage != currentPageWas) { - m_suspendSignals = true; - setCurrentPage(m_currentPage + 1); - } - if (m_suspendSignals) { - emit currentPageChanged(); - m_suspendSignals = false; - } - currentResult = 0; - } - } - qCDebug(qLcSearch) << "currentResult was" << m_currentResult - << "requested" << currentResultWas << "on page" << currentPageWas - << "->" << currentResult << "on page" << m_currentPage; - - m_currentResult = currentResult; - emit currentResultChanged(); - emit currentResultBoundingPolygonsChanged(); - emit currentResultBoundingRectChanged(); -} - -/*! - \qmlproperty string PdfSearchModel::searchString - - The string to search for. -*/ - -QT_END_NAMESPACE diff --git a/src/pdf/quick/qquickpdfsearchmodel_p.h b/src/pdf/quick/qquickpdfsearchmodel_p.h deleted file mode 100644 index 3f0f6f4c1..000000000 --- a/src/pdf/quick/qquickpdfsearchmodel_p.h +++ /dev/null @@ -1,113 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQUICKPDFSEARCHMODEL_P_H -#define QQUICKPDFSEARCHMODEL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qquickpdfdocument_p.h" -#include "../api/qpdfsearchmodel.h" - -#include -#include - -QT_BEGIN_NAMESPACE - -class QQuickPdfSearchModel : public QPdfSearchModel -{ - Q_OBJECT - Q_PROPERTY(QQuickPdfDocument *document READ document WRITE setDocument NOTIFY documentChanged) - Q_PROPERTY(int currentPage READ currentPage WRITE setCurrentPage NOTIFY currentPageChanged) - Q_PROPERTY(int currentResult READ currentResult WRITE setCurrentResult NOTIFY currentResultChanged) - Q_PROPERTY(QList currentPageBoundingPolygons READ currentPageBoundingPolygons NOTIFY currentPageBoundingPolygonsChanged) - Q_PROPERTY(QList currentResultBoundingPolygons READ currentResultBoundingPolygons NOTIFY currentResultBoundingPolygonsChanged) - Q_PROPERTY(QRectF currentResultBoundingRect READ currentResultBoundingRect NOTIFY currentResultBoundingRectChanged) - -public: - explicit QQuickPdfSearchModel(QObject *parent = nullptr); - - QQuickPdfDocument *document() const; - void setDocument(QQuickPdfDocument * document); - - Q_INVOKABLE QList boundingPolygonsOnPage(int page); - - int currentPage() const { return m_currentPage; } - void setCurrentPage(int currentPage); - - int currentResult() const { return m_currentResult; } - void setCurrentResult(int currentResult); - - QList currentPageBoundingPolygons() const; - QList currentResultBoundingPolygons() const; - QRectF currentResultBoundingRect() const; - -signals: - void documentChanged(); - void currentPageChanged(); - void currentResultChanged(); - void currentPageBoundingPolygonsChanged(); - void currentResultBoundingPolygonsChanged(); - void currentResultBoundingRectChanged(); - -private: - void updateResults(); - void onResultsChanged(); - -private: - QQuickPdfDocument *m_quickDocument = nullptr; - int m_currentPage = 0; - int m_currentResult = 0; - bool m_suspendSignals = false; - - Q_DISABLE_COPY(QQuickPdfSearchModel) -}; - -QT_END_NAMESPACE - -QML_DECLARE_TYPE(QQuickPdfSearchModel) -QML_DECLARE_TYPE(QPdfSelection) - -#endif // QQUICKPDFSEARCHMODEL_P_H diff --git a/src/pdf/quick/qquickpdfselection.cpp b/src/pdf/quick/qquickpdfselection.cpp deleted file mode 100644 index bdedb4dfb..000000000 --- a/src/pdf/quick/qquickpdfselection.cpp +++ /dev/null @@ -1,541 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qquickpdfselection_p.h" -#include "qquickpdfdocument_p.h" -#include -#include -#include -#include -#include -#include -#include -#include - -Q_LOGGING_CATEGORY(qLcIm, "qt.pdf.im") - -QT_BEGIN_NAMESPACE - -static const QRegularExpression WordDelimiter("\\s"); - -/*! - \qmltype PdfSelection - \instantiates QQuickPdfSelection - \inqmlmodule QtQuick.Pdf - \ingroup pdf - \brief A representation of a text selection within a PDF Document. - \since 5.15 - - PdfSelection provides the text string and its geometry within a bounding box - from one point to another. - - To modify the selection using the mouse, bind \l fromPoint and \l toPoint - to the suitable properties of an input handler so that they will be set to - the positions where the drag gesture begins and ends, respectively; and - bind the \l hold property so that it will be set to \c true during the drag - gesture and \c false when the gesture ends. - - PdfSelection also directly handles Input Method queries so that text - selection handles can be used on platforms such as iOS. For this purpose, - it must have keyboard focus. -*/ - -/*! - Constructs a SearchModel. -*/ -QQuickPdfSelection::QQuickPdfSelection(QQuickItem *parent) - : QQuickItem(parent) -{ -#if QT_CONFIG(im) - setFlags(ItemIsFocusScope | ItemAcceptsInputMethod); - // workaround to get Copy instead of Paste on the popover menu (QTBUG-83811) - setProperty("qt_im_readonly", QVariant(true)); -#endif -} - -QQuickPdfDocument *QQuickPdfSelection::document() const -{ - return m_document; -} - -void QQuickPdfSelection::setDocument(QQuickPdfDocument *document) -{ - if (m_document == document) - return; - - if (m_document) { - disconnect(m_document, &QQuickPdfDocument::sourceChanged, - this, &QQuickPdfSelection::resetPoints); - } - m_document = document; - emit documentChanged(); - resetPoints(); - connect(m_document, &QQuickPdfDocument::sourceChanged, - this, &QQuickPdfSelection::resetPoints); -} - -/*! - \qmlproperty list> PdfSelection::geometry - - A set of paths in a form that can be bound to the \c paths property of a - \l {QtQuick::PathMultiline}{PathMultiline} instance to render a batch of - rectangles around the text regions that are included in the selection: - - \qml - PdfDocument { - id: doc - } - PdfSelection { - id: selection - document: doc - fromPoint: textSelectionDrag.centroid.pressPosition - toPoint: textSelectionDrag.centroid.position - hold: !textSelectionDrag.active - } - Shape { - ShapePath { - PathMultiline { - paths: selection.geometry - } - } - } - DragHandler { - id: textSelectionDrag - acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus - target: null - } - \endqml - - \sa PathMultiline -*/ -QList QQuickPdfSelection::geometry() const -{ - return m_geometry; -} - -void QQuickPdfSelection::clear() -{ - m_hitPoint = QPointF(); - m_fromPoint = QPointF(); - m_toPoint = QPointF(); - m_heightAtAnchor = 0; - m_heightAtCursor = 0; - m_fromCharIndex = -1; - m_toCharIndex = -1; - m_text.clear(); - m_geometry.clear(); - emit fromPointChanged(); - emit toPointChanged(); - emit textChanged(); - emit selectedAreaChanged(); - QGuiApplication::inputMethod()->update(Qt::ImQueryInput); -} - -void QQuickPdfSelection::selectAll() -{ - QPdfSelection sel = m_document->m_doc.getAllText(m_page); - if (sel.text() != m_text) { - m_text = sel.text(); - if (QGuiApplication::clipboard()->supportsSelection()) - sel.copyToClipboard(QClipboard::Selection); - emit textChanged(); - } - - if (sel.bounds() != m_geometry) { - m_geometry = sel.bounds(); - emit selectedAreaChanged(); - } -#if QT_CONFIG(im) - m_fromCharIndex = sel.startIndex(); - m_toCharIndex = sel.endIndex(); - if (sel.bounds().isEmpty()) { - m_fromPoint = QPointF(); - m_toPoint = QPointF(); - } else { - m_fromPoint = sel.bounds().first().boundingRect().topLeft() * m_renderScale; - m_toPoint = sel.bounds().last().boundingRect().bottomRight() * m_renderScale - QPointF(0, m_heightAtCursor); - } - - QGuiApplication::inputMethod()->update(Qt::ImCursorRectangle | Qt::ImAnchorRectangle); -#endif -} - -#if QT_CONFIG(im) -void QQuickPdfSelection::keyReleaseEvent(QKeyEvent *ev) -{ - qCDebug(qLcIm) << "release" << ev; - const auto &allText = pageText(); - if (ev == QKeySequence::MoveToPreviousWord) { - // iOS sends MoveToPreviousWord first to get to the beginning of the word, - // and then SelectNextWord to select the whole word. - int i = allText.lastIndexOf(WordDelimiter, m_fromCharIndex - allText.length()); - if (i < 0) - i = 0; - else - i += 1; // don't select the space before the word - auto sel = m_document->m_doc.getSelectionAtIndex(m_page, i, m_text.length() + m_fromCharIndex - i); - update(sel); - QGuiApplication::inputMethod()->update(Qt::ImAnchorRectangle); - } else if (ev == QKeySequence::SelectNextWord) { - int i = allText.indexOf(WordDelimiter, m_toCharIndex); - if (i < 0) - i = allText.length(); // go to the end of m_textAfter - auto sel = m_document->m_doc.getSelectionAtIndex(m_page, m_fromCharIndex, m_text.length() + i - m_toCharIndex); - update(sel); - QGuiApplication::inputMethod()->update(Qt::ImCursorRectangle); - } else if (ev == QKeySequence::Copy) { - copyToClipboard(); - } -} - -void QQuickPdfSelection::inputMethodEvent(QInputMethodEvent *event) -{ - for (auto attr : event->attributes()) { - switch (attr.type) { - case QInputMethodEvent::Cursor: - qCDebug(qLcIm) << "QInputMethodEvent::Cursor: moved to" << attr.start << "len" << attr.length; - break; - case QInputMethodEvent::Selection: { - auto sel = m_document->m_doc.getSelectionAtIndex(m_page, attr.start, attr.length); - update(sel); - qCDebug(qLcIm) << "QInputMethodEvent::Selection: from" << attr.start << "len" << attr.length - << "result:" << m_fromCharIndex << "->" << m_toCharIndex << sel.boundingRectangle(); - // the iOS plugin decided that it wanted to change the selection, but still has to be told to move the handles (!?) - QGuiApplication::inputMethod()->update(Qt::ImCursorRectangle | Qt::ImAnchorRectangle); - break; - } - case QInputMethodEvent::Language: - case QInputMethodEvent::Ruby: - case QInputMethodEvent::TextFormat: - break; - } - } -} - -QVariant QQuickPdfSelection::inputMethodQuery(Qt::InputMethodQuery query, const QVariant &argument) const -{ - if (!argument.isNull()) { - qCDebug(qLcIm) << "IM query" << query << "with arg" << argument; - if (query == Qt::ImCursorPosition) { - // If it didn't move since last time, return the same result. - if (m_hitPoint == argument.toPointF()) - return inputMethodQuery(query); - m_hitPoint = argument.toPointF(); - auto tp = m_document->m_doc.d->hitTest(m_page, m_hitPoint / m_renderScale); - qCDebug(qLcIm) << "ImCursorPosition hit testing in px" << m_hitPoint << "pt" << (m_hitPoint / m_renderScale) - << "got char index" << tp.charIndex << "@" << tp.position << "pt," << tp.position * m_renderScale << "px"; - if (tp.charIndex >= 0) { - m_toCharIndex = tp.charIndex; - m_toPoint = tp.position * m_renderScale - QPointF(0, m_heightAtCursor); - m_heightAtCursor = tp.height * m_renderScale; - if (qFuzzyIsNull(m_heightAtAnchor)) - m_heightAtAnchor = m_heightAtCursor; - } - } - } - return inputMethodQuery(query); -} - -QVariant QQuickPdfSelection::inputMethodQuery(Qt::InputMethodQuery query) const -{ - QVariant ret; - switch (query) { - case Qt::ImEnabled: - ret = true; - break; - case Qt::ImHints: - ret = QVariant(Qt::ImhMultiLine | Qt::ImhNoPredictiveText); - break; - case Qt::ImInputItemClipRectangle: - ret = boundingRect(); - break; - case Qt::ImAnchorPosition: - ret = m_fromCharIndex; - break; - case Qt::ImAbsolutePosition: - ret = m_toCharIndex; - break; - case Qt::ImCursorPosition: - ret = m_toCharIndex; - break; - case Qt::ImAnchorRectangle: - ret = QRectF(m_fromPoint, QSizeF(1, m_heightAtAnchor)); - break; - case Qt::ImCursorRectangle: - ret = QRectF(m_toPoint, QSizeF(1, m_heightAtCursor)); - break; - case Qt::ImSurroundingText: - ret = QVariant(pageText()); - break; - case Qt::ImTextBeforeCursor: - ret = QVariant(pageText().mid(0, m_toCharIndex)); - break; - case Qt::ImTextAfterCursor: - ret = QVariant(pageText().mid(m_toCharIndex)); - break; - case Qt::ImCurrentSelection: - ret = QVariant(m_text); - break; - case Qt::ImEnterKeyType: - break; - case Qt::ImFont: { - QFont font = QGuiApplication::font(); - font.setPointSizeF(m_heightAtCursor); - ret = font; - break; - } - case Qt::ImMaximumTextLength: - break; - case Qt::ImPreferredLanguage: - break; - case Qt::ImPlatformData: - break; - case Qt::ImQueryInput: - case Qt::ImQueryAll: - qWarning() << "unexpected composite query"; - break; - } - qCDebug(qLcIm) << "IM query" << query << "returns" << ret; - return ret; -} -#endif // QT_CONFIG(im) - -const QString &QQuickPdfSelection::pageText() const -{ - if (m_pageTextDirty) { - m_pageText = m_document->m_doc.getAllText(m_page).text(); - m_pageTextDirty = false; - } - return m_pageText; -} - -void QQuickPdfSelection::resetPoints() -{ - bool wasHolding = m_hold; - m_hold = false; - setFromPoint(QPointF()); - setToPoint(QPointF()); - m_hold = wasHolding; -} - -/*! - \qmlproperty int PdfSelection::page - - The page number on which to search. - - \sa QtQuick::Image::currentFrame -*/ -int QQuickPdfSelection::page() const -{ - return m_page; -} - -void QQuickPdfSelection::setPage(int page) -{ - if (m_page == page) - return; - - m_page = page; - m_pageTextDirty = true; - emit pageChanged(); - resetPoints(); -} - -/*! - \qmlproperty real PdfSelection::renderScale - \brief The ratio from points to pixels at which the page is rendered. - - This is used to scale \l fromPoint and \l toPoint to find ranges of - selected characters in the document, because positions within the document - are always given in points. -*/ -qreal QQuickPdfSelection::renderScale() const -{ - return m_renderScale; -} - -void QQuickPdfSelection::setRenderScale(qreal scale) -{ - if (qFuzzyCompare(scale, m_renderScale)) - return; - - m_renderScale = scale; - emit renderScaleChanged(); - updateResults(); -} - -/*! - \qmlproperty point PdfSelection::fromPoint - - The beginning location, in pixels from the upper-left corner of the page, - from which to find selected text. This can be bound to the - \c centroid.pressPosition of a \l DragHandler to begin selecting text from - the position where the user presses the mouse button and begins dragging, - for example. -*/ -QPointF QQuickPdfSelection::fromPoint() const -{ - return m_fromPoint; -} - -void QQuickPdfSelection::setFromPoint(QPointF fromPoint) -{ - if (m_hold || m_fromPoint == fromPoint) - return; - - m_fromPoint = fromPoint; - emit fromPointChanged(); - updateResults(); -} - -/*! - \qmlproperty point PdfSelection::toPoint - - The ending location, in pixels from the upper-left corner of the page, - from which to find selected text. This can be bound to the - \c centroid.position of a \l DragHandler to end selection of text at the - position where the user is currently dragging the mouse, for example. -*/ -QPointF QQuickPdfSelection::toPoint() const -{ - return m_toPoint; -} - -void QQuickPdfSelection::setToPoint(QPointF toPoint) -{ - if (m_hold || m_toPoint == toPoint) - return; - - m_toPoint = toPoint; - emit toPointChanged(); - updateResults(); -} - -/*! - \qmlproperty bool PdfSelection::hold - - Controls whether to hold the existing selection regardless of changes to - \l fromPoint and \l toPoint. This property can be set to \c true when the mouse - or touchpoint is released, so that the selection is not lost due to the - point bindings changing. -*/ -bool QQuickPdfSelection::hold() const -{ - return m_hold; -} - -void QQuickPdfSelection::setHold(bool hold) -{ - if (m_hold == hold) - return; - - m_hold = hold; - emit holdChanged(); -} - -/*! - \qmlproperty string PdfSelection::string - - The string found. -*/ -QString QQuickPdfSelection::text() const -{ - return m_text; -} - -#if QT_CONFIG(clipboard) -/*! - \qmlmethod void PdfSelection::copyToClipboard() - - Copies plain text from the \l string property to the system clipboard. -*/ -void QQuickPdfSelection::copyToClipboard() const -{ - QGuiApplication::clipboard()->setText(m_text); -} -#endif - -void QQuickPdfSelection::updateResults() -{ - if (!m_document) - return; - QPdfSelection sel = m_document->document().getSelection(m_page, - m_fromPoint / m_renderScale, m_toPoint / m_renderScale); - update(sel, true); -} - -void QQuickPdfSelection::update(const QPdfSelection &sel, bool textAndGeometryOnly) -{ - if (sel.text() != m_text) { - m_text = sel.text(); - if (QGuiApplication::clipboard()->supportsSelection()) - sel.copyToClipboard(QClipboard::Selection); - emit textChanged(); - } - - if (sel.bounds() != m_geometry) { - m_geometry = sel.bounds(); - emit selectedAreaChanged(); - } - - if (textAndGeometryOnly) - return; - - m_fromCharIndex = sel.startIndex(); - m_toCharIndex = sel.endIndex(); - if (sel.bounds().isEmpty()) { - m_fromPoint = sel.boundingRectangle().topLeft() * m_renderScale; - m_toPoint = m_fromPoint; - } else { - Qt::InputMethodQueries toUpdate = {}; - QRectF firstLineBounds = sel.bounds().first().boundingRect(); - m_fromPoint = firstLineBounds.topLeft() * m_renderScale; - if (!qFuzzyCompare(m_heightAtAnchor, firstLineBounds.height())) { - m_heightAtAnchor = firstLineBounds.height() * m_renderScale; - toUpdate.setFlag(Qt::ImAnchorRectangle); - } - QRectF lastLineBounds = sel.bounds().last().boundingRect(); - if (!qFuzzyCompare(m_heightAtCursor, lastLineBounds.height())) { - m_heightAtCursor = lastLineBounds.height() * m_renderScale; - toUpdate.setFlag(Qt::ImCursorRectangle); - } - m_toPoint = lastLineBounds.topRight() * m_renderScale; - if (toUpdate) - QGuiApplication::inputMethod()->update(toUpdate); - } -} - -QT_END_NAMESPACE diff --git a/src/pdf/quick/qquickpdfselection_p.h b/src/pdf/quick/qquickpdfselection_p.h deleted file mode 100644 index 75631a876..000000000 --- a/src/pdf/quick/qquickpdfselection_p.h +++ /dev/null @@ -1,148 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQUICKPDFSELECTION_P_H -#define QQUICKPDFSELECTION_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include -#include -#include - -#include "qquickpdfdocument_p.h" - -QT_BEGIN_NAMESPACE -class QPdfSelection; - -class QQuickPdfSelection : public QQuickItem -{ - Q_OBJECT - Q_PROPERTY(QQuickPdfDocument *document READ document WRITE setDocument NOTIFY documentChanged) - Q_PROPERTY(int page READ page WRITE setPage NOTIFY pageChanged) - Q_PROPERTY(qreal renderScale READ renderScale WRITE setRenderScale NOTIFY renderScaleChanged) - Q_PROPERTY(QPointF fromPoint READ fromPoint WRITE setFromPoint NOTIFY fromPointChanged) - Q_PROPERTY(QPointF toPoint READ toPoint WRITE setToPoint NOTIFY toPointChanged) - Q_PROPERTY(bool hold READ hold WRITE setHold NOTIFY holdChanged) - - Q_PROPERTY(QString text READ text NOTIFY textChanged) - Q_PROPERTY(QList geometry READ geometry NOTIFY selectedAreaChanged) - -public: - explicit QQuickPdfSelection(QQuickItem *parent = nullptr); - - QQuickPdfDocument *document() const; - void setDocument(QQuickPdfDocument * document); - int page() const; - void setPage(int page); - qreal renderScale() const; - void setRenderScale(qreal scale); - QPointF fromPoint() const; - void setFromPoint(QPointF fromPoint); - QPointF toPoint() const; - void setToPoint(QPointF toPoint); - bool hold() const; - void setHold(bool hold); - - QString text() const; - QList geometry() const; - - Q_INVOKABLE void clear(); - Q_INVOKABLE void selectAll(); -#if QT_CONFIG(clipboard) - Q_INVOKABLE void copyToClipboard() const; -#endif - -signals: - void documentChanged(); - void pageChanged(); - void renderScaleChanged(); - void fromPointChanged(); - void toPointChanged(); - void holdChanged(); - void textChanged(); - void selectedAreaChanged(); - -protected: -#if QT_CONFIG(im) - void keyReleaseEvent(QKeyEvent *ev) override; - void inputMethodEvent(QInputMethodEvent *event) override; - Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, const QVariant &argument) const; - QVariant inputMethodQuery(Qt::InputMethodQuery query) const override; -#endif - -private: - void resetPoints(); - void updateResults(); - void update(const QPdfSelection &sel, bool textAndGeometryOnly = false); - const QString &pageText() const; - -private: - QQuickPdfDocument *m_document = nullptr; - mutable QPointF m_hitPoint; - QPointF m_fromPoint; - mutable QPointF m_toPoint; - qreal m_renderScale = 1; - mutable qreal m_heightAtAnchor = 0; - mutable qreal m_heightAtCursor = 0; - QString m_text; // selected text - mutable QString m_pageText; // all text on the page - QList m_geometry; - int m_page = 0; - int m_fromCharIndex = -1; // same as anchor position - mutable int m_toCharIndex = -1; // same as cursor position - bool m_hold = false; - mutable bool m_pageTextDirty = true; - - Q_DISABLE_COPY(QQuickPdfSelection) -}; - -QT_END_NAMESPACE - -QML_DECLARE_TYPE(QQuickPdfSelection) - -#endif // QQUICKPDFSELECTION_P_H diff --git a/src/pdf/quick/qquicktableviewextra.cpp b/src/pdf/quick/qquicktableviewextra.cpp deleted file mode 100644 index 017764a95..000000000 --- a/src/pdf/quick/qquicktableviewextra.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qquicktableviewextra_p.h" -#include -#include - -Q_LOGGING_CATEGORY(qLcTVE, "qt.pdf.tableextra") - -QT_BEGIN_NAMESPACE - -/*! - \internal - \qmltype TableViewExtra - \instantiates QQuickTableViewExtra - \inqmlmodule QtQuick.Pdf - \ingroup pdf - \brief A helper class with missing TableView functions - \since 5.15 - - TableViewExtra provides equivalents for some functions that will be added - to TableView in Qt 6. -*/ - -QQuickTableViewExtra::QQuickTableViewExtra(QObject *parent) : QObject(parent) -{ -} - -QPoint QQuickTableViewExtra::cellAtPos(qreal x, qreal y) const -{ - QPointF position(x, y); - return m_tableView->cellAtPos(position); -} - -QQuickItem *QQuickTableViewExtra::itemAtCell(const QPoint &cell) const -{ - return m_tableView->itemAtCell(cell); -} - -void QQuickTableViewExtra::positionViewAtCell(const QPoint &cell, Qt::Alignment alignment, const QPointF &offset) -{ - m_tableView->positionViewAtCell(cell, alignment, offset); -} - -QT_END_NAMESPACE diff --git a/src/pdf/quick/qquicktableviewextra_p.h b/src/pdf/quick/qquicktableviewextra_p.h deleted file mode 100644 index 11b4955a1..000000000 --- a/src/pdf/quick/qquicktableviewextra_p.h +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQUICKTABLEVIEWEXTRA_P_H -#define QQUICKTABLEVIEWEXTRA_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class QQuickTableViewExtra : public QObject -{ - Q_OBJECT - Q_PROPERTY(QQuickTableView *tableView READ tableView WRITE setTableView) - -public: - QQuickTableViewExtra(QObject *parent = nullptr); - - QQuickTableView * tableView() const { return m_tableView; } - void setTableView(QQuickTableView * tableView) { m_tableView = tableView; } - - Q_INVOKABLE QPoint cellAtPos(qreal x, qreal y) const; - Q_INVOKABLE QQuickItem *itemAtCell(int column, int row) const { - return itemAtCell(QPoint(column, row)); - } - Q_INVOKABLE QQuickItem *itemAtCell(const QPoint &cell) const; - Q_INVOKABLE void positionViewAtCell(int column, int row, Qt::Alignment alignment, const QPointF &offset = QPointF()) { - positionViewAtCell(QPoint(column, row), alignment, offset); - } - Q_INVOKABLE void positionViewAtCell(const QPoint &cell, Qt::Alignment alignment, const QPointF &offset); - Q_INVOKABLE void positionViewAtRow(int row, Qt::Alignment alignment, qreal offset = 0) { - positionViewAtCell(QPoint(0, row), alignment & Qt::AlignVertical_Mask, QPointF(0, offset)); - } - -private: - QQuickTableView *m_tableView = nullptr; -}; - -QT_END_NAMESPACE - -QML_DECLARE_TYPE(QQuickTableViewExtra) - -#endif // QQUICKTABLEVIEWEXTRA_P_H diff --git a/src/pdfquick/CMakeLists.txt b/src/pdfquick/CMakeLists.txt new file mode 100644 index 000000000..12cb393ff --- /dev/null +++ b/src/pdfquick/CMakeLists.txt @@ -0,0 +1,55 @@ +find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS Core Gui Qml Quick) + +get_configure_mode(configureMode) + +set(qml_files +# TODO: +# "qml/+material/PdfStyle.qml" +# "qml/+universal/PdfStyle.qml" + "qml/PdfMultiPageView.qml" + "qml/PdfPageView.qml" + "qml/PdfScrollablePageView.qml" + "qml/PdfStyle.qml" +) + +qt_internal_add_qml_module(PdfQuick + URI "QtQuick.Pdf" + VERSION "${PROJECT_VERSION}" + CLASS_NAME QtQuick2PdfPlugin + NO_GENERATE_PLUGIN_SOURCE + NO_PLUGIN_OPTIONAL + NO_GENERATE_QMLTYPES + PLUGIN_TARGET qtpdfquickplugin + QML_FILES ${qml_files} + DEPENDENCIES QtQuickControls2 + SOURCES + qquickpdfdocument.cpp qquickpdfdocument_p.h + qquickpdflinkmodel.cpp qquickpdflinkmodel_p.h + qquickpdfnavigationstack.cpp qquickpdfnavigationstack_p.h + qquickpdfsearchmodel.cpp qquickpdfsearchmodel_p.h + qquickpdfselection.cpp qquickpdfselection_p.h + qquicktableviewextra.cpp qquicktableviewextra_p.h + qtpdfquickglobal_p.h + INCLUDE_DIRECTORIES + ../3rdparty/chromium + PUBLIC_LIBRARIES + Qt::QuickPrivate + Qt::PdfPrivate + Qt::Core + Qt::Gui + Qt::Qml +) + +qt_internal_extend_target(qtpdfquickplugin + SOURCES + plugin.cpp + LIBRARIES + Qt::CorePrivate + Qt::PdfQuickPrivate +) + +make_install_only(PdfQuick) +make_install_only(qtpdfquickplugin) + + + diff --git a/src/pdfquick/plugin.cpp b/src/pdfquick/plugin.cpp new file mode 100644 index 000000000..23f32bc39 --- /dev/null +++ b/src/pdfquick/plugin.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include "qquickpdfdocument_p.h" +#include "qquickpdflinkmodel_p.h" +#include "qquickpdfnavigationstack_p.h" +#include "qquickpdfsearchmodel_p.h" +#include "qquickpdfselection_p.h" +#include "qquicktableviewextra_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \qmlmodule QtQuick.Pdf + \title Qt Quick PDF QML Types + \ingroup qmlmodules + \brief Provides QML types for handling PDF documents. + + This QML module contains types for handling PDF documents. + + To use the types in this module, import the module with the following line: + + \code + import QtQuick.Pdf + \endcode +*/ + +class QtQuick2PdfPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) + +public: + QtQuick2PdfPlugin() : QQmlExtensionPlugin() { } + + void initializeEngine(QQmlEngine *engine, const char *uri) override { + Q_UNUSED(uri); +#ifdef QT_STATIC + Q_UNUSED(engine); +#else + engine->addImportPath(QStringLiteral("qrc:/")); +#endif + } + + void registerTypes(const char *uri) override { + Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.Pdf")); + + // Register the latest version, even if there are no new types or new revisions for existing types yet. + qmlRegisterModule(uri, 2, QT_VERSION_MINOR); + + qmlRegisterType(uri, 5, 15, "PdfDocument"); + qmlRegisterType(uri, 5, 15, "PdfLinkModel"); + qmlRegisterType(uri, 5, 15, "PdfNavigationStack"); + qmlRegisterType(uri, 5, 15, "PdfSearchModel"); + qmlRegisterType(uri, 5, 15, "PdfSelection"); + qmlRegisterType(uri, 5, 15, "TableViewExtra"); + } +}; + +QT_END_NAMESPACE + +#include "plugin.moc" diff --git a/src/pdfquick/plugins.qmltypes b/src/pdfquick/plugins.qmltypes new file mode 100644 index 000000000..a30361d33 --- /dev/null +++ b/src/pdfquick/plugins.qmltypes @@ -0,0 +1,52 @@ +import QtQuick.tooling 1.2 + +// This file describes the plugin-supplied types contained in the library. +// It is used for QML tooling purposes only. +// +// This file was auto-generated by: +// 'qmlplugindump -nonrelocatable QtQuick.Pdf 5.14' + +Module { + dependencies: [ + "QtGraphicalEffects 1.12", + "QtQuick 2.14", + "QtQuick.Controls 2.14", + "QtQuick.Controls.Fusion 2.14", + "QtQuick.Controls.Fusion.impl 2.14", + "QtQuick.Controls.Imagine 2.14", + "QtQuick.Controls.Imagine.impl 2.14", + "QtQuick.Controls.Material 2.14", + "QtQuick.Controls.Material.impl 2.14", + "QtQuick.Controls.Universal 2.14", + "QtQuick.Controls.Universal.impl 2.12", + "QtQuick.Controls.impl 2.14", + "QtQuick.Shapes 1.14", + "QtQuick.Templates 2.14", + "QtQuick.Window 2.2" + ] + Component { + name: "QQuickPdfDocument" + prototype: "QObject" + exports: ["QtQuick.Pdf/PdfDocument 5.14"] + exportMetaObjectRevisions: [0] + Property { name: "source"; type: "QUrl" } + Property { name: "pageCount"; type: "int"; isReadonly: true } + Property { name: "password"; type: "string" } + Property { name: "status"; type: "QPdfDocument::Status"; isReadonly: true } + Property { name: "title"; type: "string"; isReadonly: true } + Property { name: "subject"; type: "string"; isReadonly: true } + Property { name: "author"; type: "string"; isReadonly: true } + Property { name: "keywords"; type: "string"; isReadonly: true } + Property { name: "producer"; type: "string"; isReadonly: true } + Property { name: "creator"; type: "string"; isReadonly: true } + Property { name: "creationDate"; type: "QDateTime"; isReadonly: true } + Property { name: "modificationDate"; type: "QDateTime"; isReadonly: true } + Signal { name: "passwordRequired" } + Signal { name: "metaDataLoaded" } + Method { + name: "pagePointSize" + type: "QSizeF" + Parameter { name: "page"; type: "int" } + } + } +} diff --git a/src/pdfquick/qml/+material/PdfStyle.qml b/src/pdfquick/qml/+material/PdfStyle.qml new file mode 100644 index 000000000..12df30466 --- /dev/null +++ b/src/pdfquick/qml/+material/PdfStyle.qml @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQml 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Controls.Material 2.14 +import QtQuick.Shapes 1.14 + +QtObject { + property Control prototypeControl: Control { } + function withAlpha(color, alpha) { + return Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, alpha) + } + property color selectionColor: withAlpha(prototypeControl.palette.highlight, 0.5) + property color pageSearchResultsColor: withAlpha(Qt.lighter(Material.accentColor, 1.5), 0.5) + property color currentSearchResultStrokeColor: Material.accentColor + property real currentSearchResultStrokeWidth: 2 + property color linkUnderscoreColor: prototypeControl.palette.link + property real linkUnderscoreStrokeWidth: 1 + property var linkUnderscoreStrokeStyle: ShapePath.DashLine + property var linkUnderscoreDashPattern: [ 1, 4 ] +} diff --git a/src/pdfquick/qml/+universal/PdfStyle.qml b/src/pdfquick/qml/+universal/PdfStyle.qml new file mode 100644 index 000000000..e92f2a080 --- /dev/null +++ b/src/pdfquick/qml/+universal/PdfStyle.qml @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQml 2.14 +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Controls.Universal 2.14 +import QtQuick.Shapes 1.14 + +QtObject { + property Control prototypeControl: Control { } + function withAlpha(color, alpha) { + return Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, alpha) + } + property color selectionColor: withAlpha(prototypeControl.palette.highlight, 0.5) + property color pageSearchResultsColor: withAlpha(Qt.lighter(Universal.accent, 1.5), 0.5) + property color currentSearchResultStrokeColor: Universal.accent + property real currentSearchResultStrokeWidth: 2 + property color linkUnderscoreColor: prototypeControl.palette.link + property real linkUnderscoreStrokeWidth: 1 + property var linkUnderscoreStrokeStyle: ShapePath.DashLine + property var linkUnderscoreDashPattern: [ 1, 4 ] +} diff --git a/src/pdfquick/qml/PdfMultiPageView.qml b/src/pdfquick/qml/PdfMultiPageView.qml new file mode 100644 index 000000000..71485c214 --- /dev/null +++ b/src/pdfquick/qml/PdfMultiPageView.qml @@ -0,0 +1,434 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Layouts 1.14 +import QtQuick.Pdf 5.15 +import QtQuick.Shapes 1.14 +import QtQuick.Window 2.14 + +Item { + // public API + // TODO 5.15: required property + property var document: undefined + property bool debug: false + + property string selectedText + function selectAll() { + var currentItem = tableHelper.itemAtCell(tableHelper.cellAtPos(root.width / 2, root.height / 2)) + if (currentItem) + currentItem.selection.selectAll() + } + function copySelectionToClipboard() { + var currentItem = tableHelper.itemAtCell(tableHelper.cellAtPos(root.width / 2, root.height / 2)) + if (debug) + console.log("currentItem", currentItem, "sel", currentItem.selection.text) + if (currentItem) + currentItem.selection.copyToClipboard() + } + + // page navigation + property alias currentPage: navigationStack.currentPage + property alias backEnabled: navigationStack.backAvailable + property alias forwardEnabled: navigationStack.forwardAvailable + function back() { navigationStack.back() } + function forward() { navigationStack.forward() } + function goToPage(page) { + if (page === navigationStack.currentPage) + return + goToLocation(page, Qt.point(-1, -1), 0) + } + function goToLocation(page, location, zoom) { + if (zoom > 0) { + navigationStack.jumping = true // don't call navigationStack.update() because we will push() instead + root.renderScale = zoom + tableView.forceLayout() // but do ensure that the table layout is correct before we try to jump + navigationStack.jumping = false + } + navigationStack.push(page, location, zoom) // actually jump + } + property vector2d jumpLocationMargin: Qt.vector2d(10, 10) // px from top-left corner + property int currentPageRenderingStatus: Image.Null + + // page scaling + property real renderScale: 1 + property real pageRotation: 0 + function resetScale() { root.renderScale = 1 } + function scaleToWidth(width, height) { + root.renderScale = width / (tableView.rot90 ? tableView.firstPagePointSize.height : tableView.firstPagePointSize.width) + } + function scaleToPage(width, height) { + var windowAspect = width / height + var pageAspect = tableView.firstPagePointSize.width / tableView.firstPagePointSize.height + if (tableView.rot90) { + if (windowAspect > pageAspect) { + root.renderScale = height / tableView.firstPagePointSize.width + } else { + root.renderScale = width / tableView.firstPagePointSize.height + } + } else { + if (windowAspect > pageAspect) { + root.renderScale = height / tableView.firstPagePointSize.height + } else { + root.renderScale = width / tableView.firstPagePointSize.width + } + } + } + + // text search + property alias searchModel: searchModel + property alias searchString: searchModel.searchString + function searchBack() { --searchModel.currentResult } + function searchForward() { ++searchModel.currentResult } + + id: root + PdfStyle { id: style } + TableView { + id: tableView + anchors.fill: parent + anchors.leftMargin: 2 + model: modelInUse && root.document !== undefined ? root.document.pageCount : 0 + // workaround to make TableView do scheduleRebuildTable(RebuildOption::All) in cases when forceLayout() doesn't + property bool modelInUse: true + function rebuild() { + modelInUse = false + modelInUse = true + } + // end workaround + rowSpacing: 6 + property real rotationNorm: Math.round((360 + (root.pageRotation % 360)) % 360) + property bool rot90: rotationNorm == 90 || rotationNorm == 270 + onRot90Changed: forceLayout() + property size firstPagePointSize: document === undefined ? Qt.size(0, 0) : document.pagePointSize(0) + property real pageHolderWidth: Math.max(root.width, document === undefined ? 0 : + (rot90 ? document.maxPageHeight : document.maxPageWidth) * root.renderScale) + contentWidth: document === undefined ? 0 : pageHolderWidth + vscroll.width + 2 + rowHeightProvider: function(row) { return (rot90 ? document.pagePointSize(row).width : document.pagePointSize(row).height) * root.renderScale } + TableViewExtra { + id: tableHelper + tableView: tableView + } + delegate: Rectangle { + id: pageHolder + color: root.debug ? "beige" : "transparent" + Text { + visible: root.debug + anchors { right: parent.right; verticalCenter: parent.verticalCenter } + rotation: -90; text: pageHolder.width.toFixed(1) + "x" + pageHolder.height.toFixed(1) + "\n" + + image.width.toFixed(1) + "x" + image.height.toFixed(1) + } + implicitWidth: tableView.pageHolderWidth + implicitHeight: tableView.rot90 ? image.width : image.height + property alias selection: selection + Rectangle { + id: paper + width: image.width + height: image.height + rotation: root.pageRotation + anchors.centerIn: pinch.active ? undefined : parent + property size pagePointSize: document.pagePointSize(index) + property real pageScale: image.paintedWidth / pagePointSize.width + Image { + id: image + source: document.source + currentFrame: index + asynchronous: true + fillMode: Image.PreserveAspectFit + width: paper.pagePointSize.width * root.renderScale + height: paper.pagePointSize.height * root.renderScale + property real renderScale: root.renderScale + property real oldRenderScale: 1 + onRenderScaleChanged: { + image.sourceSize.width = paper.pagePointSize.width * renderScale + image.sourceSize.height = 0 + paper.scale = 1 + searchHighlights.update() + } + onStatusChanged: { + if (index === navigationStack.currentPage) + root.currentPageRenderingStatus = status + } + } + Shape { + anchors.fill: parent + visible: image.status === Image.Ready + onVisibleChanged: searchHighlights.update() + ShapePath { + strokeWidth: -1 + fillColor: style.pageSearchResultsColor + scale: Qt.size(paper.pageScale, paper.pageScale) + PathMultiline { + id: searchHighlights + function update() { + // paths could be a binding, but we need to be able to "kick" it sometimes + paths = searchModel.boundingPolygonsOnPage(index) + } + } + } + Connections { + target: searchModel + // whenever the highlights on the _current_ page change, they actually need to change on _all_ pages + // (usually because the search string has changed) + function onCurrentPageBoundingPolygonsChanged() { searchHighlights.update() } + } + ShapePath { + strokeWidth: -1 + fillColor: style.selectionColor + scale: Qt.size(paper.pageScale, paper.pageScale) + PathMultiline { + paths: selection.geometry + } + } + } + Shape { + anchors.fill: parent + visible: image.status === Image.Ready && searchModel.currentPage === index + ShapePath { + strokeWidth: style.currentSearchResultStrokeWidth + strokeColor: style.currentSearchResultStrokeColor + fillColor: "transparent" + scale: Qt.size(paper.pageScale, paper.pageScale) + PathMultiline { + paths: searchModel.currentResultBoundingPolygons + } + } + } + PinchHandler { + id: pinch + minimumScale: 0.1 + maximumScale: root.renderScale < 4 ? 2 : 1 + minimumRotation: root.pageRotation + maximumRotation: root.pageRotation + enabled: image.sourceSize.width < 5000 + onActiveChanged: + if (active) { + paper.z = 10 + } else { + paper.z = 0 + var centroidInPoints = Qt.point(pinch.centroid.position.x / root.renderScale, + pinch.centroid.position.y / root.renderScale) + var centroidInFlickable = tableView.mapFromItem(paper, pinch.centroid.position.x, pinch.centroid.position.y) + var newSourceWidth = image.sourceSize.width * paper.scale + var ratio = newSourceWidth / image.sourceSize.width + if (root.debug) + console.log("pinch ended on page", index, "with centroid", pinch.centroid.position, centroidInPoints, "wrt flickable", centroidInFlickable, + "page at", pageHolder.x.toFixed(2), pageHolder.y.toFixed(2), + "contentX/Y were", tableView.contentX.toFixed(2), tableView.contentY.toFixed(2)) + if (ratio > 1.1 || ratio < 0.9) { + var centroidOnPage = Qt.point(centroidInPoints.x * root.renderScale * ratio, centroidInPoints.y * root.renderScale * ratio) + paper.scale = 1 + paper.x = 0 + paper.y = 0 + root.renderScale *= ratio + tableView.forceLayout() + if (tableView.rotationNorm == 0) { + tableView.contentX = pageHolder.x + tableView.originX + centroidOnPage.x - centroidInFlickable.x + tableView.contentY = pageHolder.y + tableView.originY + centroidOnPage.y - centroidInFlickable.y + } else if (tableView.rotationNorm == 90) { + tableView.contentX = pageHolder.x + tableView.originX + image.height - centroidOnPage.y - centroidInFlickable.x + tableView.contentY = pageHolder.y + tableView.originY + centroidOnPage.x - centroidInFlickable.y + } else if (tableView.rotationNorm == 180) { + tableView.contentX = pageHolder.x + tableView.originX + image.width - centroidOnPage.x - centroidInFlickable.x + tableView.contentY = pageHolder.y + tableView.originY + image.height - centroidOnPage.y - centroidInFlickable.y + } else if (tableView.rotationNorm == 270) { + tableView.contentX = pageHolder.x + tableView.originX + centroidOnPage.y - centroidInFlickable.x + tableView.contentY = pageHolder.y + tableView.originY + image.width - centroidOnPage.x - centroidInFlickable.y + } + if (root.debug) + console.log("contentX/Y adjusted to", tableView.contentX.toFixed(2), tableView.contentY.toFixed(2), "y @top", pageHolder.y) + tableView.returnToBounds() + } + } + grabPermissions: PointerHandler.CanTakeOverFromAnything + } + DragHandler { + id: textSelectionDrag + acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus + target: null + } + TapHandler { + id: mouseClickHandler + acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus + } + TapHandler { + id: touchTapHandler + acceptedDevices: PointerDevice.TouchScreen + onTapped: { + selection.clear() + selection.forceActiveFocus() + } + } + Repeater { + model: PdfLinkModel { + id: linkModel + document: root.document + page: image.currentFrame + } + delegate: Shape { + x: rect.x * paper.pageScale + y: rect.y * paper.pageScale + width: rect.width * paper.pageScale + height: rect.height * paper.pageScale + visible: image.status === Image.Ready + ShapePath { + strokeWidth: style.linkUnderscoreStrokeWidth + strokeColor: style.linkUnderscoreColor + strokeStyle: style.linkUnderscoreStrokeStyle + dashPattern: style.linkUnderscoreDashPattern + startX: 0; startY: height + PathLine { x: width; y: height } + } + MouseArea { // TODO switch to TapHandler / HoverHandler in 5.15 + id: linkMA + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + hoverEnabled: true + onClicked: { + if (page >= 0) + root.goToLocation(page, location, zoom) + else + Qt.openUrlExternally(url) + } + } + ToolTip { + visible: linkMA.containsMouse + delay: 1000 + text: page >= 0 ? + ("page " + (page + 1) + + " location " + location.x.toFixed(1) + ", " + location.y.toFixed(1) + + " zoom " + zoom) : url + } + } + } + PdfSelection { + id: selection + anchors.fill: parent + document: root.document + page: image.currentFrame + renderScale: image.renderScale + fromPoint: textSelectionDrag.centroid.pressPosition + toPoint: textSelectionDrag.centroid.position + hold: !textSelectionDrag.active && !mouseClickHandler.pressed + onTextChanged: root.selectedText = text + focus: true + } + } + } + ScrollBar.vertical: ScrollBar { + id: vscroll + property bool moved: false + onPositionChanged: moved = true + onActiveChanged: { + var cell = tableHelper.cellAtPos(root.width / 2, root.height / 2) + var currentItem = tableHelper.itemAtCell(cell) + var currentLocation = Qt.point(0, 0) + if (currentItem) { // maybe the delegate wasn't loaded yet + currentLocation = Qt.point((tableView.contentX - currentItem.x + jumpLocationMargin.x) / root.renderScale, + (tableView.contentY - currentItem.y + jumpLocationMargin.y) / root.renderScale) + } + if (active) { + moved = false + // emitJumped false to avoid interrupting a pinch if TableView thinks it should scroll at the same time + navigationStack.push(cell.y, currentLocation, root.renderScale, false) + } else if (moved) { + navigationStack.update(cell.y, currentLocation, root.renderScale) + } + } + } + ScrollBar.horizontal: ScrollBar { } + } + onRenderScaleChanged: { + // if navigationStack.jumped changes the scale, don't turn around and update the stack again; + // and don't force layout either, because positionViewAtCell() will do that + if (navigationStack.jumping) + return + // make TableView rebuild from scratch, because otherwise it doesn't know the delegates are changing size + tableView.rebuild() + var cell = tableHelper.cellAtPos(root.width / 2, root.height / 2) + var currentItem = tableHelper.itemAtCell(cell) + if (currentItem) { + var currentLocation = Qt.point((tableView.contentX - currentItem.x + jumpLocationMargin.x) / root.renderScale, + (tableView.contentY - currentItem.y + jumpLocationMargin.y) / root.renderScale) + navigationStack.update(cell.y, currentLocation, renderScale) + } + } + PdfNavigationStack { + id: navigationStack + property bool jumping: false + property int previousPage: 0 + onJumped: { + jumping = true + root.renderScale = zoom + if (location.y < 0) { + // invalid to indicate that a specific location was not needed, + // so attempt to position the new page just as the current page is + var currentYOffset = 0 + var previousPageDelegate = tableHelper.itemAtCell(0, previousPage) + if (previousPageDelegate) + currentYOffset = tableView.contentY - previousPageDelegate.y + tableHelper.positionViewAtRow(page, Qt.AlignTop, currentYOffset) + if (root.debug) { + console.log("going from page", previousPage, "to", page, "offset", currentYOffset, + "ended up @", tableView.contentX.toFixed(1) + ", " + tableView.contentY.toFixed(1)) + } + } else { + // jump to a page and position the given location relative to the top-left corner of the viewport + var pageSize = root.document.pagePointSize(page) + pageSize.width *= root.renderScale + pageSize.height *= root.renderScale + var xOffsetLimit = Math.max(0, pageSize.width - root.width) / 2 + var offset = Qt.point(Math.max(-xOffsetLimit, Math.min(xOffsetLimit, + location.x * root.renderScale - jumpLocationMargin.x)), + Math.max(0, location.y * root.renderScale - jumpLocationMargin.y)) + tableHelper.positionViewAtCell(0, page, Qt.AlignLeft | Qt.AlignTop, offset) + if (root.debug) { + console.log("going to zoom", zoom, "loc", location, "on page", page, + "ended up @", tableView.contentX.toFixed(1) + ", " + tableView.contentY.toFixed(1)) + } + } + jumping = false + previousPage = page + } + onCurrentPageChanged: searchModel.currentPage = currentPage + } + PdfSearchModel { + id: searchModel + document: root.document === undefined ? null : root.document + // TODO maybe avoid jumping if the result is already fully visible in the viewport + onCurrentResultBoundingRectChanged: root.goToLocation(currentPage, + Qt.point(currentResultBoundingRect.x, currentResultBoundingRect.y), 0) + } +} diff --git a/src/pdfquick/qml/PdfPageView.qml b/src/pdfquick/qml/PdfPageView.qml new file mode 100644 index 000000000..b90ad2d7f --- /dev/null +++ b/src/pdfquick/qml/PdfPageView.qml @@ -0,0 +1,276 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Pdf 5.15 +import QtQuick.Shapes 1.14 +import Qt.labs.animation 1.0 + +Rectangle { + // public API + // TODO 5.15: required property + property var document: undefined + property alias status: image.status + + property alias selectedText: selection.text + function selectAll() { + selection.selectAll() + } + function copySelectionToClipboard() { + selection.copyToClipboard() + } + + // page navigation + property alias currentPage: navigationStack.currentPage + property alias backEnabled: navigationStack.backAvailable + property alias forwardEnabled: navigationStack.forwardAvailable + function back() { navigationStack.back() } + function forward() { navigationStack.forward() } + function goToPage(page) { goToLocation(page, Qt.point(0, 0), 0) } + function goToLocation(page, location, zoom) { + if (zoom > 0) + root.renderScale = zoom + navigationStack.push(page, location, zoom) + } + + // page scaling + property real renderScale: 1 + property alias sourceSize: image.sourceSize + function resetScale() { + image.sourceSize.width = 0 + image.sourceSize.height = 0 + root.x = 0 + root.y = 0 + root.scale = 1 + } + function scaleToWidth(width, height) { + var halfRotation = Math.abs(root.rotation % 180) + image.sourceSize = Qt.size((halfRotation > 45 && halfRotation < 135) ? height : width, 0) + root.x = 0 + root.y = 0 + image.centerInSize = Qt.size(width, height) + image.centerOnLoad = true + image.vCenterOnLoad = (halfRotation > 45 && halfRotation < 135) + root.scale = 1 + } + function scaleToPage(width, height) { + var windowAspect = width / height + var halfRotation = Math.abs(root.rotation % 180) + var pagePointSize = document.pagePointSize(navigationStack.currentPage) + if (halfRotation > 45 && halfRotation < 135) { + // rotated 90 or 270º + var pageAspect = pagePointSize.height / pagePointSize.width + if (windowAspect > pageAspect) { + image.sourceSize = Qt.size(height, 0) + } else { + image.sourceSize = Qt.size(0, width) + } + } else { + var pageAspect = pagePointSize.width / pagePointSize.height + if (windowAspect > pageAspect) { + image.sourceSize = Qt.size(0, height) + } else { + image.sourceSize = Qt.size(width, 0) + } + } + image.centerInSize = Qt.size(width, height) + image.centerOnLoad = true + image.vCenterOnLoad = true + root.scale = 1 + } + + // text search + property alias searchModel: searchModel + property alias searchString: searchModel.searchString + function searchBack() { --searchModel.currentResult } + function searchForward() { ++searchModel.currentResult } + + // implementation + id: root + width: image.width + height: image.height + + PdfSelection { + id: selection + document: root.document + page: navigationStack.currentPage + fromPoint: Qt.point(textSelectionDrag.centroid.pressPosition.x / image.pageScale, textSelectionDrag.centroid.pressPosition.y / image.pageScale) + toPoint: Qt.point(textSelectionDrag.centroid.position.x / image.pageScale, textSelectionDrag.centroid.position.y / image.pageScale) + hold: !textSelectionDrag.active && !tapHandler.pressed + } + + PdfSearchModel { + id: searchModel + document: root.document === undefined ? null : root.document + onCurrentPageChanged: root.goToPage(currentPage) + } + + PdfNavigationStack { + id: navigationStack + onCurrentPageChanged: searchModel.currentPage = currentPage + // TODO onCurrentLocationChanged: position currentLocation.x and .y in middle // currentPageChanged() MUST occur first! + onCurrentZoomChanged: root.renderScale = currentZoom + // TODO deal with horizontal location (need WheelHandler or Flickable probably) + } + + Image { + id: image + currentFrame: navigationStack.currentPage + source: document.status === PdfDocument.Ready ? document.source : "" + asynchronous: true + fillMode: Image.PreserveAspectFit + property bool centerOnLoad: false + property bool vCenterOnLoad: false + property size centerInSize + property real pageScale: image.paintedWidth / document.pagePointSize(navigationStack.currentPage).width + function reRenderIfNecessary() { + var newSourceWidth = image.sourceSize.width * root.scale + var ratio = newSourceWidth / image.sourceSize.width + if (ratio > 1.1 || ratio < 0.9) { + image.sourceSize.width = newSourceWidth + image.sourceSize.height = 0 + root.scale = 1 + } + } + onStatusChanged: + if (status == Image.Ready && centerOnLoad) { + root.x = (centerInSize.width - image.implicitWidth) / 2 + root.y = vCenterOnLoad ? (centerInSize.height - image.implicitHeight) / 2 : 0 + centerOnLoad = false + vCenterOnLoad = false + } + } + onRenderScaleChanged: { + image.sourceSize.width = document.pagePointSize(navigationStack.currentPage).width * renderScale + image.sourceSize.height = 0 + root.scale = 1 + } + + Shape { + anchors.fill: parent + opacity: 0.25 + visible: image.status === Image.Ready + ShapePath { + strokeWidth: 1 + strokeColor: "cyan" + fillColor: "steelblue" + scale: Qt.size(image.pageScale, image.pageScale) + PathMultiline { + paths: searchModel.currentPageBoundingPolygons + } + } + ShapePath { + strokeWidth: 1 + strokeColor: "orange" + fillColor: "cyan" + scale: Qt.size(image.pageScale, image.pageScale) + PathMultiline { + paths: searchModel.currentResultBoundingPolygons + } + } + ShapePath { + fillColor: "orange" + scale: Qt.size(image.pageScale, image.pageScale) + PathMultiline { + paths: selection.geometry + } + } + } + + Repeater { + model: PdfLinkModel { + id: linkModel + document: root.document + page: navigationStack.currentPage + } + delegate: Rectangle { + color: "transparent" + border.color: "lightgrey" + x: rect.x * image.pageScale + y: rect.y * image.pageScale + width: rect.width * image.pageScale + height: rect.height * image.pageScale + MouseArea { // TODO switch to TapHandler / HoverHandler in 5.15 + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + if (page >= 0) + navigationStack.push(page, Qt.point(0, 0), root.renderScale) + else + Qt.openUrlExternally(url) + } + } + } + } + + PinchHandler { + id: pinch + minimumScale: 0.1 + maximumScale: 10 + minimumRotation: 0 + maximumRotation: 0 + onActiveChanged: if (!active) image.reRenderIfNecessary() + grabPermissions: PinchHandler.TakeOverForbidden // don't allow takeover if pinch has started + } + DragHandler { + id: pageMovingTouchDrag + acceptedDevices: PointerDevice.TouchScreen + } + DragHandler { + id: pageMovingMiddleMouseDrag + acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus + acceptedButtons: Qt.MiddleButton + snapMode: DragHandler.NoSnap + } + DragHandler { + id: textSelectionDrag + acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus + target: null + } + TapHandler { + id: tapHandler + acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus + } + // prevent it from being scrolled out of view + BoundaryRule on x { + minimum: 100 - root.width + maximum: root.parent.width - 100 + } + BoundaryRule on y { + minimum: 100 - root.height + maximum: root.parent.height - 100 + } +} diff --git a/src/pdfquick/qml/PdfScrollablePageView.qml b/src/pdfquick/qml/PdfScrollablePageView.qml new file mode 100644 index 000000000..51d9e530d --- /dev/null +++ b/src/pdfquick/qml/PdfScrollablePageView.qml @@ -0,0 +1,307 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Pdf 5.15 +import QtQuick.Shapes 1.14 +import Qt.labs.animation 1.0 + +Flickable { + // public API + // TODO 5.15: required property + property var document: undefined + property bool debug: false + property alias status: image.status + + property alias selectedText: selection.text + function selectAll() { + selection.selectAll() + } + function copySelectionToClipboard() { + selection.copyToClipboard() + } + + // page navigation + property alias currentPage: navigationStack.currentPage + property alias backEnabled: navigationStack.backAvailable + property alias forwardEnabled: navigationStack.forwardAvailable + function back() { navigationStack.back() } + function forward() { navigationStack.forward() } + function goToPage(page) { + if (page === navigationStack.currentPage) + return + goToLocation(page, Qt.point(0, 0), 0) + } + function goToLocation(page, location, zoom) { + if (zoom > 0) + root.renderScale = zoom + navigationStack.push(page, location, zoom) + } + + // page scaling + property real renderScale: 1 + property real pageRotation: 0 + property alias sourceSize: image.sourceSize + function resetScale() { + paper.scale = 1 + root.renderScale = 1 + } + function scaleToWidth(width, height) { + var pagePointSize = document.pagePointSize(navigationStack.currentPage) + root.renderScale = root.width / (paper.rot90 ? pagePointSize.height : pagePointSize.width) + if (debug) + console.log("scaling", pagePointSize, "to fit", root.width, "rotated?", paper.rot90, "scale", root.renderScale) + root.contentX = 0 + root.contentY = 0 + } + function scaleToPage(width, height) { + var pagePointSize = document.pagePointSize(navigationStack.currentPage) + root.renderScale = Math.min( + root.width / (paper.rot90 ? pagePointSize.height : pagePointSize.width), + root.height / (paper.rot90 ? pagePointSize.width : pagePointSize.height) ) + root.contentX = 0 + root.contentY = 0 + } + + // text search + property alias searchModel: searchModel + property alias searchString: searchModel.searchString + function searchBack() { --searchModel.currentResult } + function searchForward() { ++searchModel.currentResult } + + // implementation + id: root + PdfStyle { id: style } + contentWidth: paper.width + contentHeight: paper.height + ScrollBar.vertical: ScrollBar { + onActiveChanged: + if (!active ) { + var currentLocation = Qt.point((root.contentX + root.width / 2) / root.renderScale, + (root.contentY + root.height / 2) / root.renderScale) + navigationStack.update(navigationStack.currentPage, currentLocation, root.renderScale) + } + } + ScrollBar.horizontal: ScrollBar { + onActiveChanged: + if (!active ) { + var currentLocation = Qt.point((root.contentX + root.width / 2) / root.renderScale, + (root.contentY + root.height / 2) / root.renderScale) + navigationStack.update(navigationStack.currentPage, currentLocation, root.renderScale) + } + } + + onRenderScaleChanged: { + image.sourceSize.width = document.pagePointSize(navigationStack.currentPage).width * renderScale + image.sourceSize.height = 0 + paper.scale = 1 + var currentLocation = Qt.point((root.contentX + root.width / 2) / root.renderScale, + (root.contentY + root.height / 2) / root.renderScale) + navigationStack.update(navigationStack.currentPage, currentLocation, root.renderScale) + } + + PdfSearchModel { + id: searchModel + document: root.document === undefined ? null : root.document + // TODO maybe avoid jumping if the result is already fully visible in the viewport + onCurrentResultBoundingRectChanged: root.goToLocation(currentPage, + Qt.point(currentResultBoundingRect.x, currentResultBoundingRect.y), 0) + } + + PdfNavigationStack { + id: navigationStack + onJumped: { + root.renderScale = zoom + var dx = Math.max(0, location.x * root.renderScale - root.width / 2) - root.contentX + var dy = Math.max(0, location.y * root.renderScale - root.height / 2) - root.contentY + // don't jump if location is in the viewport already, i.e. if the "error" between desired and actual contentX/Y is small + if (Math.abs(dx) > root.width / 3) + root.contentX += dx + if (Math.abs(dy) > root.height / 3) + root.contentY += dy + if (root.debug) { + console.log("going to zoom", zoom, "loc", location, + "on page", page, "ended up @", root.contentX + ", " + root.contentY) + } + } + onCurrentPageChanged: searchModel.currentPage = currentPage + } + + Rectangle { + id: paper + width: rot90 ? image.height : image.width + height: rot90 ? image.width : image.height + property real rotationModulus: Math.abs(root.pageRotation % 180) + property bool rot90: rotationModulus > 45 && rotationModulus < 135 + + Image { + id: image + currentFrame: navigationStack.currentPage + source: document.status === PdfDocument.Ready ? document.source : "" + asynchronous: true + fillMode: Image.PreserveAspectFit + rotation: root.pageRotation + anchors.centerIn: parent + property real pageScale: image.paintedWidth / document.pagePointSize(navigationStack.currentPage).width + + Shape { + anchors.fill: parent + visible: image.status === Image.Ready + ShapePath { + strokeWidth: -1 + fillColor: style.pageSearchResultsColor + scale: Qt.size(image.pageScale, image.pageScale) + PathMultiline { + paths: searchModel.currentPageBoundingPolygons + } + } + ShapePath { + strokeWidth: style.currentSearchResultStrokeWidth + strokeColor: style.currentSearchResultStrokeColor + fillColor: "transparent" + scale: Qt.size(image.pageScale, image.pageScale) + PathMultiline { + paths: searchModel.currentResultBoundingPolygons + } + } + ShapePath { + fillColor: style.selectionColor + scale: Qt.size(image.pageScale, image.pageScale) + PathMultiline { + paths: selection.geometry + } + } + } + + Repeater { + model: PdfLinkModel { + id: linkModel + document: root.document + page: navigationStack.currentPage + } + delegate: Shape { + x: rect.x * image.pageScale + y: rect.y * image.pageScale + width: rect.width * image.pageScale + height: rect.height * image.pageScale + ShapePath { + strokeWidth: style.linkUnderscoreStrokeWidth + strokeColor: style.linkUnderscoreColor + strokeStyle: style.linkUnderscoreStrokeStyle + dashPattern: style.linkUnderscoreDashPattern + startX: 0; startY: height + PathLine { x: width; y: height } + } + MouseArea { // TODO switch to TapHandler / HoverHandler in 5.15 + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + if (page >= 0) + navigationStack.push(page, Qt.point(0, 0), root.renderScale) + else + Qt.openUrlExternally(url) + } + } + } + } + DragHandler { + id: textSelectionDrag + acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus + target: null + } + TapHandler { + id: mouseClickHandler + acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus + } + TapHandler { + id: touchTapHandler + acceptedDevices: PointerDevice.TouchScreen + onTapped: { + selection.clear() + selection.focus = true + } + } + } + + PdfSelection { + id: selection + anchors.fill: parent + document: root.document + page: navigationStack.currentPage + renderScale: image.pageScale + fromPoint: textSelectionDrag.centroid.pressPosition + toPoint: textSelectionDrag.centroid.position + hold: !textSelectionDrag.active && !mouseClickHandler.pressed + focus: true + } + + PinchHandler { + id: pinch + minimumScale: 0.1 + maximumScale: root.renderScale < 4 ? 2 : 1 + minimumRotation: 0 + maximumRotation: 0 + enabled: image.sourceSize.width < 5000 + onActiveChanged: + if (!active) { + var centroidInPoints = Qt.point(pinch.centroid.position.x / root.renderScale, + pinch.centroid.position.y / root.renderScale) + var centroidInFlickable = root.mapFromItem(paper, pinch.centroid.position.x, pinch.centroid.position.y) + var newSourceWidth = image.sourceSize.width * paper.scale + var ratio = newSourceWidth / image.sourceSize.width + if (root.debug) + console.log("pinch ended with centroid", pinch.centroid.position, centroidInPoints, "wrt flickable", centroidInFlickable, + "page at", paper.x.toFixed(2), paper.y.toFixed(2), + "contentX/Y were", root.contentX.toFixed(2), root.contentY.toFixed(2)) + if (ratio > 1.1 || ratio < 0.9) { + var centroidOnPage = Qt.point(centroidInPoints.x * root.renderScale * ratio, centroidInPoints.y * root.renderScale * ratio) + paper.scale = 1 + paper.x = 0 + paper.y = 0 + root.contentX = centroidOnPage.x - centroidInFlickable.x + root.contentY = centroidOnPage.y - centroidInFlickable.y + root.renderScale *= ratio // onRenderScaleChanged calls navigationStack.update() so we don't need to here + if (root.debug) + console.log("contentX/Y adjusted to", root.contentX.toFixed(2), root.contentY.toFixed(2)) + } else { + paper.x = 0 + paper.y = 0 + } + } + grabPermissions: PointerHandler.CanTakeOverFromAnything + } + } +} diff --git a/src/pdfquick/qml/PdfStyle.qml b/src/pdfquick/qml/PdfStyle.qml new file mode 100644 index 000000000..090465ce6 --- /dev/null +++ b/src/pdfquick/qml/PdfStyle.qml @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +import QtQml 2.14 +import QtQuick 2.14 +import QtQuick.Controls 2.14 +import QtQuick.Shapes 1.14 + +QtObject { + property Control prototypeControl: Control { } + function withAlpha(color, alpha) { + return Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, alpha) + } + property color selectionColor: withAlpha(prototypeControl.palette.highlight, 0.5) + property color pageSearchResultsColor: "#80B0C4DE" + property color currentSearchResultStrokeColor: "cyan" + property real currentSearchResultStrokeWidth: 2 + property color linkUnderscoreColor: prototypeControl.palette.link + property real linkUnderscoreStrokeWidth: 1 + property var linkUnderscoreStrokeStyle: ShapePath.DashLine + property var linkUnderscoreDashPattern: [ 1, 4 ] +} diff --git a/src/pdfquick/qquickpdfdocument.cpp b/src/pdfquick/qquickpdfdocument.cpp new file mode 100644 index 000000000..79b23ca84 --- /dev/null +++ b/src/pdfquick/qquickpdfdocument.cpp @@ -0,0 +1,305 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickpdfdocument_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype PdfDocument + \instantiates QQuickPdfDocument + \inqmlmodule QtQuick.Pdf + \ingroup pdf + \brief A representation of a PDF document. + \since 5.15 + + PdfDocument provides access to PDF document meta-information. + It is not necessary for rendering, as it is enough to use an + \l Image with source set to the URL of the PDF. +*/ + +/*! + Constructs a PDF document. +*/ +QQuickPdfDocument::QQuickPdfDocument(QObject *parent) + : QObject(parent) +{ + connect(&m_doc, &QPdfDocument::passwordChanged, this, &QQuickPdfDocument::passwordChanged); + connect(&m_doc, &QPdfDocument::passwordRequired, this, &QQuickPdfDocument::passwordRequired); + connect(&m_doc, &QPdfDocument::statusChanged, [=] (QPdfDocument::Status status) { + emit statusChanged(); + if (status == QPdfDocument::Ready) + emit metaDataChanged(); + }); + connect(&m_doc, &QPdfDocument::pageCountChanged, this, &QQuickPdfDocument::pageCountChanged); +} + +void QQuickPdfDocument::componentComplete() +{ + if (m_doc.error() == QPdfDocument::IncorrectPasswordError) + emit passwordRequired(); +} + +/*! + \qmlproperty url PdfDocument::source + + This property holds a URL pointing to the PDF file to be loaded. + + \note At this time, only local filesystem URLs are supported. +*/ +void QQuickPdfDocument::setSource(QUrl source) +{ + if (m_source == source) + return; + + m_source = source; + m_maxPageWidthHeight = QSizeF(); + emit sourceChanged(); + if (source.scheme() == QLatin1String("qrc")) + m_doc.load(QLatin1Char(':') + source.path()); + else + m_doc.load(source.toLocalFile()); +} + +/*! + \qmlproperty string PdfDocument::error + + This property holds a translated string representation of the current + error, if any. + + \sa status +*/ +QString QQuickPdfDocument::error() const +{ + switch (m_doc.error()) { + case QPdfDocument::NoError: + return tr("no error"); + break; + case QPdfDocument::UnknownError: + break; + case QPdfDocument::DataNotYetAvailableError: + return tr("data not yet available"); + break; + case QPdfDocument::FileNotFoundError: + return tr("file not found"); + break; + case QPdfDocument::InvalidFileFormatError: + return tr("invalid file format"); + break; + case QPdfDocument::IncorrectPasswordError: + return tr("incorrect password"); + break; + case QPdfDocument::UnsupportedSecuritySchemeError: + return tr("unsupported security scheme"); + break; + } + return tr("unknown error"); +} + +/*! + \qmlproperty bool PdfDocument::password + + This property holds the document password. If the passwordRequired() + signal is emitted, the UI should prompt the user and then set this + property so that document opening can continue. +*/ +void QQuickPdfDocument::setPassword(const QString &password) +{ + if (m_doc.password() == password) + return; + m_doc.setPassword(password); + if (source().isValid() && source().isLocalFile()) + m_doc.load(source().path()); +} + +/*! + \qmlproperty int PdfDocument::pageCount + + This property holds the number of pages the PDF contains. +*/ + +/*! + \qmlsignal PdfDocument::passwordRequired() + + This signal is emitted when the PDF requires a password in order to open. + The UI in a typical PDF viewer should prompt the user for the password + and then set the password property when the user has provided it. +*/ + +/*! + \qmlmethod size PdfDocument::pagePointSize(int page) + + Returns the size of the given \a page in points. +*/ +QSizeF QQuickPdfDocument::pagePointSize(int page) const +{ + return m_doc.pageSize(page); +} + +qreal QQuickPdfDocument::maxPageWidth() const +{ + const_cast(this)->updateMaxPageSize(); + return m_maxPageWidthHeight.width(); +} + +qreal QQuickPdfDocument::maxPageHeight() const +{ + const_cast(this)->updateMaxPageSize(); + return m_maxPageWidthHeight.height(); +} + +/*! + \internal + \qmlmethod size PdfDocument::heightSumBeforePage(int page) + + Returns the sum of the heights, in points, of all sets of \a facingPages + pages from 0 to the given \a page, exclusive. + + That is, if the pages were laid out end-to-end in adjacent sets of + \a facingPages, what would be the distance in points from the top of the + first page to the top of the given page. +*/ +// Workaround for lack of something analogous to ListView.positionViewAtIndex() in TableView +qreal QQuickPdfDocument::heightSumBeforePage(int page, qreal spacing, int facingPages) const +{ + qreal ret = 0; + for (int i = 0; i < page; i+= facingPages) { + if (i + facingPages > page) + break; + qreal facingPagesHeight = 0; + for (int j = i; j < i + facingPages; ++j) + facingPagesHeight = qMax(facingPagesHeight, pagePointSize(j).height()); + ret += facingPagesHeight + spacing; + } + return ret; +} + +void QQuickPdfDocument::updateMaxPageSize() +{ + if (m_maxPageWidthHeight.isValid()) + return; + qreal w = 0; + qreal h = 0; + const int count = pageCount(); + for (int i = 0; i < count; ++i) { + auto size = pagePointSize(i); + w = qMax(w, size.width()); + h = qMax(w, size.height()); + } + m_maxPageWidthHeight = QSizeF(w, h); +} + +/*! + \qmlproperty real PdfDocument::maxPageWidth + + This property holds the width of the widest page in the document, in points. +*/ + +/*! + \qmlproperty real PdfDocument::maxPageHeight + + This property holds the height of the tallest page in the document, in points. +*/ + +/*! + \qmlproperty string PdfDocument::title + + This property holds the document's title. A typical viewer UI can bind this + to the \c Window.title property. +*/ + +/*! + \qmlproperty string PdfDocument::author + + This property holds the name of the person who created the document. +*/ + +/*! + \qmlproperty string PdfDocument::subject + + This property holds the subject of the document. +*/ + +/*! + \qmlproperty string PdfDocument::keywords + + This property holds the keywords associated with the document. +*/ + +/*! + \qmlproperty string PdfDocument::creator + + If the document was converted to PDF from another format, this property + holds the name of the software that created the original document. +*/ + +/*! + \qmlproperty string PdfDocument::producer + + If the document was converted to PDF from another format, this property + holds the name of the software that converted it to PDF. +*/ + +/*! + \qmlproperty string PdfDocument::creationDate + + This property holds the date and time the document was created. +*/ + +/*! + \qmlproperty string PdfDocument::modificationDate + + This property holds the date and time the document was most recently + modified. +*/ + +/*! + \qmlproperty enum PdfDocument::status + + This property tells the current status of the document. The possible values are: + + \value PdfDocument.Null The initial status after the document has been created or after it has been closed. + \value PdfDocument.Loading The status after load() has been called and before the document is fully loaded. + \value PdfDocument.Ready The status when the document is fully loaded and its data can be accessed. + \value PdfDocument.Unloading The status after close() has been called on an open document. + At this point the document is still valid and all its data can be accessed. + \value PdfDocument.Error The status after Loading, if loading has failed. +*/ + +QT_END_NAMESPACE diff --git a/src/pdfquick/qquickpdfdocument_p.h b/src/pdfquick/qquickpdfdocument_p.h new file mode 100644 index 000000000..cfeeb7b98 --- /dev/null +++ b/src/pdfquick/qquickpdfdocument_p.h @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKPDFDOCUMENT_P_H +#define QQUICKPDFDOCUMENT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_PDFQUICK_EXPORT QQuickPdfDocument : public QObject, public QQmlParserStatus +{ + Q_OBJECT + Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) + Q_PROPERTY(int pageCount READ pageCount NOTIFY pageCountChanged FINAL) + Q_PROPERTY(qreal maxPageWidth READ maxPageWidth NOTIFY metaDataChanged) + Q_PROPERTY(qreal maxPageHeight READ maxPageHeight NOTIFY metaDataChanged) + Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged FINAL) + Q_PROPERTY(QPdfDocument::Status status READ status NOTIFY statusChanged FINAL) + Q_PROPERTY(QString error READ error NOTIFY statusChanged FINAL) + + Q_PROPERTY(QString title READ title NOTIFY metaDataChanged) + Q_PROPERTY(QString subject READ subject NOTIFY metaDataChanged) + Q_PROPERTY(QString author READ author NOTIFY metaDataChanged) + Q_PROPERTY(QString keywords READ keywords NOTIFY metaDataChanged) + Q_PROPERTY(QString producer READ producer NOTIFY metaDataChanged) + Q_PROPERTY(QString creator READ creator NOTIFY metaDataChanged) + Q_PROPERTY(QDateTime creationDate READ creationDate NOTIFY metaDataChanged) + Q_PROPERTY(QDateTime modificationDate READ modificationDate NOTIFY metaDataChanged) + +public: + explicit QQuickPdfDocument(QObject *parent = nullptr); + + void classBegin() override {} + void componentComplete() override; + + QUrl source() const { return m_source; } + void setSource(QUrl source); + + int pageCount() const { return m_doc.pageCount(); } + QPdfDocument::Status status() const { return m_doc.status(); } + + QString error() const; + + QString password() const { return m_doc.password(); } + void setPassword(const QString &password); + + QString title() { return m_doc.metaData(QPdfDocument::Title).toString(); } + QString author() { return m_doc.metaData(QPdfDocument::Author).toString(); } + QString subject() { return m_doc.metaData(QPdfDocument::Subject).toString(); } + QString keywords() { return m_doc.metaData(QPdfDocument::Keywords).toString(); } + QString producer() { return m_doc.metaData(QPdfDocument::Producer).toString(); } + QString creator() { return m_doc.metaData(QPdfDocument::Creator).toString(); } + QDateTime creationDate() { return m_doc.metaData(QPdfDocument::CreationDate).toDateTime(); } + QDateTime modificationDate() { return m_doc.metaData(QPdfDocument::ModificationDate).toDateTime(); } + + Q_INVOKABLE QSizeF pagePointSize(int page) const; + qreal maxPageWidth() const; + qreal maxPageHeight() const; + Q_INVOKABLE qreal heightSumBeforePage(int page, qreal spacing = 0, int facingPages = 1) const; + +Q_SIGNALS: + void sourceChanged(); + void passwordChanged(); + void passwordRequired(); + void statusChanged(); + void pageCountChanged(); + void metaDataChanged(); + +private: + QPdfDocument &document() { return m_doc; } + void updateMaxPageSize(); + +private: + QUrl m_source; + QPdfDocument m_doc; + QSizeF m_maxPageWidthHeight; + + friend class QQuickPdfLinkModel; + friend class QQuickPdfSearchModel; + friend class QQuickPdfSelection; + + Q_DISABLE_COPY(QQuickPdfDocument) +}; + +QT_END_NAMESPACE + +#endif // QQUICKPDFDOCUMENT_P_H diff --git a/src/pdfquick/qquickpdflinkmodel.cpp b/src/pdfquick/qquickpdflinkmodel.cpp new file mode 100644 index 000000000..4f3958337 --- /dev/null +++ b/src/pdfquick/qquickpdflinkmodel.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickpdflinkmodel_p.h" +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \qmltype PdfLinkModel + \instantiates QQuickPdfLinkModel + \inqmlmodule QtQuick.Pdf + \ingroup pdf + \brief A representation of links within a PDF document. + \since 5.15 + + PdfLinkModel provides the geometry and the destination for each link + that the specified \l page contains. + + The available model roles are: + + \value rect + Bounding rectangle around the link. + \value url + If the link is a web link, the URL for that; otherwise an empty URL. + \value page + If the link is an internal link, the page number to which the link should jump; otherwise \c {-1}. + \value location + If the link is an internal link, the location on the page to which the link should jump. + \value zoom + If the link is an internal link, the intended zoom level on the destination page. + + Normally it will be used with \l {QtQuick::Repeater}{Repeater} to visualize + the links and provide the ability to click them: + + \qml + Repeater { + model: PdfLinkModel { + document: root.document + page: image.currentFrame + } + delegate: Rectangle { + color: "transparent" + border.color: "lightgrey" + x: rect.x + y: rect.y + width: rect.width + height: rect.height + HoverHandler { cursorShape: Qt.PointingHandCursor } + TapHandler { + onTapped: { + if (page >= 0) + image.currentFrame = page + else + Qt.openUrlExternally(url) + } + } + } + } + \endqml + + \note General-purpose PDF viewing capabilities are provided by + \l PdfScrollablePageView and \l PdfMultiPageView. PdfLinkModel is only needed + when building PDF view components from scratch. +*/ + +QQuickPdfLinkModel::QQuickPdfLinkModel(QObject *parent) + : QPdfLinkModel(parent) +{ +} + +/*! + \qmlproperty PdfDocument PdfLinkModel::document + + This property holds the PDF document in which links are to be found. +*/ +QQuickPdfDocument *QQuickPdfLinkModel::document() const +{ + return m_quickDocument; +} + +void QQuickPdfLinkModel::setDocument(QQuickPdfDocument *document) +{ + if (document == m_quickDocument) + return; + m_quickDocument = document; + QPdfLinkModel::setDocument(&document->m_doc); +} + +/*! + \qmlproperty int PdfLinkModel::page + + This property holds the page number on which links are to be found. +*/ + +QT_END_NAMESPACE diff --git a/src/pdfquick/qquickpdflinkmodel_p.h b/src/pdfquick/qquickpdflinkmodel_p.h new file mode 100644 index 000000000..d777643ef --- /dev/null +++ b/src/pdfquick/qquickpdflinkmodel_p.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKPDFLINKMODEL_P_H +#define QQUICKPDFLINKMODEL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_PDFQUICK_EXPORT QQuickPdfLinkModel : public QPdfLinkModel +{ + Q_OBJECT + Q_PROPERTY(QQuickPdfDocument *document READ document WRITE setDocument NOTIFY documentChanged) + +public: + explicit QQuickPdfLinkModel(QObject *parent = nullptr); + + QQuickPdfDocument *document() const; + void setDocument(QQuickPdfDocument *document); + +signals: + void documentChanged(); + +private: + void updateResults(); + +private: + QQuickPdfDocument *m_quickDocument; + QList m_linksGeometry; + + Q_DISABLE_COPY(QQuickPdfLinkModel) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickPdfLinkModel) + +#endif // QQUICKPDFLINKMODEL_P_H diff --git a/src/pdfquick/qquickpdfnavigationstack.cpp b/src/pdfquick/qquickpdfnavigationstack.cpp new file mode 100644 index 000000000..e41e43ed5 --- /dev/null +++ b/src/pdfquick/qquickpdfnavigationstack.cpp @@ -0,0 +1,272 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickpdfnavigationstack_p.h" +#include + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(qLcNav, "qt.pdf.navigationstack") + +/*! + \qmltype PdfNavigationStack + \instantiates QQuickPdfNavigationStack + \inqmlmodule QtQuick.Pdf + \ingroup pdf + \brief History of the destinations visited within a PDF Document. + \since 5.15 + + PdfNavigationStack remembers which destinations the user has visited in a PDF + document, and provides the ability to traverse backward and forward. +*/ + +QQuickPdfNavigationStack::QQuickPdfNavigationStack(QObject *parent) + : QObject(parent) +{ + push(0, QPointF(), 1); +} + +/*! + \qmlmethod void PdfNavigationStack::forward() + + Goes back to the page, location and zoom level that was being viewed before + back() was called, and then emits the \l jumped() signal. + + If a new destination was pushed since the last time \l back() was called, + the forward() function does nothing, because there is a branch in the + timeline which causes the "future" to be lost. +*/ +void QQuickPdfNavigationStack::forward() +{ + if (m_currentHistoryIndex >= m_pageHistory.count() - 1) + return; + bool backAvailableWas = backAvailable(); + bool forwardAvailableWas = forwardAvailable(); + QPointF currentLocationWas = currentLocation(); + qreal currentZoomWas = currentZoom(); + ++m_currentHistoryIndex; + m_changing = true; + emit jumped(currentPage(), currentLocation(), currentZoom()); + if (currentZoomWas != currentZoom()) + emit currentZoomChanged(); + emit currentPageChanged(); + if (currentLocationWas != currentLocation()) + emit currentLocationChanged(); + if (!backAvailableWas) + emit backAvailableChanged(); + if (forwardAvailableWas != forwardAvailable()) + emit forwardAvailableChanged(); + m_changing = false; + qCDebug(qLcNav) << "forward: index" << m_currentHistoryIndex << "page" << currentPage() + << "@" << currentLocation() << "zoom" << currentZoom(); +} + +/*! + \qmlmethod void PdfNavigationStack::back() + + Pops the stack, updates the \l currentPage, \l currentLocation and + \l currentZoom properties to the most-recently-viewed destination, and then + emits the \l jumped() signal. +*/ +void QQuickPdfNavigationStack::back() +{ + if (m_currentHistoryIndex <= 0) + return; + bool backAvailableWas = backAvailable(); + bool forwardAvailableWas = forwardAvailable(); + QPointF currentLocationWas = currentLocation(); + qreal currentZoomWas = currentZoom(); + --m_currentHistoryIndex; + m_changing = true; + emit jumped(currentPage(), currentLocation(), currentZoom()); + if (currentZoomWas != currentZoom()) + emit currentZoomChanged(); + emit currentPageChanged(); + if (currentLocationWas != currentLocation()) + emit currentLocationChanged(); + if (backAvailableWas != backAvailable()) + emit backAvailableChanged(); + if (!forwardAvailableWas) + emit forwardAvailableChanged(); + m_changing = false; + qCDebug(qLcNav) << "back: index" << m_currentHistoryIndex << "page" << currentPage() + << "@" << currentLocation() << "zoom" << currentZoom(); +} + +/*! + \qmlproperty int PdfNavigationStack::currentPage + + This property holds the current page that is being viewed. + If there is no current page, it holds \c -1. +*/ +int QQuickPdfNavigationStack::currentPage() const +{ + if (m_currentHistoryIndex < 0 || m_currentHistoryIndex >= m_pageHistory.count()) + return -1; + return m_pageHistory.at(m_currentHistoryIndex)->page; +} + +/*! + \qmlproperty point PdfNavigationStack::currentLocation + + This property holds the current location on the page that is being viewed. +*/ +QPointF QQuickPdfNavigationStack::currentLocation() const +{ + if (m_currentHistoryIndex < 0 || m_currentHistoryIndex >= m_pageHistory.count()) + return QPointF(); + return m_pageHistory.at(m_currentHistoryIndex)->location; +} + +/*! + \qmlproperty real PdfNavigationStack::currentZoom + + This property holds the magnification scale on the page that is being viewed. +*/ +qreal QQuickPdfNavigationStack::currentZoom() const +{ + if (m_currentHistoryIndex < 0 || m_currentHistoryIndex >= m_pageHistory.count()) + return 1; + return m_pageHistory.at(m_currentHistoryIndex)->zoom; +} + +/*! + \qmlmethod void PdfNavigationStack::push(int page, point location, qreal zoom) + + Adds the given destination, consisting of \a page, \a location and \a zoom, + to the history of visited locations. If \a emitJumped is \c false, the + \l jumped() signal will not be emitted. + + If forwardAvailable is \c true, calling this function represents a branch + in the timeline which causes the "future" to be lost, and therefore + forwardAvailable will change to \c false. +*/ +void QQuickPdfNavigationStack::push(int page, QPointF location, qreal zoom, bool emitJumped) +{ + if (page == currentPage() && location == currentLocation() && zoom == currentZoom()) + return; + if (qFuzzyIsNull(zoom)) + zoom = currentZoom(); + bool backAvailableWas = backAvailable(); + bool forwardAvailableWas = forwardAvailable(); + if (!m_changing) { + if (m_currentHistoryIndex >= 0 && forwardAvailableWas) + m_pageHistory.remove(m_currentHistoryIndex + 1, m_pageHistory.count() - m_currentHistoryIndex - 1); + m_pageHistory.append(QExplicitlySharedDataPointer(new QPdfDestinationPrivate(page, location, zoom))); + m_currentHistoryIndex = m_pageHistory.count() - 1; + } + emit currentZoomChanged(); + emit currentPageChanged(); + emit currentLocationChanged(); + if (m_changing) + return; + if (!backAvailableWas) + emit backAvailableChanged(); + if (forwardAvailableWas) + emit forwardAvailableChanged(); + if (emitJumped) + emit jumped(page, location, zoom); + qCDebug(qLcNav) << "push: index" << m_currentHistoryIndex << "page" << page + << "@" << location << "zoom" << zoom << "-> history" << + [this]() { + QStringList ret; + for (auto d : m_pageHistory) + ret << QString::number(d->page); + return ret.join(QLatin1Char(',')); + }(); +} + +/*! + \qmlmethod void PdfNavigationStack::update(int page, point location, qreal zoom) + + Modifies the current destination, consisting of \a page, \a location and \a zoom. + + This can be called periodically while the user is manually moving around + the document, so that after back() is called, forward() will jump back to + the most-recently-viewed destination rather than the destination that was + last specified by push(). + + The \c currentZoomChanged, \c currentPageChanged and \c currentLocationChanged + signals will be emitted if the respective properties are actually changed. + The \l jumped signal is not emitted, because this operation + represents smooth movement rather than a navigational jump. +*/ +void QQuickPdfNavigationStack::update(int page, QPointF location, qreal zoom) +{ + if (m_currentHistoryIndex < 0 || m_currentHistoryIndex >= m_pageHistory.count()) + return; + int currentPageWas = currentPage(); + QPointF currentLocationWas = currentLocation(); + qreal currentZoomWas = currentZoom(); + if (page == currentPageWas && location == currentLocationWas && zoom == currentZoomWas) + return; + m_pageHistory[m_currentHistoryIndex]->page = page; + m_pageHistory[m_currentHistoryIndex]->location = location; + m_pageHistory[m_currentHistoryIndex]->zoom = zoom; + if (currentZoomWas != zoom) + emit currentZoomChanged(); + if (currentPageWas != page) + emit currentPageChanged(); + if (currentLocationWas != location) + emit currentLocationChanged(); + qCDebug(qLcNav) << "update: index" << m_currentHistoryIndex << "page" << page + << "@" << location << "zoom" << zoom << "-> history" << + [this]() { + QStringList ret; + for (auto d : m_pageHistory) + ret << QString::number(d->page); + return ret.join(QLatin1Char(',')); + }(); +} + +bool QQuickPdfNavigationStack::backAvailable() const +{ + return m_currentHistoryIndex > 0; +} + +bool QQuickPdfNavigationStack::forwardAvailable() const +{ + return m_currentHistoryIndex < m_pageHistory.count() - 1; +} + +/*! + \qmlsignal PdfNavigationStack::jumped(int page, point location, qreal zoom) + + This signal is emitted when forward(), back() or push() is called, but not + when update() is called. +*/ + +QT_END_NAMESPACE diff --git a/src/pdfquick/qquickpdfnavigationstack_p.h b/src/pdfquick/qquickpdfnavigationstack_p.h new file mode 100644 index 000000000..1d37a4a85 --- /dev/null +++ b/src/pdfquick/qquickpdfnavigationstack_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKPDFNAVIGATIONSTACK_P_H +#define QQUICKPDFNAVIGATIONSTACK_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class Q_PDFQUICK_EXPORT QQuickPdfNavigationStack : public QObject +{ + Q_OBJECT + Q_PROPERTY(int currentPage READ currentPage NOTIFY currentPageChanged) + Q_PROPERTY(QPointF currentLocation READ currentLocation NOTIFY currentLocationChanged) + Q_PROPERTY(qreal currentZoom READ currentZoom NOTIFY currentZoomChanged) + Q_PROPERTY(bool backAvailable READ backAvailable NOTIFY backAvailableChanged) + Q_PROPERTY(bool forwardAvailable READ forwardAvailable NOTIFY forwardAvailableChanged) + +public: + explicit QQuickPdfNavigationStack(QObject *parent = nullptr); + + Q_INVOKABLE void push(int page, QPointF location, qreal zoom, bool emitJumped = true); + Q_INVOKABLE void update(int page, QPointF location, qreal zoom); + Q_INVOKABLE void forward(); + Q_INVOKABLE void back(); + + int currentPage() const; + QPointF currentLocation() const; + qreal currentZoom() const; + + bool backAvailable() const; + bool forwardAvailable() const; + +Q_SIGNALS: + void currentPageChanged(); + void currentLocationChanged(); + void currentZoomChanged(); + void backAvailableChanged(); + void forwardAvailableChanged(); + void jumped(int page, QPointF location, qreal zoom); + +private: + QList> m_pageHistory; + int m_currentHistoryIndex = 0; + bool m_changing = false; + + Q_DISABLE_COPY(QQuickPdfNavigationStack) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickPdfNavigationStack) + +#endif // QQUICKPDFNAVIGATIONSTACK_P_H diff --git a/src/pdfquick/qquickpdfsearchmodel.cpp b/src/pdfquick/qquickpdfsearchmodel.cpp new file mode 100644 index 000000000..d91ca69f8 --- /dev/null +++ b/src/pdfquick/qquickpdfsearchmodel.cpp @@ -0,0 +1,301 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickpdfsearchmodel_p.h" +#include + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(qLcSearch, "qt.pdf.search") + +/*! + \qmltype PdfSearchModel + \instantiates QQuickPdfSearchModel + \inqmlmodule QtQuick.Pdf + \ingroup pdf + \brief A representation of text search results within a PDF Document. + \since 5.15 + + PdfSearchModel provides the ability to search for text strings within a + document and get the geometric locations of matches on each page. +*/ + +QQuickPdfSearchModel::QQuickPdfSearchModel(QObject *parent) + : QPdfSearchModel(parent) +{ + connect(this, &QPdfSearchModel::searchStringChanged, + this, &QQuickPdfSearchModel::onResultsChanged); +} + +QQuickPdfDocument *QQuickPdfSearchModel::document() const +{ + return m_quickDocument; +} + +void QQuickPdfSearchModel::setDocument(QQuickPdfDocument *document) +{ + if (document == m_quickDocument || !document) + return; + + m_quickDocument = document; + QPdfSearchModel::setDocument(&document->m_doc); +} + +/*! + \qmlproperty list> PdfSearchModel::currentResultBoundingPolygons + + A set of paths in a form that can be bound to the \c paths property of a + \l {QtQuick::PathMultiline}{PathMultiline} instance to render a batch of + rectangles around the regions comprising the search result \l currentResult + on \l currentPage. This is normally used to highlight one search result + at a time, in a UI that allows stepping through the results: + + \qml + PdfDocument { + id: doc + } + PdfSearchModel { + id: searchModel + document: doc + currentPage: view.currentPage + currentResult: ... + } + Shape { + ShapePath { + PathMultiline { + paths: searchModel.currentResultBoundingPolygons + } + } + } + \endqml + + \sa PathMultiline +*/ +QList QQuickPdfSearchModel::currentResultBoundingPolygons() const +{ + QList ret; + const auto &results = const_cast(this)->resultsOnPage(m_currentPage); + if (m_currentResult < 0 || m_currentResult >= results.count()) + return ret; + const auto result = results[m_currentResult]; + for (auto rect : result.rectangles()) + ret << QPolygonF(rect); + return ret; +} + +/*! + \qmlproperty point PdfSearchModel::currentResultBoundingRect + + The bounding box containing all \l currentResultBoundingPolygons. + + When this property changes, a scrollable view should automatically scroll + itself in such a way as to ensure that this region is visible; for example, + it could try to position the upper-left corner near the upper-left of its + own viewport, subject to the constraints of the scrollable area. +*/ +QRectF QQuickPdfSearchModel::currentResultBoundingRect() const +{ + QRectF ret; + const auto &results = const_cast(this)->resultsOnPage(m_currentPage); + if (m_currentResult < 0 || m_currentResult >= results.count()) + return ret; + auto rects = results[m_currentResult].rectangles(); + ret = rects.takeFirst(); + for (auto rect : rects) + ret = ret.united(rect); + return ret; +} + +void QQuickPdfSearchModel::onResultsChanged() +{ + emit currentPageBoundingPolygonsChanged(); + emit currentResultBoundingPolygonsChanged(); +} + +/*! + \qmlproperty list> PdfSearchModel::currentPageBoundingPolygons + + A set of paths in a form that can be bound to the \c paths property of a + \l {QtQuick::PathMultiline}{PathMultiline} instance to render a batch of + rectangles around all the regions where search results are found on + \l currentPage: + + \qml + PdfDocument { + id: doc + } + PdfSearchModel { + id: searchModel + document: doc + } + Shape { + ShapePath { + PathMultiline { + paths: searchModel.matchGeometry(view.currentPage) + } + } + } + \endqml + + \sa PathMultiline +*/ +QList QQuickPdfSearchModel::currentPageBoundingPolygons() const +{ + return const_cast(this)->boundingPolygonsOnPage(m_currentPage); +} + +/*! + \qmlfunction list> PdfSearchModel::boundingPolygonsOnPage(int page) + + Returns a set of paths in a form that can be bound to the \c paths property of a + \l {QtQuick::PathMultiline}{PathMultiline} instance to render a batch of + rectangles around all the locations where search results are found: + + \qml + PdfDocument { + id: doc + } + PdfSearchModel { + id: searchModel + document: doc + } + Shape { + ShapePath { + PathMultiline { + paths: searchModel.matchGeometry(view.currentPage) + } + } + } + \endqml + + \sa PathMultiline +*/ +QList QQuickPdfSearchModel::boundingPolygonsOnPage(int page) +{ + if (!document() || searchString().isEmpty() || page < 0 || page > document()->pageCount()) + return {}; + + updatePage(page); + + QList ret; + auto m = QPdfSearchModel::resultsOnPage(page); + for (auto result : m) { + for (auto rect : result.rectangles()) + ret << QPolygonF(rect); + } + + return ret; +} + +/*! + \qmlproperty int PdfSearchModel::currentPage + + The page on which \l currentMatchGeometry should provide filtered search results. +*/ +void QQuickPdfSearchModel::setCurrentPage(int currentPage) +{ + if (m_currentPage == currentPage) + return; + + if (currentPage < 0) + currentPage = document()->pageCount() - 1; + else if (currentPage >= document()->pageCount()) + currentPage = 0; + + m_currentPage = currentPage; + if (!m_suspendSignals) { + emit currentPageChanged(); + onResultsChanged(); + } +} + +/*! + \qmlproperty int PdfSearchModel::currentResult + + The result index on \l currentPage for which \l currentResultBoundingPolygons + should provide the regions to highlight. +*/ +void QQuickPdfSearchModel::setCurrentResult(int currentResult) +{ + if (m_currentResult == currentResult) + return; + + int currentResultWas = currentResult; + int currentPageWas = m_currentPage; + if (currentResult < 0) { + setCurrentPage(m_currentPage - 1); + while (resultsOnPage(m_currentPage).count() == 0 && m_currentPage != currentPageWas) { + m_suspendSignals = true; + setCurrentPage(m_currentPage - 1); + } + if (m_suspendSignals) { + emit currentPageChanged(); + m_suspendSignals = false; + } + const auto results = resultsOnPage(m_currentPage); + currentResult = results.count() - 1; + } else { + const auto results = resultsOnPage(m_currentPage); + if (currentResult >= results.count()) { + setCurrentPage(m_currentPage + 1); + while (resultsOnPage(m_currentPage).count() == 0 && m_currentPage != currentPageWas) { + m_suspendSignals = true; + setCurrentPage(m_currentPage + 1); + } + if (m_suspendSignals) { + emit currentPageChanged(); + m_suspendSignals = false; + } + currentResult = 0; + } + } + qCDebug(qLcSearch) << "currentResult was" << m_currentResult + << "requested" << currentResultWas << "on page" << currentPageWas + << "->" << currentResult << "on page" << m_currentPage; + + m_currentResult = currentResult; + emit currentResultChanged(); + emit currentResultBoundingPolygonsChanged(); + emit currentResultBoundingRectChanged(); +} + +/*! + \qmlproperty string PdfSearchModel::searchString + + The string to search for. +*/ + +QT_END_NAMESPACE diff --git a/src/pdfquick/qquickpdfsearchmodel_p.h b/src/pdfquick/qquickpdfsearchmodel_p.h new file mode 100644 index 000000000..ad92d4222 --- /dev/null +++ b/src/pdfquick/qquickpdfsearchmodel_p.h @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKPDFSEARCHMODEL_P_H +#define QQUICKPDFSEARCHMODEL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_PDFQUICK_EXPORT QQuickPdfSearchModel : public QPdfSearchModel +{ + Q_OBJECT + Q_PROPERTY(QQuickPdfDocument *document READ document WRITE setDocument NOTIFY documentChanged) + Q_PROPERTY(int currentPage READ currentPage WRITE setCurrentPage NOTIFY currentPageChanged) + Q_PROPERTY(int currentResult READ currentResult WRITE setCurrentResult NOTIFY currentResultChanged) + Q_PROPERTY(QList currentPageBoundingPolygons READ currentPageBoundingPolygons NOTIFY currentPageBoundingPolygonsChanged) + Q_PROPERTY(QList currentResultBoundingPolygons READ currentResultBoundingPolygons NOTIFY currentResultBoundingPolygonsChanged) + Q_PROPERTY(QRectF currentResultBoundingRect READ currentResultBoundingRect NOTIFY currentResultBoundingRectChanged) + +public: + explicit QQuickPdfSearchModel(QObject *parent = nullptr); + + QQuickPdfDocument *document() const; + void setDocument(QQuickPdfDocument * document); + + Q_INVOKABLE QList boundingPolygonsOnPage(int page); + + int currentPage() const { return m_currentPage; } + void setCurrentPage(int currentPage); + + int currentResult() const { return m_currentResult; } + void setCurrentResult(int currentResult); + + QList currentPageBoundingPolygons() const; + QList currentResultBoundingPolygons() const; + QRectF currentResultBoundingRect() const; + +signals: + void documentChanged(); + void currentPageChanged(); + void currentResultChanged(); + void currentPageBoundingPolygonsChanged(); + void currentResultBoundingPolygonsChanged(); + void currentResultBoundingRectChanged(); + +private: + void updateResults(); + void onResultsChanged(); + +private: + QQuickPdfDocument *m_quickDocument = nullptr; + int m_currentPage = 0; + int m_currentResult = 0; + bool m_suspendSignals = false; + + Q_DISABLE_COPY(QQuickPdfSearchModel) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickPdfSearchModel) +QML_DECLARE_TYPE(QPdfSelection) + +#endif // QQUICKPDFSEARCHMODEL_P_H diff --git a/src/pdfquick/qquickpdfselection.cpp b/src/pdfquick/qquickpdfselection.cpp new file mode 100644 index 000000000..54a13828a --- /dev/null +++ b/src/pdfquick/qquickpdfselection.cpp @@ -0,0 +1,543 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickpdfselection_p.h" +#include "qquickpdfdocument_p.h" +#include +#include +#include +#include +#include +#include +#include +#include + +Q_LOGGING_CATEGORY(qLcIm, "qt.pdf.im") + +QT_BEGIN_NAMESPACE + +static const QRegularExpression WordDelimiter(QStringLiteral("\\s")); + +/*! + \qmltype PdfSelection + \instantiates QQuickPdfSelection + \inqmlmodule QtQuick.Pdf + \ingroup pdf + \brief A representation of a text selection within a PDF Document. + \since 5.15 + + PdfSelection provides the text string and its geometry within a bounding box + from one point to another. + + To modify the selection using the mouse, bind \l fromPoint and \l toPoint + to the suitable properties of an input handler so that they will be set to + the positions where the drag gesture begins and ends, respectively; and + bind the \l hold property so that it will be set to \c true during the drag + gesture and \c false when the gesture ends. + + PdfSelection also directly handles Input Method queries so that text + selection handles can be used on platforms such as iOS. For this purpose, + it must have keyboard focus. +*/ + +/*! + Constructs a SearchModel. +*/ +QQuickPdfSelection::QQuickPdfSelection(QQuickItem *parent) + : QQuickItem(parent) +{ +#if QT_CONFIG(im) + setFlags(ItemIsFocusScope | ItemAcceptsInputMethod); + // workaround to get Copy instead of Paste on the popover menu (QTBUG-83811) + setProperty("qt_im_readonly", QVariant(true)); +#endif +} + +QQuickPdfDocument *QQuickPdfSelection::document() const +{ + return m_document; +} + +void QQuickPdfSelection::setDocument(QQuickPdfDocument *document) +{ + if (m_document == document) + return; + + if (m_document) { + disconnect(m_document, &QQuickPdfDocument::sourceChanged, + this, &QQuickPdfSelection::resetPoints); + } + m_document = document; + emit documentChanged(); + resetPoints(); + connect(m_document, &QQuickPdfDocument::sourceChanged, + this, &QQuickPdfSelection::resetPoints); +} + +/*! + \qmlproperty list> PdfSelection::geometry + + A set of paths in a form that can be bound to the \c paths property of a + \l {QtQuick::PathMultiline}{PathMultiline} instance to render a batch of + rectangles around the text regions that are included in the selection: + + \qml + PdfDocument { + id: doc + } + PdfSelection { + id: selection + document: doc + fromPoint: textSelectionDrag.centroid.pressPosition + toPoint: textSelectionDrag.centroid.position + hold: !textSelectionDrag.active + } + Shape { + ShapePath { + PathMultiline { + paths: selection.geometry + } + } + } + DragHandler { + id: textSelectionDrag + acceptedDevices: PointerDevice.Mouse | PointerDevice.Stylus + target: null + } + \endqml + + \sa PathMultiline +*/ +QList QQuickPdfSelection::geometry() const +{ + return m_geometry; +} + +void QQuickPdfSelection::clear() +{ + m_hitPoint = QPointF(); + m_fromPoint = QPointF(); + m_toPoint = QPointF(); + m_heightAtAnchor = 0; + m_heightAtCursor = 0; + m_fromCharIndex = -1; + m_toCharIndex = -1; + m_text.clear(); + m_geometry.clear(); + emit fromPointChanged(); + emit toPointChanged(); + emit textChanged(); + emit selectedAreaChanged(); + QGuiApplication::inputMethod()->update(Qt::ImQueryInput); +} + +void QQuickPdfSelection::selectAll() +{ + QPdfSelection sel = m_document->m_doc.getAllText(m_page); + if (sel.text() != m_text) { + m_text = sel.text(); + if (QGuiApplication::clipboard()->supportsSelection()) + sel.copyToClipboard(QClipboard::Selection); + emit textChanged(); + } + + if (sel.bounds() != m_geometry) { + m_geometry = sel.bounds(); + emit selectedAreaChanged(); + } +#if QT_CONFIG(im) + m_fromCharIndex = sel.startIndex(); + m_toCharIndex = sel.endIndex(); + if (sel.bounds().isEmpty()) { + m_fromPoint = QPointF(); + m_toPoint = QPointF(); + } else { + m_fromPoint = sel.bounds().first().boundingRect().topLeft() * m_renderScale; + m_toPoint = sel.bounds().last().boundingRect().bottomRight() * m_renderScale - QPointF(0, m_heightAtCursor); + } + + QGuiApplication::inputMethod()->update(Qt::ImCursorRectangle | Qt::ImAnchorRectangle); +#endif +} + +#if QT_CONFIG(im) +void QQuickPdfSelection::keyReleaseEvent(QKeyEvent *ev) +{ + qCDebug(qLcIm) << "release" << ev; + const auto &allText = pageText(); + if (ev == QKeySequence::MoveToPreviousWord) { + // iOS sends MoveToPreviousWord first to get to the beginning of the word, + // and then SelectNextWord to select the whole word. + int i = allText.lastIndexOf(WordDelimiter, m_fromCharIndex - allText.length()); + if (i < 0) + i = 0; + else + i += 1; // don't select the space before the word + auto sel = m_document->m_doc.getSelectionAtIndex(m_page, i, m_text.length() + m_fromCharIndex - i); + update(sel); + QGuiApplication::inputMethod()->update(Qt::ImAnchorRectangle); + } else if (ev == QKeySequence::SelectNextWord) { + int i = allText.indexOf(WordDelimiter, m_toCharIndex); + if (i < 0) + i = allText.length(); // go to the end of m_textAfter + auto sel = m_document->m_doc.getSelectionAtIndex(m_page, m_fromCharIndex, m_text.length() + i - m_toCharIndex); + update(sel); + QGuiApplication::inputMethod()->update(Qt::ImCursorRectangle); + } else if (ev == QKeySequence::Copy) { + copyToClipboard(); + } +} + +void QQuickPdfSelection::inputMethodEvent(QInputMethodEvent *event) +{ + for (auto attr : event->attributes()) { + switch (attr.type) { + case QInputMethodEvent::Cursor: + qCDebug(qLcIm) << "QInputMethodEvent::Cursor: moved to" << attr.start << "len" << attr.length; + break; + case QInputMethodEvent::Selection: { + auto sel = m_document->m_doc.getSelectionAtIndex(m_page, attr.start, attr.length); + update(sel); + qCDebug(qLcIm) << "QInputMethodEvent::Selection: from" << attr.start << "len" << attr.length + << "result:" << m_fromCharIndex << "->" << m_toCharIndex << sel.boundingRectangle(); + // the iOS plugin decided that it wanted to change the selection, but still has to be told to move the handles (!?) + QGuiApplication::inputMethod()->update(Qt::ImCursorRectangle | Qt::ImAnchorRectangle); + break; + } + case QInputMethodEvent::Language: + case QInputMethodEvent::Ruby: + case QInputMethodEvent::TextFormat: + break; + } + } +} + +QVariant QQuickPdfSelection::inputMethodQuery(Qt::InputMethodQuery query, const QVariant &argument) const +{ + if (!argument.isNull()) { + qCDebug(qLcIm) << "IM query" << query << "with arg" << argument; + if (query == Qt::ImCursorPosition) { + // If it didn't move since last time, return the same result. + if (m_hitPoint == argument.toPointF()) + return inputMethodQuery(query); + m_hitPoint = argument.toPointF(); + auto tp = m_document->m_doc.d->hitTest(m_page, m_hitPoint / m_renderScale); + qCDebug(qLcIm) << "ImCursorPosition hit testing in px" << m_hitPoint << "pt" << (m_hitPoint / m_renderScale) + << "got char index" << tp.charIndex << "@" << tp.position << "pt," << tp.position * m_renderScale << "px"; + if (tp.charIndex >= 0) { + m_toCharIndex = tp.charIndex; + m_toPoint = tp.position * m_renderScale - QPointF(0, m_heightAtCursor); + m_heightAtCursor = tp.height * m_renderScale; + if (qFuzzyIsNull(m_heightAtAnchor)) + m_heightAtAnchor = m_heightAtCursor; + } + } + } + return inputMethodQuery(query); +} + +QVariant QQuickPdfSelection::inputMethodQuery(Qt::InputMethodQuery query) const +{ + QVariant ret; + switch (query) { + case Qt::ImEnabled: + ret = true; + break; + case Qt::ImHints: + ret = QVariant(Qt::ImhMultiLine | Qt::ImhNoPredictiveText); + break; + case Qt::ImInputItemClipRectangle: + ret = boundingRect(); + break; + case Qt::ImAnchorPosition: + ret = m_fromCharIndex; + break; + case Qt::ImAbsolutePosition: + ret = m_toCharIndex; + break; + case Qt::ImCursorPosition: + ret = m_toCharIndex; + break; + case Qt::ImAnchorRectangle: + ret = QRectF(m_fromPoint, QSizeF(1, m_heightAtAnchor)); + break; + case Qt::ImCursorRectangle: + ret = QRectF(m_toPoint, QSizeF(1, m_heightAtCursor)); + break; + case Qt::ImSurroundingText: + ret = QVariant(pageText()); + break; + case Qt::ImTextBeforeCursor: + ret = QVariant(pageText().mid(0, m_toCharIndex)); + break; + case Qt::ImTextAfterCursor: + ret = QVariant(pageText().mid(m_toCharIndex)); + break; + case Qt::ImCurrentSelection: + ret = QVariant(m_text); + break; + case Qt::ImEnterKeyType: + break; + case Qt::ImFont: { + QFont font = QGuiApplication::font(); + font.setPointSizeF(m_heightAtCursor); + ret = font; + break; + } + case Qt::ImMaximumTextLength: + break; + case Qt::ImPreferredLanguage: + break; + case Qt::ImPlatformData: + break; + case Qt::ImReadOnly: + break; + case Qt::ImQueryInput: + case Qt::ImQueryAll: + qWarning() << "unexpected composite query"; + break; + } + qCDebug(qLcIm) << "IM query" << query << "returns" << ret; + return ret; +} +#endif // QT_CONFIG(im) + +const QString &QQuickPdfSelection::pageText() const +{ + if (m_pageTextDirty) { + m_pageText = m_document->m_doc.getAllText(m_page).text(); + m_pageTextDirty = false; + } + return m_pageText; +} + +void QQuickPdfSelection::resetPoints() +{ + bool wasHolding = m_hold; + m_hold = false; + setFromPoint(QPointF()); + setToPoint(QPointF()); + m_hold = wasHolding; +} + +/*! + \qmlproperty int PdfSelection::page + + The page number on which to search. + + \sa QtQuick::Image::currentFrame +*/ +int QQuickPdfSelection::page() const +{ + return m_page; +} + +void QQuickPdfSelection::setPage(int page) +{ + if (m_page == page) + return; + + m_page = page; + m_pageTextDirty = true; + emit pageChanged(); + resetPoints(); +} + +/*! + \qmlproperty real PdfSelection::renderScale + \brief The ratio from points to pixels at which the page is rendered. + + This is used to scale \l fromPoint and \l toPoint to find ranges of + selected characters in the document, because positions within the document + are always given in points. +*/ +qreal QQuickPdfSelection::renderScale() const +{ + return m_renderScale; +} + +void QQuickPdfSelection::setRenderScale(qreal scale) +{ + if (qFuzzyCompare(scale, m_renderScale)) + return; + + m_renderScale = scale; + emit renderScaleChanged(); + updateResults(); +} + +/*! + \qmlproperty point PdfSelection::fromPoint + + The beginning location, in pixels from the upper-left corner of the page, + from which to find selected text. This can be bound to the + \c centroid.pressPosition of a \l DragHandler to begin selecting text from + the position where the user presses the mouse button and begins dragging, + for example. +*/ +QPointF QQuickPdfSelection::fromPoint() const +{ + return m_fromPoint; +} + +void QQuickPdfSelection::setFromPoint(QPointF fromPoint) +{ + if (m_hold || m_fromPoint == fromPoint) + return; + + m_fromPoint = fromPoint; + emit fromPointChanged(); + updateResults(); +} + +/*! + \qmlproperty point PdfSelection::toPoint + + The ending location, in pixels from the upper-left corner of the page, + from which to find selected text. This can be bound to the + \c centroid.position of a \l DragHandler to end selection of text at the + position where the user is currently dragging the mouse, for example. +*/ +QPointF QQuickPdfSelection::toPoint() const +{ + return m_toPoint; +} + +void QQuickPdfSelection::setToPoint(QPointF toPoint) +{ + if (m_hold || m_toPoint == toPoint) + return; + + m_toPoint = toPoint; + emit toPointChanged(); + updateResults(); +} + +/*! + \qmlproperty bool PdfSelection::hold + + Controls whether to hold the existing selection regardless of changes to + \l fromPoint and \l toPoint. This property can be set to \c true when the mouse + or touchpoint is released, so that the selection is not lost due to the + point bindings changing. +*/ +bool QQuickPdfSelection::hold() const +{ + return m_hold; +} + +void QQuickPdfSelection::setHold(bool hold) +{ + if (m_hold == hold) + return; + + m_hold = hold; + emit holdChanged(); +} + +/*! + \qmlproperty string PdfSelection::string + + The string found. +*/ +QString QQuickPdfSelection::text() const +{ + return m_text; +} + +#if QT_CONFIG(clipboard) +/*! + \qmlmethod void PdfSelection::copyToClipboard() + + Copies plain text from the \l string property to the system clipboard. +*/ +void QQuickPdfSelection::copyToClipboard() const +{ + QGuiApplication::clipboard()->setText(m_text); +} +#endif + +void QQuickPdfSelection::updateResults() +{ + if (!m_document) + return; + QPdfSelection sel = m_document->document().getSelection(m_page, + m_fromPoint / m_renderScale, m_toPoint / m_renderScale); + update(sel, true); +} + +void QQuickPdfSelection::update(const QPdfSelection &sel, bool textAndGeometryOnly) +{ + if (sel.text() != m_text) { + m_text = sel.text(); + if (QGuiApplication::clipboard()->supportsSelection()) + sel.copyToClipboard(QClipboard::Selection); + emit textChanged(); + } + + if (sel.bounds() != m_geometry) { + m_geometry = sel.bounds(); + emit selectedAreaChanged(); + } + + if (textAndGeometryOnly) + return; + + m_fromCharIndex = sel.startIndex(); + m_toCharIndex = sel.endIndex(); + if (sel.bounds().isEmpty()) { + m_fromPoint = sel.boundingRectangle().topLeft() * m_renderScale; + m_toPoint = m_fromPoint; + } else { + Qt::InputMethodQueries toUpdate = {}; + QRectF firstLineBounds = sel.bounds().first().boundingRect(); + m_fromPoint = firstLineBounds.topLeft() * m_renderScale; + if (!qFuzzyCompare(m_heightAtAnchor, firstLineBounds.height())) { + m_heightAtAnchor = firstLineBounds.height() * m_renderScale; + toUpdate.setFlag(Qt::ImAnchorRectangle); + } + QRectF lastLineBounds = sel.bounds().last().boundingRect(); + if (!qFuzzyCompare(m_heightAtCursor, lastLineBounds.height())) { + m_heightAtCursor = lastLineBounds.height() * m_renderScale; + toUpdate.setFlag(Qt::ImCursorRectangle); + } + m_toPoint = lastLineBounds.topRight() * m_renderScale; + if (toUpdate) + QGuiApplication::inputMethod()->update(toUpdate); + } +} + +QT_END_NAMESPACE diff --git a/src/pdfquick/qquickpdfselection_p.h b/src/pdfquick/qquickpdfselection_p.h new file mode 100644 index 000000000..b364a6c03 --- /dev/null +++ b/src/pdfquick/qquickpdfselection_p.h @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKPDFSELECTION_P_H +#define QQUICKPDFSELECTION_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QPdfSelection; + +class Q_PDFQUICK_EXPORT QQuickPdfSelection : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(QQuickPdfDocument *document READ document WRITE setDocument NOTIFY documentChanged) + Q_PROPERTY(int page READ page WRITE setPage NOTIFY pageChanged) + Q_PROPERTY(qreal renderScale READ renderScale WRITE setRenderScale NOTIFY renderScaleChanged) + Q_PROPERTY(QPointF fromPoint READ fromPoint WRITE setFromPoint NOTIFY fromPointChanged) + Q_PROPERTY(QPointF toPoint READ toPoint WRITE setToPoint NOTIFY toPointChanged) + Q_PROPERTY(bool hold READ hold WRITE setHold NOTIFY holdChanged) + + Q_PROPERTY(QString text READ text NOTIFY textChanged) + Q_PROPERTY(QList geometry READ geometry NOTIFY selectedAreaChanged) + +public: + explicit QQuickPdfSelection(QQuickItem *parent = nullptr); + + QQuickPdfDocument *document() const; + void setDocument(QQuickPdfDocument * document); + int page() const; + void setPage(int page); + qreal renderScale() const; + void setRenderScale(qreal scale); + QPointF fromPoint() const; + void setFromPoint(QPointF fromPoint); + QPointF toPoint() const; + void setToPoint(QPointF toPoint); + bool hold() const; + void setHold(bool hold); + + QString text() const; + QList geometry() const; + + Q_INVOKABLE void clear(); + Q_INVOKABLE void selectAll(); +#if QT_CONFIG(clipboard) + Q_INVOKABLE void copyToClipboard() const; +#endif + +signals: + void documentChanged(); + void pageChanged(); + void renderScaleChanged(); + void fromPointChanged(); + void toPointChanged(); + void holdChanged(); + void textChanged(); + void selectedAreaChanged(); + +protected: +#if QT_CONFIG(im) + void keyReleaseEvent(QKeyEvent *ev) override; + void inputMethodEvent(QInputMethodEvent *event) override; + Q_INVOKABLE QVariant inputMethodQuery(Qt::InputMethodQuery query, const QVariant &argument) const; + QVariant inputMethodQuery(Qt::InputMethodQuery query) const override; +#endif + +private: + void resetPoints(); + void updateResults(); + void update(const QPdfSelection &sel, bool textAndGeometryOnly = false); + const QString &pageText() const; + +private: + QQuickPdfDocument *m_document = nullptr; + mutable QPointF m_hitPoint; + QPointF m_fromPoint; + mutable QPointF m_toPoint; + qreal m_renderScale = 1; + mutable qreal m_heightAtAnchor = 0; + mutable qreal m_heightAtCursor = 0; + QString m_text; // selected text + mutable QString m_pageText; // all text on the page + QList m_geometry; + int m_page = 0; + int m_fromCharIndex = -1; // same as anchor position + mutable int m_toCharIndex = -1; // same as cursor position + bool m_hold = false; + mutable bool m_pageTextDirty = true; + + Q_DISABLE_COPY(QQuickPdfSelection) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickPdfSelection) + +#endif // QQUICKPDFSELECTION_P_H diff --git a/src/pdfquick/qquicktableviewextra.cpp b/src/pdfquick/qquicktableviewextra.cpp new file mode 100644 index 000000000..017764a95 --- /dev/null +++ b/src/pdfquick/qquicktableviewextra.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquicktableviewextra_p.h" +#include +#include + +Q_LOGGING_CATEGORY(qLcTVE, "qt.pdf.tableextra") + +QT_BEGIN_NAMESPACE + +/*! + \internal + \qmltype TableViewExtra + \instantiates QQuickTableViewExtra + \inqmlmodule QtQuick.Pdf + \ingroup pdf + \brief A helper class with missing TableView functions + \since 5.15 + + TableViewExtra provides equivalents for some functions that will be added + to TableView in Qt 6. +*/ + +QQuickTableViewExtra::QQuickTableViewExtra(QObject *parent) : QObject(parent) +{ +} + +QPoint QQuickTableViewExtra::cellAtPos(qreal x, qreal y) const +{ + QPointF position(x, y); + return m_tableView->cellAtPos(position); +} + +QQuickItem *QQuickTableViewExtra::itemAtCell(const QPoint &cell) const +{ + return m_tableView->itemAtCell(cell); +} + +void QQuickTableViewExtra::positionViewAtCell(const QPoint &cell, Qt::Alignment alignment, const QPointF &offset) +{ + m_tableView->positionViewAtCell(cell, alignment, offset); +} + +QT_END_NAMESPACE diff --git a/src/pdfquick/qquicktableviewextra_p.h b/src/pdfquick/qquicktableviewextra_p.h new file mode 100644 index 000000000..30eed696d --- /dev/null +++ b/src/pdfquick/qquicktableviewextra_p.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtPDF module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKTABLEVIEWEXTRA_P_H +#define QQUICKTABLEVIEWEXTRA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_PDFQUICK_EXPORT QQuickTableViewExtra : public QObject +{ + Q_OBJECT + Q_PROPERTY(QQuickTableView *tableView READ tableView WRITE setTableView) + +public: + QQuickTableViewExtra(QObject *parent = nullptr); + + QQuickTableView * tableView() const { return m_tableView; } + void setTableView(QQuickTableView * tableView) { m_tableView = tableView; } + + Q_INVOKABLE QPoint cellAtPos(qreal x, qreal y) const; + Q_INVOKABLE QQuickItem *itemAtCell(int column, int row) const { + return itemAtCell(QPoint(column, row)); + } + Q_INVOKABLE QQuickItem *itemAtCell(const QPoint &cell) const; + Q_INVOKABLE void positionViewAtCell(int column, int row, Qt::Alignment alignment, const QPointF &offset = QPointF()) { + positionViewAtCell(QPoint(column, row), alignment, offset); + } + Q_INVOKABLE void positionViewAtCell(const QPoint &cell, Qt::Alignment alignment, const QPointF &offset); + Q_INVOKABLE void positionViewAtRow(int row, Qt::Alignment alignment, qreal offset = 0) { + positionViewAtCell(QPoint(0, row), alignment & Qt::AlignVertical_Mask, QPointF(0, offset)); + } + +private: + QQuickTableView *m_tableView = nullptr; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickTableViewExtra) + +#endif // QQUICKTABLEVIEWEXTRA_P_H diff --git a/src/pdfquick/qtpdfquickglobal_p.h b/src/pdfquick/qtpdfquickglobal_p.h new file mode 100644 index 000000000..226a82c28 --- /dev/null +++ b/src/pdfquick/qtpdfquickglobal_p.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2021 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTPDFQUICKGLOBAL_H +#define QTPDFQUICKGLOBAL_H + +#include + +QT_BEGIN_NAMESPACE + +#ifndef QT_STATIC +# if defined(QT_BUILD_PDFQUICK_LIB) +# define Q_PDFQUICK_EXPORT Q_DECL_EXPORT +# else +# define Q_PDFQUICK_EXPORT Q_DECL_IMPORT +# endif +#else +# define Q_PDFQUICK_EXPORT +#endif + +QT_END_NAMESPACE + +#endif // QTPDFQUICKGLOBAL_H diff --git a/src/pdfwidgets/CMakeLists.txt b/src/pdfwidgets/CMakeLists.txt new file mode 100644 index 000000000..04ca1387e --- /dev/null +++ b/src/pdfwidgets/CMakeLists.txt @@ -0,0 +1,15 @@ +find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS Core Gui Widgets) + +qt_internal_add_module(PdfWidgets + SOURCES + qpdfview.cpp qpdfview.h qpdfview_p.h + qtpdfwidgetsglobal.h + LIBRARIES + Qt::WidgetsPrivate + PUBLIC_LIBRARIES + Qt::Core + Qt::Gui + Qt::Widgets + Qt::Pdf +) +make_install_only(PdfWidgets) diff --git a/src/plugins/imageformats/pdf/main.cpp b/src/plugins/imageformats/pdf/main.cpp deleted file mode 100644 index b4d59353c..000000000 --- a/src/plugins/imageformats/pdf/main.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qpdfiohandler_p.h" - -QT_BEGIN_NAMESPACE - -class QPdfPlugin : public QImageIOPlugin -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID QImageIOHandlerFactoryInterface_iid FILE "pdf.json") - -public: - Capabilities capabilities(QIODevice *device, const QByteArray &format) const override; - QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override; -}; - -QImageIOPlugin::Capabilities QPdfPlugin::capabilities(QIODevice *device, const QByteArray &format) const -{ - if (format == "pdf") - return Capabilities(CanRead); - if (!format.isEmpty()) - return {}; - - Capabilities cap; - if (device->isReadable() && QPdfIOHandler::canRead(device)) - cap |= CanRead; - return cap; -} - -QImageIOHandler *QPdfPlugin::create(QIODevice *device, const QByteArray &format) const -{ - QPdfIOHandler *hand = new QPdfIOHandler(); - hand->setDevice(device); - hand->setFormat(format); - return hand; -} - -QT_END_NAMESPACE - -#include "main.moc" diff --git a/src/plugins/imageformats/pdf/pdf.json b/src/plugins/imageformats/pdf/pdf.json deleted file mode 100644 index 1f5268ca1..000000000 --- a/src/plugins/imageformats/pdf/pdf.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "Keys": [ "pdf" ], - "MimeTypes": [ "application/pdf" ] -} diff --git a/src/plugins/imageformats/pdf/qpdfiohandler.cpp b/src/plugins/imageformats/pdf/qpdfiohandler.cpp deleted file mode 100644 index 4f610935c..000000000 --- a/src/plugins/imageformats/pdf/qpdfiohandler.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qpdfiohandler_p.h" -#include -#include - -QT_BEGIN_NAMESPACE - -Q_LOGGING_CATEGORY(qLcPdf, "qt.imageformat.pdf") - -QPdfIOHandler::QPdfIOHandler() -{ -} - -bool QPdfIOHandler::canRead() const -{ - if (!device()) - return false; - if (m_loaded) - return true; - if (QPdfIOHandler::canRead(device())) { - setFormat("pdf"); - return true; - } - return false; -} - -bool QPdfIOHandler::canRead(QIODevice *device) -{ - char buf[6]; - device->peek(buf, 6); - return (!qstrncmp(buf, "%PDF-", 5) || Q_UNLIKELY(!qstrncmp(buf, "\012%PDF-", 6))); -} - -int QPdfIOHandler::currentImageNumber() const -{ - return m_page; -} - -QRect QPdfIOHandler::currentImageRect() const -{ - return QRect(QPoint(0, 0), m_doc.pageSize(m_page).toSize()); -} - -int QPdfIOHandler::imageCount() const -{ - int ret = 0; - if (const_cast(this)->load(device())) - ret = m_doc.pageCount(); - qCDebug(qLcPdf) << "imageCount" << ret; - return ret; -} - -bool QPdfIOHandler::read(QImage *image) -{ - if (load(device())) { - if (m_page >= m_doc.pageCount()) - return false; - if (m_page < 0) - m_page = 0; - const bool xform = (m_clipRect.isValid() || m_scaledSize.isValid() || m_scaledClipRect.isValid()); - QSize pageSize = m_doc.pageSize(m_page).toSize(); - QSize finalSize = pageSize; - QRectF bounds; - if (xform && !finalSize.isEmpty()) { - bounds = QRectF(QPointF(0,0), QSizeF(finalSize)); - QPoint tr1, tr2; - QSizeF sc(1, 1); - if (m_clipRect.isValid()) { - tr1 = -m_clipRect.topLeft(); - finalSize = m_clipRect.size(); - } - if (m_scaledSize.isValid()) { - sc = QSizeF(qreal(m_scaledSize.width()) / finalSize.width(), - qreal(m_scaledSize.height()) / finalSize.height()); - finalSize = m_scaledSize; - pageSize = m_scaledSize; - } - if (m_scaledClipRect.isValid()) { - tr2 = -m_scaledClipRect.topLeft(); - finalSize = m_scaledClipRect.size(); - } - QTransform t; - t.translate(tr2.x(), tr2.y()); - t.scale(sc.width(), sc.height()); - t.translate(tr1.x(), tr1.y()); - bounds = t.mapRect(bounds); - } - qCDebug(qLcPdf) << Q_FUNC_INFO << m_page << finalSize; - if (image->size() != finalSize || !image->reinterpretAsFormat(QImage::Format_ARGB32_Premultiplied)) { - *image = QImage(finalSize, QImage::Format_ARGB32_Premultiplied); - if (!finalSize.isEmpty() && image->isNull()) { - // avoid QTBUG-68229 - qWarning("QPdfIOHandler: QImage allocation failed (size %i x %i)", finalSize.width(), finalSize.height()); - return false; - } - } - if (!finalSize.isEmpty()) { - QPdfDocumentRenderOptions options; - if (m_scaledClipRect.isValid()) - options.setScaledClipRect(m_scaledClipRect); - options.setScaledSize(pageSize); - image->fill(m_backColor.rgba()); - QPainter p(image); - QImage pageImage = m_doc.render(m_page, finalSize, options); - p.drawImage(0, 0, pageImage); - p.end(); - } - return true; - } - - return false; -} - -QVariant QPdfIOHandler::option(ImageOption option) const -{ - switch (option) { - case ImageFormat: - return QImage::Format_ARGB32_Premultiplied; - case Size: - const_cast(this)->load(device()); - return m_doc.pageSize(qMax(0, m_page)); - case ClipRect: - return m_clipRect; - case ScaledSize: - return m_scaledSize; - case ScaledClipRect: - return m_scaledClipRect; - case BackgroundColor: - return m_backColor; - case Name: - return m_doc.metaData(QPdfDocument::Title); - default: - break; - } - return QVariant(); -} - -void QPdfIOHandler::setOption(ImageOption option, const QVariant & value) -{ - switch (option) { - case ClipRect: - m_clipRect = value.toRect(); - break; - case ScaledSize: - m_scaledSize = value.toSize(); - break; - case ScaledClipRect: - m_scaledClipRect = value.toRect(); - break; - case BackgroundColor: - m_backColor = value.value(); - break; - default: - break; - } -} - -bool QPdfIOHandler::supportsOption(ImageOption option) const -{ - switch (option) - { - case ImageFormat: - case Size: - case ClipRect: - case ScaledSize: - case ScaledClipRect: - case BackgroundColor: - case Name: - return true; - default: - break; - } - return false; -} - -bool QPdfIOHandler::jumpToImage(int frame) -{ - qCDebug(qLcPdf) << Q_FUNC_INFO << frame; - if (frame < 0 || frame >= imageCount()) - return false; - m_page = frame; - return true; -} - -bool QPdfIOHandler::jumpToNextImage() -{ - return jumpToImage(m_page + 1); -} - -bool QPdfIOHandler::load(QIODevice *device) -{ - if (m_loaded) - return true; - if (format().isEmpty()) - if (!canRead()) - return false; - - m_doc.load(device); - m_loaded = (m_doc.error() == QPdfDocument::DocumentError::NoError); - - return m_loaded; -} - -QT_END_NAMESPACE diff --git a/src/plugins/imageformats/pdf/qpdfiohandler_p.h b/src/plugins/imageformats/pdf/qpdfiohandler_p.h deleted file mode 100644 index 99a91154c..000000000 --- a/src/plugins/imageformats/pdf/qpdfiohandler_p.h +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtPDF module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QPDFIOHANDLER_H -#define QPDFIOHANDLER_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include -#include - -QT_BEGIN_NAMESPACE - -class QPdfIOHandler : public QImageIOHandler -{ -public: - QPdfIOHandler(); - bool canRead() const override; - static bool canRead(QIODevice *device); - int currentImageNumber() const override; - QRect currentImageRect() const override; - int imageCount() const override; - bool read(QImage *image) override; - QVariant option(ImageOption option) const override; - void setOption(ImageOption option, const QVariant & value) override; - bool supportsOption(ImageOption option) const override; - bool jumpToImage(int frame) override; - bool jumpToNextImage() override; - -private: - bool load(QIODevice *device); - -private: - QPdfDocument m_doc; - int m_page = -1; - - QRect m_clipRect; - QSize m_scaledSize; - QRect m_scaledClipRect; - QColor m_backColor = Qt::transparent; - bool m_loaded = false; -}; - -QT_END_NAMESPACE - -#endif // QPDFIOHANDLER_H diff --git a/sync.profile b/sync.profile index 57ec30099..44a85e829 100644 --- a/sync.profile +++ b/sync.profile @@ -3,12 +3,12 @@ "QtWebEngineWidgets" => "$basedir/src/webenginewidgets", "QtWebEngineCore" => "$basedir/src/core/api", "QtPdf" => "$basedir/src/pdf", + "QtPdfQuick" => "$basedir/src/pdfquick", "QtPdfWidgets" => "$basedir/src/pdfwidgets", ); %moduleheaders = ( # restrict the module headers to those found in relative path "QtWebEngineQuick" => "api", - "QtWebEngineWidgets" => "api", - "QtPdf" => "api" + "QtWebEngineWidgets" => "api" ); %classnames = ( ); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8d1f1a002..ace11de4a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -16,7 +16,8 @@ endif() find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals Core) find_package(Qt6 ${PROJECT_VERSION} CONFIG OPTIONAL_COMPONENTS Gui Widgets - WebEngineCore WebEngineWidgets WebEngineQuick QuickWidgets Test QuickTest WebSockets) + WebEngineCore WebEngineWidgets WebEngineQuick Pdf QuickWidgets Test QuickTest WebSockets +) if(NOT QT_BUILD_STANDALONE_TESTS) qt_build_repo_begin() diff --git a/tests/auto/CMakeLists.txt b/tests/auto/CMakeLists.txt index 2227e6e46..1e5c1f6bd 100644 --- a/tests/auto/CMakeLists.txt +++ b/tests/auto/CMakeLists.txt @@ -12,6 +12,7 @@ if(QT_FEATURE_qtwebengine_widgets_build OR (QT_BUILD_STANDALONE_TESTS AND TARGET Qt::WebEngineWidgets)) add_subdirectory(widgets) endif() -#if(QT_FEATURE_build_qtpdf AND QT_FEATURE_webengine_qtpdf_support) -# add_subdirectory(pdf) -#endif() +if(QT_FEATURE_qtpdf_build + OR (QT_BUILD_STANDALONE_TESTS AND TARGET Qt::Pdf)) + add_subdirectory(pdf) +endif() diff --git a/tests/auto/pdf/CMakeLists.txt b/tests/auto/pdf/CMakeLists.txt new file mode 100644 index 000000000..1220581ca --- /dev/null +++ b/tests/auto/pdf/CMakeLists.txt @@ -0,0 +1,6 @@ +add_subdirectory(qpdfbookmarkmodel) +add_subdirectory(qpdfpagenavigation) +add_subdirectory(qpdfpagerenderer) +if(TARGET Qt::PrintSupport) + add_subdirectory(qpdfdocument) +endif() diff --git a/tests/auto/pdf/qpdfbookmarkmodel/CMakeLists.txt b/tests/auto/pdf/qpdfbookmarkmodel/CMakeLists.txt new file mode 100644 index 000000000..f0300ce7b --- /dev/null +++ b/tests/auto/pdf/qpdfbookmarkmodel/CMakeLists.txt @@ -0,0 +1,9 @@ +qt_internal_add_test(tst_qpdfbookmarkmodel + SOURCES + tst_qpdfbookmarkmodel.cpp + PUBLIC_LIBRARIES + Qt::Gui + Qt::Network + Qt::Pdf +) + diff --git a/tests/auto/pdf/qpdfdocument/CMakeLists.txt b/tests/auto/pdf/qpdfdocument/CMakeLists.txt new file mode 100644 index 000000000..4551fdb6c --- /dev/null +++ b/tests/auto/pdf/qpdfdocument/CMakeLists.txt @@ -0,0 +1,9 @@ +qt_internal_add_test(tst_qpdfdocument + SOURCES + tst_qpdfdocument.cpp + PUBLIC_LIBRARIES + Qt::Gui + Qt::Network + Qt::PrintSupport + Qt::Pdf +) diff --git a/tests/auto/pdf/qpdfpagenavigation/CMakeLists.txt b/tests/auto/pdf/qpdfpagenavigation/CMakeLists.txt new file mode 100644 index 000000000..12ece7507 --- /dev/null +++ b/tests/auto/pdf/qpdfpagenavigation/CMakeLists.txt @@ -0,0 +1,8 @@ +qt_internal_add_test(tst_qpdfpagenavigation + SOURCES + tst_qpdfpagenavigation.cpp + PUBLIC_LIBRARIES + Qt::Gui + Qt::Network + Qt::Pdf +) diff --git a/tests/auto/pdf/qpdfpagerenderer/CMakeLists.txt b/tests/auto/pdf/qpdfpagerenderer/CMakeLists.txt new file mode 100644 index 000000000..f4084cce1 --- /dev/null +++ b/tests/auto/pdf/qpdfpagerenderer/CMakeLists.txt @@ -0,0 +1,9 @@ +qt_internal_add_test(tst_qpdfpagerenderer + SOURCES + tst_qpdfpagerenderer.cpp + PUBLIC_LIBRARIES + Qt::Gui + Qt::Network + Qt::Pdf +) + diff --git a/tests/auto/pdf/qpdfsearchmodel/CMakeLists.txt b/tests/auto/pdf/qpdfsearchmodel/CMakeLists.txt new file mode 100644 index 000000000..2c3e744d0 --- /dev/null +++ b/tests/auto/pdf/qpdfsearchmodel/CMakeLists.txt @@ -0,0 +1,8 @@ +qt_internal_add_test(tst_qpdfsearchmodel + SOURCES + tst_qpdfsearchmodel.cpp + PUBLIC_LIBRARIES + Qt::Gui + Qt::Network + Qt::Pdf +) -- cgit v1.2.3