mirror of
https://invent.kde.org/graphics/okular
synced 2024-10-01 05:33:33 +00:00
Merge branch 'master' of https://invent.kde.org/graphics/okular into work/hires_wheel_page_scroll_rework
This commit is contained in:
commit
4a6d28ddb8
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
Checks: 'clang-diagnostic-*,clang-analyzer-*,-*,performance-*,bugprone-*,readability-inconsistent-declaration-parameter-name,readability-string-compare,readability-braces-around-statements,modernize-redundant-void-arg,modernize-use-bool-literals,modernize-make-unique,modernize-make-shared,modernize-use-override,modernize-use-equals-delete,modernize-use-emplace,modernize-loop-convert,modernize-use-nullptr,google-explicit-constructor,-bugprone-macro-parentheses,-bugprone-narrowing-conversions,-bugprone-branch-clone,-bugprone-incorrect-roundings,-bugprone-suspicious-include,-bugprone-reserved-identifier,-performance-no-automatic-move,-bugprone-suspicious-enum-usage,-bugprone-easily-swappable-parameters,-performance-no-int-to-ptr,-bugprone-implicit-widening-of-multiplication-result'
|
||||
Checks: 'clang-diagnostic-*,clang-analyzer-*,-*,performance-*,bugprone-*,readability-inconsistent-declaration-parameter-name,readability-string-compare,readability-braces-around-statements,modernize-redundant-void-arg,modernize-use-bool-literals,modernize-make-unique,modernize-make-shared,modernize-use-override,modernize-use-equals-delete,modernize-use-emplace,modernize-loop-convert,modernize-use-nullptr,google-explicit-constructor,-bugprone-assignment-in-if-condition,-bugprone-switch-missing-default-case,-bugprone-macro-parentheses,-bugprone-narrowing-conversions,-bugprone-branch-clone,-bugprone-incorrect-roundings,-bugprone-suspicious-include,-bugprone-reserved-identifier,-performance-no-automatic-move,-bugprone-suspicious-enum-usage,-bugprone-easily-swappable-parameters,-performance-no-int-to-ptr,-bugprone-implicit-widening-of-multiplication-result,-performance-unnecessary-copy-initialization'
|
||||
WarningsAsErrors: '*'
|
||||
HeaderFilterRegex: '.*/okular/.*'
|
||||
AnalyzeTemporaryDtors: false
|
||||
|
|
5
.craft.ini
Normal file
5
.craft.ini
Normal file
|
@ -0,0 +1,5 @@
|
|||
; SPDX-FileCopyrightText: None
|
||||
; SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
[BlueprintSettings]
|
||||
kde/applications/okular.packageAppx = True
|
|
@ -2,57 +2,75 @@ variables:
|
|||
DEBIAN_FRONTEND: "noninteractive"
|
||||
|
||||
include:
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/android.yml
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml
|
||||
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/windows.yml
|
||||
- project: sysadmin/ci-utilities
|
||||
file:
|
||||
- /gitlab-templates/android-qt6.yml
|
||||
- /gitlab-templates/linux-qt6.yml
|
||||
- /gitlab-templates/freebsd-qt6.yml
|
||||
- /gitlab-templates/windows-qt6.yml
|
||||
- /gitlab-templates/cppcheck.yml
|
||||
- /gitlab-templates/xml-lint.yml
|
||||
- /gitlab-templates/craft-windows-x86-64-qt6.yml
|
||||
# - /gitlab-templates/craft-android-qt6-apks.yml
|
||||
- /gitlab-templates/craft-macos-arm64-qt6.yml
|
||||
- /gitlab-templates/craft-macos-x86-64-qt6.yml
|
||||
|
||||
build_ubuntu_20_04:
|
||||
stage: build
|
||||
image: ubuntu:focal
|
||||
tags:
|
||||
- Linux
|
||||
only:
|
||||
- merge_requests
|
||||
before_script:
|
||||
- sed -i -e 's/# deb-src/deb-src/g' /etc/apt/sources.list
|
||||
- apt-get update
|
||||
- apt-get install --yes eatmydata
|
||||
- eatmydata apt-get build-dep --yes --no-install-recommends okular
|
||||
- eatmydata apt-get install --yes --no-install-recommends ninja-build qtbase5-private-dev
|
||||
script:
|
||||
- mkdir -p build && cd build
|
||||
- cmake -DOKULAR_UI=desktop -G Ninja ..
|
||||
- ninja
|
||||
|
||||
#build_ubuntu_22_04:
|
||||
# stage: build
|
||||
# image: ubuntu:22.04
|
||||
# tags:
|
||||
# - Linux
|
||||
# only:
|
||||
# - merge_requests
|
||||
# before_script:
|
||||
# - sed -i -e 's/# deb-src/deb-src/g' /etc/apt/sources.list
|
||||
# - apt-get update
|
||||
# - apt-get install --yes eatmydata
|
||||
# - eatmydata apt-get build-dep --yes --no-install-recommends okular
|
||||
# - eatmydata apt-get install --yes --no-install-recommends ninja-build libqt5x11extras5-dev
|
||||
# script:
|
||||
# - mkdir -p build && cd build
|
||||
# - cmake -DOKULAR_UI=desktop -G Ninja ..
|
||||
# - ninja
|
||||
|
||||
build_clazy_clang_tidy:
|
||||
stage: build
|
||||
image: debian:unstable
|
||||
image: invent-registry.kde.org/sysadmin/ci-images/suse-qt66:latest
|
||||
tags:
|
||||
- Linux
|
||||
interruptible: true
|
||||
before_script:
|
||||
- git clone https://invent.kde.org/sysadmin/ci-utilities.git --depth=1
|
||||
- git clone https://invent.kde.org/sysadmin/repo-metadata.git ci-utilities/repo-metadata/ --depth=1
|
||||
only:
|
||||
- merge_requests
|
||||
before_script:
|
||||
- echo 'deb-src http://deb.debian.org/debian unstable main' >> /etc/apt/sources.list
|
||||
- apt-get update
|
||||
- apt-get install --yes eatmydata
|
||||
- eatmydata apt-get build-dep --yes --no-install-recommends okular
|
||||
- eatmydata apt-get install --yes --no-install-recommends ninja-build clazy clang clang-tidy qtbase5-private-dev libkf5crash-dev libkf5purpose-dev kirigami2-dev libegl-dev jq
|
||||
|
||||
variables:
|
||||
KDECI_CC_CACHE: /mnt/caches/suse-qt6.6/
|
||||
KDECI_CACHE_PATH: /mnt/artifacts/suse-qq6.6/
|
||||
KDECI_GITLAB_SERVER: https://invent.kde.org/
|
||||
KDECI_PACKAGE_PROJECT: teams/ci-artifacts/suse-qt6.6
|
||||
CLAZY_CHECKS: level0,level1,level2,no-ctor-missing-parent-argument,isempty-vs-count,qhash-with-char-pointer-key,raw-environment-function,qproperty-type-mismatch
|
||||
CXXFLAGS: -Werror -Wno-deprecated-declarations
|
||||
CC: clang
|
||||
CXX: clazy
|
||||
script:
|
||||
- srcdir=`pwd` && mkdir -p /tmp/okular_build && cd /tmp/okular_build && CC=clang CXX=clazy CXXFLAGS="-Werror -Wno-deprecated-declarations" cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G Ninja $srcdir && cat compile_commands.json | jq '[.[] | select(.file | contains("'"$srcdir"'"))]' > compile_commands.aux.json && cat compile_commands.aux.json | jq '[.[] | select(.file | contains("/synctex/")| not)]' > compile_commands.json && cp "$srcdir/.clang-tidy" .
|
||||
- CLAZY_IGNORE_DIRS="settings_core.[cpp|h]|settings.[cpp.h]|pdfsettings.h|gssettings.h" CLAZY_CHECKS="level0,level1,level2,no-ctor-missing-parent-argument,isempty-vs-count,qhash-with-char-pointer-key,raw-environment-function,qproperty-type-mismatch" ninja
|
||||
- run-clang-tidy-14
|
||||
- rm -rf *
|
||||
- echo "Now compiling the mobile UI"
|
||||
- cd "$CI_PROJECT_DIR"
|
||||
- srcdir=`pwd` && mkdir -p /tmp/okular_build && cd /tmp/okular_build && CC=clang CXX=clazy CXXFLAGS="-Werror -Wno-deprecated-declarations" cmake -DOKULAR_UI=mobile -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G Ninja $srcdir && cat compile_commands.json | jq '[.[] | select(.file | contains("'"$srcdir"'"))]' > compile_commands.aux.json && cat compile_commands.aux.json | jq '[.[] | select(.file | contains("/synctex/")| not)]' > compile_commands.json && cp "$srcdir/.clang-tidy" .
|
||||
- CLAZY_IGNORE_DIRS="settings_mobile.[cpp|h]|settings.[cpp.h]|pdfsettings.h|gssettings.h" CLAZY_CHECKS="level0,level1,level2,no-ctor-missing-parent-argument,isempty-vs-count,qhash-with-char-pointer-key,raw-environment-function,qproperty-type-mismatch" ninja
|
||||
- run-clang-tidy-14
|
||||
- git config --global --add safe.directory $CI_PROJECT_DIR
|
||||
- python3 -u ci-utilities/run-ci-build.py --project $CI_PROJECT_NAME --branch $CI_COMMIT_REF_NAME --platform Linux/Qt5/Shared --only-setup-environment
|
||||
- mkdir -p /tmp/okular_build
|
||||
- cd /tmp/okular_build
|
||||
- cmake -DOKULAR_UI=both -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G Ninja -DCMAKE_INSTALL_PREFIX=$CI_PROJECT_DIR/_install -DFORCE_NOT_REQUIRED_DEPENDENCIES=KF6DocTools -DKF6DocTools_FOUND=false $CI_PROJECT_DIR
|
||||
- cat compile_commands.json | jq '[.[] | select(.file | contains("'"$CI_PROJECT_DIR"'"))]' > compile_commands.aux.json
|
||||
- cat compile_commands.aux.json | jq '[.[] | select(.file | contains("/synctex/")| not)]' > compile_commands.json
|
||||
- cp "$CI_PROJECT_DIR/.clang-tidy" .
|
||||
- CLAZY_IGNORE_DIRS="settings_core.[cpp|h]|settings.[cpp.h]|pdfsettings.h|gssettings.h|ui_selectcertificatedialog.h" ninja -k 0
|
||||
- run-clang-tidy
|
||||
|
||||
clang_format:
|
||||
stage: build
|
||||
image: debian:testing
|
||||
image: debian:stable
|
||||
tags:
|
||||
- Linux
|
||||
only:
|
||||
- merge_requests
|
||||
- master
|
||||
|
|
41
.kde-ci.yml
41
.kde-ci.yml
|
@ -4,26 +4,43 @@
|
|||
Dependencies:
|
||||
- 'on': ['@all']
|
||||
'require':
|
||||
'frameworks/kbookmarks': '@stable'
|
||||
'frameworks/threadweaver': '@stable'
|
||||
'frameworks/ki18n': '@stable'
|
||||
'frameworks/kio': '@stable'
|
||||
'frameworks/karchive': '@stable'
|
||||
'libraries/phonon': '@stable'
|
||||
'frameworks/kbookmarks': '@latest-kf6'
|
||||
'frameworks/threadweaver': '@latest-kf6'
|
||||
'frameworks/kcolorscheme': '@latest-kf6'
|
||||
'frameworks/ki18n': '@latest-kf6'
|
||||
'frameworks/kio': '@latest-kf6'
|
||||
'frameworks/kitemviews': '@latest-kf6'
|
||||
'frameworks/karchive': '@latest-kf6'
|
||||
'frameworks/kparts': '@latest-kf6'
|
||||
'frameworks/ktextwidgets': '@latest-kf6'
|
||||
'frameworks/kwidgetsaddons': '@latest-kf6'
|
||||
'frameworks/kxmlgui': '@latest-kf6'
|
||||
'libraries/phonon': '@latest-kf6'
|
||||
'graphics/kdegraphics-mobipocket': '@same'
|
||||
|
||||
- 'on': ['Linux', 'FreeBSD', 'Windows']
|
||||
'require':
|
||||
'frameworks/khtml': '@stable'
|
||||
'frameworks/kjs': '@stable'
|
||||
'frameworks/purpose': '@stable'
|
||||
'frameworks/purpose': '@latest-kf6'
|
||||
'frameworks/breeze-icons': '@latest-kf6'
|
||||
'graphics/libkexiv2': '@same'
|
||||
|
||||
- 'on': ['Linux', 'FreeBSD']
|
||||
'require':
|
||||
'frameworks/kactivities': '@stable'
|
||||
'frameworks/kpty': '@stable'
|
||||
'plasma/plasma-activities': '@latest-kf6'
|
||||
'frameworks/kpty': '@latest-kf6'
|
||||
|
||||
- 'on': ['Android']
|
||||
'require':
|
||||
'frameworks/kirigami': '@stable'
|
||||
'frameworks/kirigami': '@latest-kf6'
|
||||
|
||||
Options:
|
||||
require-passing-tests-on: [ 'Linux', 'FreeBSD' ]
|
||||
per-test-timeout: 300
|
||||
cppcheck-arguments: '--enable=warning,style,performance -DOKULAR_EXPORT_PLUGIN --suppress-xml=cppcheck-suppressions.xml'
|
||||
cppcheck-ignore-files:
|
||||
- autotests
|
||||
- core/synctex/synctex_parser.c
|
||||
xml-validate-include:
|
||||
- shell/shell.rc
|
||||
- part/part-viewermode.rc
|
||||
- part/part.rc
|
||||
|
|
373
CMakeLists.txt
373
CMakeLists.txt
|
@ -1,22 +1,39 @@
|
|||
cmake_minimum_required(VERSION 3.16)
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
# KDE Application Version, managed by release script
|
||||
set (RELEASE_SERVICE_VERSION_MAJOR "22")
|
||||
set (RELEASE_SERVICE_VERSION_MINOR "11")
|
||||
set (RELEASE_SERVICE_VERSION_MAJOR "24")
|
||||
set (RELEASE_SERVICE_VERSION_MINOR "07")
|
||||
set (RELEASE_SERVICE_VERSION_MICRO "70")
|
||||
set (RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
|
||||
|
||||
project(okular VERSION ${RELEASE_SERVICE_VERSION})
|
||||
|
||||
set(QT_REQUIRED_VERSION "5.12.0") # Remember to update the QT_DEPRECATED_WARNINGS_SINCE below
|
||||
set(KF5_REQUIRED_VERSION "5.68.0") # Remember to update the KF_DEPRECATED_WARNINGS_SINCE below
|
||||
set(QT_REQUIRED_VERSION "6.6.0") # Remember to update the QT_DEPRECATED_WARNINGS_SINCE below
|
||||
set(KF_REQUIRED_VERSION "5.240.0") # Remember to update the KF_DEPRECATED_WARNINGS_SINCE below
|
||||
|
||||
set(OKULAR_UI "" CACHE STRING "Which Okular user interface to build. Possible values: desktop, mobile, both. Default: desktop (except on Android, where it is 'mobile')")
|
||||
|
||||
option(FORCE_NOT_REQUIRED_DEPENDENCIES "List (semicolon-separated) of dependencies that will be downgraded from REQUIRED to RECOMMENDED")
|
||||
set(FORCE_NOT_REQUIRED_DEPENDENCIES "" CACHE STRING "List (semicolon-separated) of dependencies that will be downgraded from REQUIRED to RECOMMENDED")
|
||||
|
||||
if (ANDROID AND (NOT FORCE_NOT_REQUIRED_DEPENDENCIES) AND (NOT FORCE_NOT_REQUIRED_DEPENDENCIES STREQUAL ""))
|
||||
set(FORCE_NOT_REQUIRED_DEPENDENCIES "KF5Wallet;KF5DocTools;KF5JS;TIFF;JPEG;LibSpectre;KF5KExiv2;CHM;KF5KHtml;LibZip;DjVuLibre;EPub;Discount;")
|
||||
find_package(ECM ${KF_REQUIRED_VERSION} CONFIG REQUIRED)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH})
|
||||
|
||||
include(ECMInstallIcons)
|
||||
include(ECMSetupVersion)
|
||||
include(ECMOptionalAddSubdirectory)
|
||||
include(GenerateExportHeader)
|
||||
include(FeatureSummary)
|
||||
include(ECMAddAppIcon)
|
||||
include(KDECompilerSettings NO_POLICY_SCOPE)
|
||||
include(KDEInstallDirs)
|
||||
include(KDECMakeSettings)
|
||||
include(ECMAddTests)
|
||||
include(ECMAddAppIcon)
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(ECMSetupQtPluginMacroNames)
|
||||
|
||||
if (ANDROID AND (FORCE_NOT_REQUIRED_DEPENDENCIES STREQUAL ""))
|
||||
set(FORCE_NOT_REQUIRED_DEPENDENCIES "KF6Wallet;KF6DocTools;Qt6Qml;TIFF;LibSpectre;KExiv2Qt6;CHM;LibZip;DjVuLibre;EPub;Discount;")
|
||||
endif()
|
||||
|
||||
function(set_okular_optional_package_properties _name _props)
|
||||
|
@ -65,27 +82,6 @@ else()
|
|||
set(BUILD_MOBILE OFF)
|
||||
endif()
|
||||
|
||||
if (BUILD_MOBILE)
|
||||
set(QT_REQUIRED_VERSION "5.15.2")
|
||||
endif()
|
||||
|
||||
find_package(ECM ${KF5_REQUIRED_VERSION} CONFIG REQUIRED)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH})
|
||||
|
||||
include(ECMInstallIcons)
|
||||
include(ECMSetupVersion)
|
||||
include(ECMOptionalAddSubdirectory)
|
||||
include(GenerateExportHeader)
|
||||
include(FeatureSummary)
|
||||
include(ECMAddAppIcon)
|
||||
include(KDECompilerSettings NO_POLICY_SCOPE)
|
||||
include(KDEInstallDirs)
|
||||
include(KDECMakeSettings)
|
||||
include(ECMAddTests)
|
||||
include(ECMAddAppIcon)
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(ECMSetupQtPluginMacroNames)
|
||||
|
||||
# append the plugins from the install tree folder to the QT_PLUGIN_PATH
|
||||
if(UNIX)
|
||||
set(ENV{QT_PLUGIN_PATH} "$ENV{QT_PLUGIN_PATH}:${KDE_INSTALL_FULL_QTPLUGINDIR}")
|
||||
|
@ -93,20 +89,16 @@ elseif(WIN32)
|
|||
set(ENV{QT_PLUGIN_PATH} "$ENV{QT_PLUGIN_PATH};${KDE_INSTALL_FULL_QTPLUGINDIR}")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
|
||||
ecm_setup_version(${PROJECT_VERSION}
|
||||
VARIABLE_PREFIX OKULAR
|
||||
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/core/version.h"
|
||||
PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/Okular5ConfigVersion.cmake")
|
||||
PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/Okular6ConfigVersion.cmake")
|
||||
|
||||
find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Core Test Widgets PrintSupport Svg Qml Quick)
|
||||
|
||||
if(ANDROID)
|
||||
find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS AndroidExtras)
|
||||
endif()
|
||||
find_package(Qt6 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Core Test Widgets PrintSupport Svg Xml)
|
||||
|
||||
ecm_setup_qtplugin_macro_names(
|
||||
JSON_ARG2
|
||||
|
@ -115,7 +107,7 @@ ecm_setup_qtplugin_macro_names(
|
|||
PACKAGE_SETUP_AUTOMOC_VARIABLES
|
||||
)
|
||||
|
||||
find_package(KF5 ${KF5_REQUIRED_VERSION} REQUIRED COMPONENTS
|
||||
find_package(KF6 ${KF_REQUIRED_VERSION} REQUIRED COMPONENTS
|
||||
Archive
|
||||
Bookmarks
|
||||
Completion
|
||||
|
@ -126,73 +118,106 @@ find_package(KF5 ${KF5_REQUIRED_VERSION} REQUIRED COMPONENTS
|
|||
KIO
|
||||
ThreadWeaver
|
||||
WindowSystem
|
||||
XmlGui
|
||||
)
|
||||
|
||||
find_package(KF5Wallet ${KF5_REQUIRED_VERSION})
|
||||
set_okular_optional_package_properties(KF5Wallet PROPERTIES
|
||||
if (NOT WIN32)
|
||||
find_package(KF6Wallet ${KF_REQUIRED_VERSION})
|
||||
set_okular_optional_package_properties(KF6Wallet PROPERTIES
|
||||
PURPOSE "Required for document storing passwords in secure wallets.")
|
||||
if(KF5Wallet_FOUND)
|
||||
add_definitions(-DWITH_KWALLET=1)
|
||||
endif()
|
||||
if(KF6Wallet_FOUND)
|
||||
set(HAVE_KWALLET 1)
|
||||
else()
|
||||
set(HAVE_KWALLET 0)
|
||||
endif()
|
||||
|
||||
find_package(KF5DocTools ${KF5_REQUIRED_VERSION})
|
||||
set_okular_optional_package_properties(KF5DocTools PROPERTIES
|
||||
find_package(KF6DocTools ${KF_REQUIRED_VERSION})
|
||||
set_okular_optional_package_properties(KF6DocTools PROPERTIES
|
||||
PURPOSE "Required for compiling and installing the user documentation.")
|
||||
|
||||
find_package(KF5JS ${KF5_REQUIRED_VERSION})
|
||||
set_okular_optional_package_properties(KF5JS PROPERTIES
|
||||
find_package(Qt6Qml)
|
||||
set_okular_optional_package_properties(Qt6Qml PROPERTIES
|
||||
PURPOSE "Required for supporting JavaScript in PDF documents")
|
||||
if(KF5JS_FOUND)
|
||||
add_definitions(-DWITH_KJS=1)
|
||||
if(TARGET Qt6::Qml)
|
||||
set(HAVE_JS 1)
|
||||
else()
|
||||
set(HAVE_JS 0)
|
||||
endif()
|
||||
|
||||
if (BUILD_DESKTOP)
|
||||
find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS DBus)
|
||||
find_package(KF5 ${KF5_REQUIRED_VERSION} REQUIRED COMPONENTS Parts Crash IconThemes TextWidgets)
|
||||
find_package(Qt6DBus)
|
||||
set_okular_optional_package_properties(Qt6DBus PROPERTIES
|
||||
PURPOSE "Required for interprocess communication, external open in same instance and various presentation related bits.")
|
||||
if(TARGET Qt6::DBus)
|
||||
set(HAVE_DBUS 1)
|
||||
else()
|
||||
set(HAVE_DBUS 0)
|
||||
endif()
|
||||
find_package(KF6 ${KF_REQUIRED_VERSION} REQUIRED COMPONENTS Parts ColorScheme Crash IconThemes ItemViews TextWidgets WidgetsAddons)
|
||||
|
||||
find_package(KF5Purpose)
|
||||
set_okular_optional_package_properties(KF5Purpose PROPERTIES
|
||||
find_package(KF6Purpose)
|
||||
set_okular_optional_package_properties(KF6Purpose PROPERTIES
|
||||
DESCRIPTION "A framework for services and actions integration"
|
||||
PURPOSE "Required for enabling the share menu.")
|
||||
if (KF5Purpose_FOUND)
|
||||
set(PURPOSE_FOUND 1)
|
||||
if (KF6Purpose_FOUND)
|
||||
set(HAVE_PURPOSE 1)
|
||||
else()
|
||||
set(PURPOSE_FOUND 0)
|
||||
set(HAVE_PURPOSE 0)
|
||||
endif()
|
||||
|
||||
find_package(Qt5TextToSpeech ${QT_REQUIRED_VERSION} CONFIG)
|
||||
set_okular_optional_package_properties(Qt5TextToSpeech PROPERTIES
|
||||
find_package(Qt6TextToSpeech ${QT_REQUIRED_VERSION} CONFIG)
|
||||
set_okular_optional_package_properties(Qt6TextToSpeech PROPERTIES
|
||||
PURPOSE "Enables speech features.")
|
||||
if (Qt5TextToSpeech_FOUND)
|
||||
add_definitions(-DHAVE_SPEECH)
|
||||
if (Qt6TextToSpeech_FOUND)
|
||||
set(HAVE_SPEECH 1)
|
||||
else()
|
||||
set(HAVE_SPEECH 0)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (BUILD_MOBILE)
|
||||
find_package(KF5Kirigami2)
|
||||
set_package_properties(KF5Kirigami2 PROPERTIES
|
||||
find_package(Qt6 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Qml Quick)
|
||||
find_package(KF6Kirigami2)
|
||||
set_package_properties(KF6Kirigami2 PROPERTIES
|
||||
DESCRIPTION "A QtQuick based components set"
|
||||
PURPOSE "Required at runtime by the mobile app"
|
||||
TYPE RUNTIME
|
||||
)
|
||||
find_package(KF6KirigamiAddons)
|
||||
set_package_properties(KF6KirigamiAddons PROPERTIES
|
||||
DESCRIPTION "A set of widgets for Kirigami along with code to support them"
|
||||
PURPOSE "Required at runtime by the mobile app"
|
||||
TYPE RUNTIME
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT WIN32 AND NOT ANDROID AND NOT APPLE)
|
||||
find_package(KF5 ${KF5_REQUIRED_VERSION} REQUIRED COMPONENTS
|
||||
Activities
|
||||
)
|
||||
set_package_properties("KF5Activities" PROPERTIES
|
||||
find_package(Qt6Gui REQUIRED COMPONENTS Private)
|
||||
find_package(PlasmaActivities REQUIRED)
|
||||
set_package_properties("PlasmaActivities" PROPERTIES
|
||||
DESCRIPTION "Activities interface library"
|
||||
URL "https://api.kde.org/frameworks/kactivities/html/"
|
||||
PURPOSE "Required for Activities integration.")
|
||||
URL "https://invent.kde.org/plasma/plasma-activities"
|
||||
PURPOSE "Required for Activities integration."
|
||||
)
|
||||
set(HAVE_X11 TRUE)
|
||||
else()
|
||||
set(HAVE_X11 FALSE)
|
||||
endif()
|
||||
find_package(Phonon4Qt6 CONFIG)
|
||||
set_okular_optional_package_properties(Phonon4Qt6 PROPERTIES
|
||||
PURPOSE "Required for documents with audio or video elements")
|
||||
if (Phonon4Qt6_FOUND)
|
||||
set(HAVE_PHONON 1)
|
||||
else()
|
||||
set(HAVE_PHONON 0)
|
||||
endif()
|
||||
find_package(Phonon4Qt5 CONFIG REQUIRED)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/modules)
|
||||
|
||||
find_package(ZLIB REQUIRED)
|
||||
|
||||
find_package(Poppler "0.86.0" COMPONENTS Qt5)
|
||||
find_package(Poppler "22.02.0" COMPONENTS Qt6)
|
||||
set_okular_optional_package_properties(Poppler PROPERTIES
|
||||
PURPOSE "Support for PDF files in okular.")
|
||||
|
||||
|
@ -208,12 +233,6 @@ set_okular_optional_package_properties(TIFF PROPERTIES
|
|||
URL "http://www.libtiff.org"
|
||||
PURPOSE "Support for TIFF files in okular.")
|
||||
|
||||
find_package(JPEG)
|
||||
set_okular_optional_package_properties(JPEG PROPERTIES
|
||||
DESCRIPTION "A library for reading and writing JPEG image files."
|
||||
URL "https://www.ijg.org"
|
||||
PURPOSE "Support for PalmDB documents in okular.")
|
||||
|
||||
set(LIBSPECTRE_MINIMUM_VERSION "0.2")
|
||||
find_package(LibSpectre "${LIBSPECTRE_MINIMUM_VERSION}")
|
||||
set_okular_optional_package_properties(LibSpectre PROPERTIES
|
||||
|
@ -221,22 +240,20 @@ set_okular_optional_package_properties(LibSpectre PROPERTIES
|
|||
URL "https://libspectre.freedesktop.org"
|
||||
PURPOSE "Support for PS files in okular.")
|
||||
|
||||
find_package(KF5KExiv2 CONFIG)
|
||||
set_okular_optional_package_properties(KF5KExiv2 PROPERTIES
|
||||
find_package(KExiv2Qt6 CONFIG)
|
||||
set_okular_optional_package_properties(KExiv2Qt6 PROPERTIES
|
||||
DESCRIPTION "Wrapper around Exiv2 library"
|
||||
URL "https://commits.kde.org/libkexiv2"
|
||||
PURPOSE "Support for exif rotation in image files.")
|
||||
|
||||
find_package(CHM)
|
||||
set_okular_optional_package_properties(CHM PROPERTIES
|
||||
DESCRIPTION "A library for dealing with Microsoft ITSS/CHM format files"
|
||||
URL "http://www.jedrea.com/chmlib"
|
||||
PURPOSE "Support CHM files in okular.")
|
||||
if (FALSE ) # Investigate porting at some point
|
||||
find_package(CHM)
|
||||
set_okular_optional_package_properties(CHM PROPERTIES
|
||||
DESCRIPTION "A library for dealing with Microsoft ITSS/CHM format files"
|
||||
URL "http://www.jedrea.com/chmlib"
|
||||
PURPOSE "Support CHM files in okular.")
|
||||
|
||||
find_package(KF5KHtml CONFIG)
|
||||
set_okular_optional_package_properties(KF5KHtml PROPERTIES
|
||||
DESCRIPTION "HTML rendering library"
|
||||
PURPOSE "Support CHM files in okular.")
|
||||
endif()
|
||||
|
||||
find_package(LibZip)
|
||||
set_okular_optional_package_properties(LibZip PROPERTIES
|
||||
|
@ -244,7 +261,7 @@ set_okular_optional_package_properties(LibZip PROPERTIES
|
|||
URL "https://libzip.org/"
|
||||
PURPOSE "Support CHM files in okular.")
|
||||
|
||||
find_package(DjVuLibre "3.5.17")
|
||||
find_package(DjVuLibre "3.5.28")
|
||||
set_okular_optional_package_properties(DjVuLibre PROPERTIES
|
||||
DESCRIPTION "A library for dealing with DjVu formatted files"
|
||||
URL "https://djvulibre.djvuzone.org"
|
||||
|
@ -256,8 +273,8 @@ set_okular_optional_package_properties(EPub PROPERTIES
|
|||
URL "http://sourceforge.net/projects/ebook-tools"
|
||||
PURPOSE "Support for EPub documents in Okular.")
|
||||
|
||||
find_package(QMobipocket "2" CONFIG)
|
||||
set_okular_optional_package_properties(QMobipocket PROPERTIES
|
||||
find_package(QMobipocket6 "2" CONFIG)
|
||||
set_okular_optional_package_properties(QMobiPocket6 PROPERTIES
|
||||
DESCRIPTION "A library for reading Mobipocket documents"
|
||||
URL "https://commits.kde.org/kdegraphics-mobipocket"
|
||||
PURPOSE "Support for Mobipocket documents in Okular.")
|
||||
|
@ -268,23 +285,12 @@ set_okular_optional_package_properties(Discount PROPERTIES
|
|||
URL "https://www.pell.portland.or.us/~orc/Code/discount/"
|
||||
PURPOSE "Support for Markdown documents in Okular.")
|
||||
|
||||
add_definitions(-DQT_USE_QSTRINGBUILDER)
|
||||
add_definitions(-DTRANSLATION_DOMAIN="okular")
|
||||
add_definitions(-DQT_NO_URL_CAST_FROM_STRING)
|
||||
add_definitions(-DQT_NO_CAST_FROM_ASCII)
|
||||
add_definitions(-DQT_NO_CAST_FROM_BYTEARRAY)
|
||||
add_definitions(-DQT_NO_CAST_TO_ASCII)
|
||||
add_definitions(-DQT_DEPRECATED_WARNINGS_SINCE=0x050C00)
|
||||
add_definitions(-DKF_DEPRECATED_WARNINGS_SINCE=0x054400)
|
||||
add_definitions(-DQT_NO_KEYWORDS)
|
||||
add_definitions(-DQT_DEPRECATED_WARNINGS_SINCE=0x060600)
|
||||
add_definitions(-DKF_DEPRECATED_WARNINGS_SINCE=0x05F000)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${PHONON_INCLUDES} core/synctex ${CMAKE_BINARY_DIR}/core)
|
||||
|
||||
if(BUILD_MOBILE AND KF5Kirigami2_VERSION VERSION_LESS "5.85")
|
||||
message(FATAL_ERROR "Disable mobile build. This requires Kirigami 5.85 or greater.")
|
||||
set(BUILD_MOBILE OFF)
|
||||
endif()
|
||||
|
||||
option(BUILD_COVERAGE "Build the project with gcov support" OFF)
|
||||
|
||||
if(BUILD_COVERAGE)
|
||||
|
@ -307,7 +313,7 @@ if(BUILD_TESTING)
|
|||
add_subdirectory( autotests )
|
||||
endif()
|
||||
|
||||
if(KF5DocTools_FOUND)
|
||||
if(KF6DocTools_FOUND)
|
||||
add_subdirectory(doc)
|
||||
endif()
|
||||
|
||||
|
@ -359,7 +365,7 @@ set(okularcore_SRCS
|
|||
core/synctex/synctex_parser.c
|
||||
core/synctex/synctex_parser_utils.c
|
||||
)
|
||||
qt5_add_resources(okularcore_SRCS
|
||||
qt_add_resources(okularcore_SRCS
|
||||
core/script/builtin.qrc
|
||||
)
|
||||
|
||||
|
@ -411,6 +417,7 @@ kconfig_add_kcfg_files(okularcore_SRCS GENERATE_MOC conf/settings_core.kcfgc)
|
|||
|
||||
add_library(okularcore SHARED ${okularcore_SRCS})
|
||||
generate_export_header(okularcore BASE_NAME okularcore EXPORT_FILE_NAME "${CMAKE_CURRENT_BINARY_DIR}/core/okularcore_export.h")
|
||||
target_include_directories(okularcore PUBLIC "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR}>")
|
||||
|
||||
if (ANDROID)
|
||||
set(fileName ${CMAKE_BINARY_DIR}/Okular5Core-android-dependencies.xml)
|
||||
|
@ -435,55 +442,56 @@ target_link_libraries(okularcore
|
|||
PRIVATE
|
||||
${OKULAR_IOKIT}
|
||||
${SHLWAPI}
|
||||
KF5::Archive
|
||||
KF5::KIOCore
|
||||
KF5::KIOWidgets
|
||||
KF5::I18n
|
||||
KF5::ThreadWeaver
|
||||
KF5::Bookmarks
|
||||
Phonon::phonon4qt5
|
||||
Qt5::Svg
|
||||
KF6::Archive
|
||||
KF6::KIOCore
|
||||
KF6::KIOWidgets
|
||||
KF6::I18n
|
||||
KF6::ThreadWeaver
|
||||
KF6::BookmarksWidgets
|
||||
KF6::Bookmarks
|
||||
Qt6::Svg
|
||||
${MATH_LIB}
|
||||
ZLIB::ZLIB
|
||||
PUBLIC # these are included from the installed headers
|
||||
KF5::CoreAddons
|
||||
KF5::XmlGui
|
||||
KF5::ConfigGui
|
||||
Qt5::PrintSupport
|
||||
Qt5::Widgets
|
||||
Qt5::CorePrivate
|
||||
KF6::CoreAddons
|
||||
KF6::XmlGui
|
||||
KF6::ConfigGui
|
||||
Qt6::PrintSupport
|
||||
Qt6::Widgets
|
||||
)
|
||||
|
||||
|
||||
if (KF5Wallet_FOUND)
|
||||
target_link_libraries(okularcore PRIVATE KF5::Wallet)
|
||||
if (Phonon4Qt6_FOUND)
|
||||
target_link_libraries(okularcore PRIVATE Phonon::phonon4qt6)
|
||||
endif()
|
||||
if (KF5JS_FOUND)
|
||||
|
||||
|
||||
if (KF6Wallet_FOUND)
|
||||
target_link_libraries(okularcore PRIVATE KF6::Wallet)
|
||||
endif()
|
||||
if (TARGET Qt6::Qml)
|
||||
target_sources(okularcore PRIVATE
|
||||
core/script/executor_kjs.cpp
|
||||
core/script/kjs_app.cpp
|
||||
core/script/kjs_console.cpp
|
||||
core/script/kjs_data.cpp
|
||||
core/script/kjs_display.cpp
|
||||
core/script/kjs_document.cpp
|
||||
core/script/kjs_field.cpp
|
||||
core/script/kjs_fullscreen.cpp
|
||||
core/script/kjs_field.cpp
|
||||
core/script/kjs_spell.cpp
|
||||
core/script/kjs_util.cpp
|
||||
core/script/kjs_event.cpp
|
||||
core/script/kjs_ocg.cpp
|
||||
core/script/executor_js.cpp
|
||||
core/script/js_app.cpp
|
||||
core/script/js_console.cpp
|
||||
core/script/js_data.cpp
|
||||
core/script/js_display.cpp
|
||||
core/script/js_document.cpp
|
||||
core/script/js_field.cpp
|
||||
core/script/js_fullscreen.cpp
|
||||
core/script/js_field.cpp
|
||||
core/script/js_spell.cpp
|
||||
core/script/js_util.cpp
|
||||
core/script/js_event.cpp
|
||||
core/script/js_ocg.cpp
|
||||
)
|
||||
target_link_libraries(okularcore PRIVATE KF5::JS KF5::JSApi)
|
||||
target_link_libraries(okularcore PRIVATE Qt6::Qml)
|
||||
endif()
|
||||
|
||||
set_target_properties(okularcore PROPERTIES VERSION 10.0.0 SOVERSION 10 OUTPUT_NAME Okular5Core EXPORT_NAME Core)
|
||||
set_target_properties(okularcore PROPERTIES VERSION 1.0.0 SOVERSION 1 OUTPUT_NAME Okular6Core EXPORT_NAME Core)
|
||||
|
||||
install(TARGETS okularcore EXPORT Okular5Targets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
install(TARGETS okularcore EXPORT Okular6Targets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
|
||||
|
||||
install(FILES conf/okular.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR})
|
||||
install(FILES conf/okular_core.kcfg DESTINATION ${KDE_INSTALL_KCFGDIR})
|
||||
install(FILES core/okularGenerator.desktop DESTINATION ${KDE_INSTALL_KSERVICETYPES5DIR})
|
||||
|
||||
if(BUILD_DESKTOP)
|
||||
# okularpart
|
||||
|
@ -509,7 +517,6 @@ if(BUILD_DESKTOP)
|
|||
part/widgetconfigurationtoolsbase.cpp
|
||||
part/widgetdrawingtools.cpp
|
||||
part/part.cpp
|
||||
part/xmlgui_helper.cpp
|
||||
part/extensions.cpp
|
||||
part/embeddedfilesdialog.cpp
|
||||
part/actionbar.cpp
|
||||
|
@ -557,9 +564,12 @@ if(BUILD_DESKTOP)
|
|||
part/signaturepartutils.cpp
|
||||
part/signaturepropertiesdialog.cpp
|
||||
part/signaturepanel.cpp
|
||||
)
|
||||
|
||||
if (Qt5TextToSpeech_FOUND)
|
||||
part/part.qrc
|
||||
)
|
||||
ki18n_wrap_ui(okularpart_SRCS part/selectcertificatedialog.ui)
|
||||
|
||||
if (Qt6TextToSpeech_FOUND)
|
||||
set(okularpart_SRCS ${okularpart_SRCS}
|
||||
part/tts.cpp)
|
||||
endif()
|
||||
|
@ -571,75 +581,74 @@ generate_export_header(okularpart BASE_NAME okularpart)
|
|||
|
||||
target_link_libraries(okularpart okularcore
|
||||
${MATH_LIB}
|
||||
Qt5::Svg
|
||||
Phonon::phonon4qt5
|
||||
KF5::Archive
|
||||
KF5::Bookmarks
|
||||
KF5::I18n
|
||||
KF5::IconThemes
|
||||
KF5::ItemViews
|
||||
KF5::KIOCore
|
||||
KF5::KIOFileWidgets
|
||||
KF5::KIOWidgets
|
||||
KF5::Parts
|
||||
KF5::Solid
|
||||
KF5::WindowSystem
|
||||
KF5::TextWidgets
|
||||
Qt6::Svg
|
||||
KF6::Archive
|
||||
KF6::Bookmarks
|
||||
KF6::I18n
|
||||
KF6::IconThemes
|
||||
KF6::ItemViews
|
||||
KF6::KIOCore
|
||||
KF6::KIOWidgets
|
||||
KF6::Parts
|
||||
KF6::WindowSystem
|
||||
KF6::TextWidgets
|
||||
)
|
||||
|
||||
if(KF5Wallet_FOUND)
|
||||
target_link_libraries(okularpart KF5::Wallet)
|
||||
if (TARGET Qt6::DBus)
|
||||
target_link_libraries(okularpart Qt6::DBus)
|
||||
endif()
|
||||
if (Phonon4Qt6_FOUND)
|
||||
target_link_libraries(okularpart Phonon::phonon4qt6)
|
||||
endif()
|
||||
|
||||
if (KF5Purpose_FOUND)
|
||||
target_link_libraries(okularpart KF5::PurposeWidgets)
|
||||
if(KF6Wallet_FOUND)
|
||||
target_link_libraries(okularpart KF6::Wallet)
|
||||
endif()
|
||||
|
||||
if (KF6Purpose_FOUND)
|
||||
target_link_libraries(okularpart KF6::PurposeWidgets)
|
||||
endif()
|
||||
|
||||
set_target_properties(okularpart PROPERTIES PREFIX "")
|
||||
set_target_properties(okularpart PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/kf6/parts)
|
||||
|
||||
if (Qt5TextToSpeech_FOUND)
|
||||
target_link_libraries(okularpart Qt5::TextToSpeech)
|
||||
endif()
|
||||
install(TARGETS okularpart DESTINATION ${KDE_INSTALL_PLUGINDIR})
|
||||
if (Qt6TextToSpeech_FOUND)
|
||||
target_link_libraries(okularpart Qt6::TextToSpeech)
|
||||
endif()
|
||||
|
||||
#instead install the part to this path so it can be found
|
||||
install(TARGETS okularpart DESTINATION ${KDE_INSTALL_PLUGINDIR}/kf6/parts/ )
|
||||
|
||||
endif()# End of BUILD_DESKTOP if
|
||||
|
||||
|
||||
########### install files ###############
|
||||
|
||||
install(FILES okular.upd DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR})
|
||||
|
||||
install( FILES okular_part.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} )
|
||||
install( FILES part/part.rc part/part-viewermode.rc DESTINATION ${KDE_INSTALL_KXMLGUI5DIR}/okular )
|
||||
|
||||
if (${ECM_VERSION} STRGREATER "5.58.0")
|
||||
install(FILES okular.categories DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR})
|
||||
else()
|
||||
install(FILES okular.categories DESTINATION ${KDE_INSTALL_CONFDIR})
|
||||
endif()
|
||||
install(FILES okular.categories DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR})
|
||||
|
||||
ki18n_install(po)
|
||||
if(KF5DocTools_FOUND)
|
||||
if(KF6DocTools_FOUND)
|
||||
kdoctools_install(po)
|
||||
endif()
|
||||
|
||||
########### cmake files #################
|
||||
|
||||
set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/Okular5")
|
||||
set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/Okular6")
|
||||
configure_package_config_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Okular5Config.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Okular5Config.cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Okular6Config.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Okular6Config.cmake"
|
||||
INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
|
||||
PATH_VARS INCLUDE_INSTALL_DIR CMAKE_INSTALL_PREFIX
|
||||
PATH_VARS KDE_INSTALL_INCLUDEDIR CMAKE_INSTALL_PREFIX
|
||||
)
|
||||
|
||||
install(FILES
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Okular5Config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Okular5ConfigVersion.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Okular6Config.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/Okular6ConfigVersion.cmake"
|
||||
DESTINATION "${CMAKECONFIG_INSTALL_DIR}"
|
||||
COMPONENT Devel
|
||||
)
|
||||
|
||||
install(EXPORT Okular5Targets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE Okular5Targets.cmake NAMESPACE Okular::)
|
||||
install(EXPORT Okular6Targets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE Okular6Targets.cmake NAMESPACE Okular::)
|
||||
|
||||
install(FILES
|
||||
core/stamps.svg
|
||||
|
|
|
@ -411,13 +411,13 @@ add_definitions(-DTRANSLATION_DOMAIN="okular_magic")
|
|||
|
||||
macro_optional_find_package(Okular)
|
||||
|
||||
include_directories( ${OKULAR_INCLUDE_DIR} ${KF5_INCLUDE_DIR} ${QT_INCLUDES} )
|
||||
include_directories( ${OKULAR_INCLUDE_DIR} ${KF6_INCLUDE_DIR} ${QT_INCLUDES} )
|
||||
|
||||
########### next target ###############
|
||||
|
||||
set( okularGenerator_magic_PART_SRCS generator_magic.cpp )
|
||||
|
||||
target_link_libraries( okularGenerator_magic PRIVATE okularcore KF5::I18n KF5::KIOCore )
|
||||
target_link_libraries( okularGenerator_magic PRIVATE okularcore KF6::I18n KF6::KIOCore )
|
||||
|
||||
install( TARGETS okularGenerator_magic DESTINATION ${PLUGIN_INSTALL_DIR} )
|
||||
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
find_dependency(Qt5Core @QT_REQUIRED_VERSION@)
|
||||
find_dependency(Qt5PrintSupport @QT_REQUIRED_VERSION@)
|
||||
find_dependency(Qt5Widgets @QT_REQUIRED_VERSION@)
|
||||
find_dependency(KF5CoreAddons @KF5_REQUIRED_VERSION@)
|
||||
find_dependency(KF5Config @KF5_REQUIRED_VERSION@)
|
||||
find_dependency(KF5XmlGui @KF5_REQUIRED_VERSION@)
|
||||
|
||||
@PACKAGE_SETUP_AUTOMOC_VARIABLES@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/Okular5Targets.cmake")
|
14
Okular6Config.cmake.in
Normal file
14
Okular6Config.cmake.in
Normal file
|
@ -0,0 +1,14 @@
|
|||
@PACKAGE_INIT@
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
|
||||
find_dependency(Qt6Core @QT_REQUIRED_VERSION@)
|
||||
find_dependency(Qt6PrintSupport @QT_REQUIRED_VERSION@)
|
||||
find_dependency(Qt6Widgets @QT_REQUIRED_VERSION@)
|
||||
find_dependency(KF6CoreAddons @KF6_REQUIRED_VERSION@)
|
||||
find_dependency(KF6Config @KF6_REQUIRED_VERSION@)
|
||||
find_dependency(KF6XmlGui @KF6_REQUIRED_VERSION@)
|
||||
|
||||
@PACKAGE_SETUP_AUTOMOC_VARIABLES@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/Okular6Targets.cmake")
|
|
@ -9,12 +9,12 @@ macro(add_conf_unittest _source)
|
|||
add_test( NAME ${_name} COMMAND ${_name} )
|
||||
ecm_mark_as_test(${_name})
|
||||
target_link_libraries( ${_name}
|
||||
Qt5::Test
|
||||
Qt5::Widgets
|
||||
Qt5::Xml
|
||||
KF5::I18n
|
||||
KF5::Completion
|
||||
KF5::WidgetsAddons
|
||||
Qt6::Test
|
||||
Qt6::Widgets
|
||||
Qt6::Xml
|
||||
KF6::I18n
|
||||
KF6::Completion
|
||||
KF6::WidgetsAddons
|
||||
)
|
||||
endmacro ()
|
||||
|
||||
|
@ -22,117 +22,134 @@ add_conf_unittest(editdrawingtooldialogtest.cpp)
|
|||
|
||||
ecm_add_test(shelltest.cpp ../shell/shellutils.cpp
|
||||
TEST_NAME "shelltest"
|
||||
LINK_LIBRARIES Qt5::Test okularcore
|
||||
LINK_LIBRARIES Qt6::Test okularcore
|
||||
)
|
||||
|
||||
if(Poppler_Qt5_FOUND)
|
||||
if(Poppler_Qt6_FOUND)
|
||||
if (BUILD_DESKTOP)
|
||||
ecm_add_test(parttest.cpp closedialoghelper.cpp
|
||||
TEST_NAME "parttest"
|
||||
LINK_LIBRARIES Qt5::Widgets Qt5::Test Qt5::Xml okularcore okularpart
|
||||
LINK_LIBRARIES Qt6::Widgets Qt6::Test Qt6::Xml okularcore okularpart
|
||||
)
|
||||
endif()
|
||||
|
||||
ecm_add_test(visibilitytest.cpp
|
||||
TEST_NAME "visibilitytest"
|
||||
LINK_LIBRARIES Qt5::Widgets Qt5::Test okularcore
|
||||
LINK_LIBRARIES Qt6::Widgets Qt6::Test okularcore
|
||||
)
|
||||
|
||||
ecm_add_test(kjsfunctionstest.cpp
|
||||
TEST_NAME "kjsfunctionstest"
|
||||
LINK_LIBRARIES Qt5::Widgets Qt5::Test okularcore
|
||||
ecm_add_test(jsfunctionstest.cpp
|
||||
TEST_NAME "jsfunctionstest"
|
||||
LINK_LIBRARIES Qt6::Widgets Qt6::Test okularcore
|
||||
)
|
||||
|
||||
ecm_add_test(formattest.cpp
|
||||
TEST_NAME "formattest"
|
||||
LINK_LIBRARIES Qt5::Widgets Qt5::Test okularcore
|
||||
LINK_LIBRARIES Qt6::Widgets Qt6::Test okularcore
|
||||
)
|
||||
|
||||
ecm_add_test(keystroketest.cpp
|
||||
TEST_NAME "keystroketest"
|
||||
LINK_LIBRARIES Qt5::Widgets Qt5::Test okularcore
|
||||
LINK_LIBRARIES Qt6::Widgets Qt6::Test okularcore
|
||||
)
|
||||
|
||||
ecm_add_test(signunsignedfieldtest.cpp
|
||||
TEST_NAME "signunsignedfieldtest"
|
||||
LINK_LIBRARIES Qt5::Widgets Qt5::Test okularcore
|
||||
LINK_LIBRARIES Qt6::Widgets Qt6::Test okularcore
|
||||
)
|
||||
endif()
|
||||
|
||||
ecm_add_test(suggestedfilenametest.cpp
|
||||
TEST_NAME "suggestedfilenametest"
|
||||
LINK_LIBRARIES Qt6::Test okularcore KF6::I18n
|
||||
)
|
||||
|
||||
ecm_add_test(documenttest.cpp
|
||||
TEST_NAME "documenttest"
|
||||
LINK_LIBRARIES Qt5::Widgets Qt5::Test Qt5::Xml okularcore KF5::ThreadWeaver
|
||||
LINK_LIBRARIES Qt6::Widgets Qt6::Test Qt6::Xml okularcore KF6::ThreadWeaver
|
||||
)
|
||||
|
||||
ecm_add_test(searchtest.cpp
|
||||
TEST_NAME "searchtest"
|
||||
LINK_LIBRARIES Qt5::Widgets Qt5::Test Qt5::Xml okularcore
|
||||
LINK_LIBRARIES Qt6::Widgets Qt6::Test Qt6::Xml okularcore
|
||||
)
|
||||
|
||||
ecm_add_test(annotationstest.cpp
|
||||
TEST_NAME "annotationstest"
|
||||
LINK_LIBRARIES Qt5::Widgets Qt5::Test Qt5::Xml okularcore
|
||||
LINK_LIBRARIES Qt6::Widgets Qt6::Test Qt6::Xml okularcore
|
||||
)
|
||||
|
||||
ecm_add_test(urldetecttest.cpp
|
||||
TEST_NAME "urldetecttest"
|
||||
LINK_LIBRARIES Qt5::Widgets Qt5::Test Qt5::Xml KF5::CoreAddons
|
||||
LINK_LIBRARIES Qt6::Widgets Qt6::Test Qt6::Xml KF6::CoreAddons
|
||||
)
|
||||
|
||||
ecm_add_test(editannotationcontentstest.cpp testingutils.cpp
|
||||
TEST_NAME "editannotationcontentstest"
|
||||
LINK_LIBRARIES Qt5::Widgets Qt5::Test Qt5::Xml okularcore
|
||||
LINK_LIBRARIES Qt6::Widgets Qt6::Test Qt6::Xml okularcore
|
||||
)
|
||||
|
||||
ecm_add_test(addremoveannotationtest.cpp testingutils.cpp
|
||||
TEST_NAME "addremoveannotationtest"
|
||||
LINK_LIBRARIES Qt5::Widgets Qt5::Test Qt5::Xml okularcore
|
||||
LINK_LIBRARIES Qt6::Widgets Qt6::Test Qt6::Xml okularcore
|
||||
)
|
||||
|
||||
ecm_add_test(translateannotationtest.cpp testingutils.cpp
|
||||
TEST_NAME "translateannotationtest"
|
||||
LINK_LIBRARIES Qt5::Widgets Qt5::Test Qt5::Xml okularcore
|
||||
LINK_LIBRARIES Qt6::Widgets Qt6::Test Qt6::Xml okularcore
|
||||
)
|
||||
|
||||
ecm_add_test(modifyannotationpropertiestest.cpp testingutils.cpp
|
||||
TEST_NAME "modifyannotationpropertiestest"
|
||||
LINK_LIBRARIES Qt5::Widgets Qt5::Test okularcore
|
||||
LINK_LIBRARIES Qt6::Widgets Qt6::Test okularcore
|
||||
)
|
||||
|
||||
ecm_add_test(editformstest.cpp
|
||||
TEST_NAME "editformstest"
|
||||
LINK_LIBRARIES Qt5::Widgets Qt5::Test okularcore
|
||||
LINK_LIBRARIES Qt6::Widgets Qt6::Test okularcore
|
||||
)
|
||||
|
||||
ecm_add_test(calculatetexttest.cpp
|
||||
TEST_NAME "calculatetexttest"
|
||||
LINK_LIBRARIES Qt5::Widgets Qt5::Test okularcore
|
||||
LINK_LIBRARIES Qt6::Widgets Qt6::Test okularcore
|
||||
)
|
||||
|
||||
if(KF5Activities_FOUND AND BUILD_DESKTOP)
|
||||
ecm_add_test(mainshelltest.cpp ../shell/okular_main.cpp ../shell/shellutils.cpp ../shell/shell.cpp ../shell/welcomescreen.cpp ../shell/recentitemsmodel.cpp closedialoghelper.cpp
|
||||
TEST_NAME "mainshelltest"
|
||||
LINK_LIBRARIES Qt5::Test KF5::Activities okularpart okularcore
|
||||
)
|
||||
target_compile_definitions(mainshelltest PRIVATE OKULAR_BINARY="$<TARGET_FILE:okular>")
|
||||
ecm_add_test(check_distinguished_name_parser.cpp
|
||||
TEST_NAME "distinguishednameparser"
|
||||
LINK_LIBRARIES Qt6::Test)
|
||||
|
||||
if(PlasmaActivities_FOUND AND BUILD_DESKTOP)
|
||||
ecm_add_test(mainshelltest.cpp ../shell/okular_main.cpp ../shell/shellutils.cpp ../shell/shell.cpp ../shell/welcomescreen.cpp ../shell/recentitemsmodel.cpp closedialoghelper.cpp
|
||||
TEST_NAME "mainshelltest"
|
||||
LINK_LIBRARIES Qt6::Test Plasma::Activities okularpart okularcore
|
||||
)
|
||||
target_compile_definitions(mainshelltest PRIVATE OKULAR_BINARY="$<TARGET_FILE:okular>")
|
||||
|
||||
if (HAVE_X11)
|
||||
target_link_libraries(mainshelltest Qt6::GuiPrivate)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(BUILD_DESKTOP)
|
||||
ecm_add_test(annotationtoolbartest.cpp ../shell/okular_main.cpp ../shell/shellutils.cpp ../shell/shell.cpp ../shell/welcomescreen.cpp ../shell/recentitemsmodel.cpp closedialoghelper.cpp ../shell/welcomescreen.ui
|
||||
TEST_NAME "annotationtoolbartest"
|
||||
LINK_LIBRARIES Qt5::Test okularpart
|
||||
LINK_LIBRARIES Qt6::Test okularpart
|
||||
)
|
||||
|
||||
if (HAVE_X11)
|
||||
target_link_libraries(annotationtoolbartest Qt6::GuiPrivate)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
ecm_add_test(generatorstest.cpp
|
||||
TEST_NAME "generatorstest"
|
||||
LINK_LIBRARIES Qt5::Test KF5::CoreAddons okularcore
|
||||
LINK_LIBRARIES Qt6::Test KF6::CoreAddons okularcore
|
||||
)
|
||||
target_compile_definitions(generatorstest PRIVATE GENERATORS_BUILD_DIR="${CMAKE_BINARY_DIR}/generators")
|
||||
|
||||
ecm_add_test(signatureformtest.cpp
|
||||
TEST_NAME "signatureformtest"
|
||||
LINK_LIBRARIES Qt5::Test okularcore
|
||||
LINK_LIBRARIES Qt6::Test okularcore
|
||||
)
|
||||
|
||||
find_package(Discount)
|
||||
|
@ -140,11 +157,11 @@ find_package(Discount)
|
|||
if(Discount_FOUND)
|
||||
ecm_add_test(markdowntest.cpp ../generators/markdown/converter.cpp
|
||||
TEST_NAME "markdowntest"
|
||||
LINK_LIBRARIES Qt5::Test okularcore KF5::I18n PkgConfig::Discount
|
||||
LINK_LIBRARIES Qt6::Test okularcore KF6::I18n PkgConfig::Discount
|
||||
)
|
||||
endif()
|
||||
|
||||
ecm_add_test(toggleactionmenutest.cpp ../part/toggleactionmenu.cpp
|
||||
TEST_NAME "toggleactionmenutest"
|
||||
LINK_LIBRARIES Qt5::Test KF5::WidgetsAddons
|
||||
LINK_LIBRARIES Qt6::Test KF6::WidgetsAddons
|
||||
)
|
||||
|
|
|
@ -94,11 +94,11 @@ void AnnotationTest::testDistance_data()
|
|||
square->setGeometricalInnerColor(QColor(0, 0, 0));
|
||||
}
|
||||
m_document->addPageAnnotation(0, square);
|
||||
QTest::newRow("Square: Base point 1") << (Okular::Annotation *)square << 0.1 << 0.1 << 0;
|
||||
QTest::newRow("Square: On edge 1") << (Okular::Annotation *)square << 0.1 << 0.2 << 0;
|
||||
QTest::newRow("Square: On edge 2") << (Okular::Annotation *)square << 0.2 << 0.1 << 0;
|
||||
QTest::newRow("Square: Inside") << (Okular::Annotation *)square << 0.2 << 0.2 << ((i == 0) ? qRound(pow(0.1 * documentX, 2) - 1 /* stroke width */) : 0);
|
||||
QTest::newRow("Square: Outside") << (Okular::Annotation *)square << 0.0 << 0.0 << qRound(pow(0.1 * documentX, 2) + pow(0.1 * documentY, 2));
|
||||
QTest::addRow("Square: Base point 1 %d", i) << (Okular::Annotation *)square << 0.1 << 0.1 << 0;
|
||||
QTest::addRow("Square: On edge 1 %d", i) << (Okular::Annotation *)square << 0.1 << 0.2 << 0;
|
||||
QTest::addRow("Square: On edge 2 %d", i) << (Okular::Annotation *)square << 0.2 << 0.1 << 0;
|
||||
QTest::addRow("Square: Inside %d", i) << (Okular::Annotation *)square << 0.2 << 0.2 << ((i == 0) ? qRound(pow(0.1 * documentX, 2) - 1 /* stroke width */) : 0);
|
||||
QTest::addRow("Square: Outside %d", i) << (Okular::Annotation *)square << 0.0 << 0.0 << qRound(pow(0.1 * documentX, 2) + pow(0.1 * documentY, 2));
|
||||
}
|
||||
|
||||
// ellipsis
|
||||
|
@ -110,9 +110,9 @@ void AnnotationTest::testDistance_data()
|
|||
ellipse->setGeometricalInnerColor(QColor(0, 0, 0));
|
||||
}
|
||||
m_document->addPageAnnotation(0, ellipse);
|
||||
QTest::newRow("Ellipse: Base point 1") << (Okular::Annotation *)ellipse << 0.1 << 0.3 << 0;
|
||||
QTest::newRow("Ellipse: Inside") << (Okular::Annotation *)ellipse << 0.2 << 0.3 << qRound((i == 0) ? pow(documentX * 0.1, 2) - 1 /* pen */ : 0);
|
||||
QTest::newRow("Ellipse: Outside") << (Okular::Annotation *)ellipse << 0.0 << 0.3 << qRound(pow(documentX * 0.1, 2));
|
||||
QTest::addRow("Ellipse: Base point 1 %d", i) << (Okular::Annotation *)ellipse << 0.1 << 0.3 << 0;
|
||||
QTest::addRow("Ellipse: Inside %d", i) << (Okular::Annotation *)ellipse << 0.2 << 0.3 << qRound((i == 0) ? pow(documentX * 0.1, 2) - 1 /* pen */ : 0);
|
||||
QTest::addRow("Ellipse: Outside %d", i) << (Okular::Annotation *)ellipse << 0.0 << 0.3 << qRound(pow(documentX * 0.1, 2));
|
||||
}
|
||||
|
||||
// highlight
|
||||
|
|
|
@ -90,8 +90,8 @@ void AnnotationToolBarTest::initMain()
|
|||
QByteArray homePath = QFile::encodeName(homeDir.path());
|
||||
qputenv("USERPROFILE", homePath);
|
||||
qputenv("HOME", homePath);
|
||||
qputenv("XDG_DATA_HOME", homePath + "/.local");
|
||||
qputenv("XDG_CONFIG_HOME", homePath + "/.kde-unit-test/xdg/config");
|
||||
qputenv("XDG_DATA_HOME", QByteArray(homePath + "/.local"));
|
||||
qputenv("XDG_CONFIG_HOME", QByteArray(homePath + "/.kde-unit-test/xdg/config"));
|
||||
}
|
||||
|
||||
void AnnotationToolBarTest::initTestCase()
|
||||
|
|
166
autotests/check_distinguished_name_parser.cpp
Normal file
166
autotests/check_distinguished_name_parser.cpp
Normal file
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2023 g10 Code GmbH
|
||||
SPDX-FileContributor: Sune Stolborg Vuorela <sune@vuorela.dk>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
Copied from poppler (pdf library)
|
||||
*/
|
||||
#include "../part/DistinguishedNameParser.h"
|
||||
|
||||
#include <QTest>
|
||||
|
||||
class TestDistinguishedNameParser : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit TestDistinguishedNameParser(QObject *parent = nullptr)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
private Q_SLOTS:
|
||||
// The big set of input/output. Several of the helper functions can be tested independently
|
||||
void testParser();
|
||||
void testParser_data();
|
||||
|
||||
void testRemoveLeadingSpaces();
|
||||
void testRemoveLeadingSpaces_data();
|
||||
|
||||
void testRemoveTrailingSpaces();
|
||||
void testRemoveTrailingSpaces_data();
|
||||
|
||||
void testParseHexString();
|
||||
void testParseHexString_data();
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(DN::Result);
|
||||
Q_DECLARE_METATYPE(std::string);
|
||||
Q_DECLARE_METATYPE(std::optional<std::string>);
|
||||
|
||||
void TestDistinguishedNameParser::testParser()
|
||||
{
|
||||
QFETCH(std::string, inputData);
|
||||
QFETCH(DN::Result, expectedResult);
|
||||
|
||||
auto result = DN::parseString(inputData);
|
||||
QCOMPARE(result, expectedResult);
|
||||
}
|
||||
|
||||
void TestDistinguishedNameParser::testParser_data()
|
||||
{
|
||||
QTest::addColumn<std::string>("inputData");
|
||||
QTest::addColumn<DN::Result>("expectedResult");
|
||||
|
||||
QTest::newRow("empty") << std::string {} << DN::Result {};
|
||||
QTest::newRow("CN=Simple") << std::string {"CN=Simple"} << DN::Result {{"CN", "Simple"}};
|
||||
QTest::newRow("CN=Name with spaces") << std::string {"CN=Name with spaces"} << DN::Result {{"CN", "Name with spaces"}};
|
||||
QTest::newRow("CN=Simple,O=Silly") << std::string {"CN=Simple,O=Silly"} << DN::Result {{"CN", "Simple"}, {"O", "Silly"}};
|
||||
QTest::newRow("CN=Steve Kille,O=Isode Limited,C=GB") << std::string {"CN=Steve Kille,O=Isode Limited,C=GB"} << DN::Result {{"CN", "Steve Kille"}, {"O", "Isode Limited"}, {"C", "GB"}};
|
||||
QTest::newRow("CN=some.user@example.com, O=MyCompany, L=San Diego,ST=California, C=US")
|
||||
<< std::string {"CN=some.user@example.com, O=MyCompany, L=San Diego,ST=California, C=US"} << DN::Result {{"CN", "some.user@example.com"}, {"O", "MyCompany"}, {"L", "San Diego"}, {"ST", "California"}, {"C", "US"}};
|
||||
QTest::newRow("Multi valued") << std::string {"OU=Sales+CN=J. Smith,O=Widget Inc.,C=US"}
|
||||
<< DN::Result {{"OU", "Sales"}, {"CN", "J. Smith"}, {"O", "Widget Inc."}, {"C", "US"}}; // This is technically wrong, but probably good enough for now
|
||||
QTest::newRow("Escaping comma") << std::string {"CN=L. Eagle,O=Sue\\, Grabbit and Runn,C=GB"} << DN::Result {{"CN", "L. Eagle"}, {"O", "Sue, Grabbit and Runn"}, {"C", "GB"}};
|
||||
QTest::newRow("Escaped trailing space") << std::string {"CN=Trailing space\\ "} << DN::Result {{"CN", "Trailing space "}};
|
||||
QTest::newRow("Escaped quote") << std::string {"CN=Quotation \\\" Mark"} << DN::Result {{"CN", "Quotation \" Mark"}};
|
||||
|
||||
QTest::newRow("CN=Simple with escaping") << std::string {"CN=S\\69mpl\\65\\7A"} << DN::Result {{"CN", "Simplez"}};
|
||||
QTest::newRow("SN=Lu\\C4\\8Di\\C4\\87") << std::string {"SN=Lu\\C4\\8Di\\C4\\87"} << DN::Result {{"SN", "Lučić"}};
|
||||
QTest::newRow("CN=\"Quoted name\"") << std::string {"CN=\"Quoted name\""} << DN::Result {{"CN", "Quoted name"}};
|
||||
QTest::newRow("CN=\" Leading and trailing spacees \"") << std::string {"CN=\" Leading and trailing spaces \""} << DN::Result {{"CN", " Leading and trailing spaces "}};
|
||||
QTest::newRow("Comma in quotes") << std::string {"CN=\"Comma, inside\""} << DN::Result {{"CN", "Comma, inside"}};
|
||||
QTest::newRow("forbidden chars in quotes") << std::string {"CN=\"Forbidden !@#$%&*()<>[]{},.?/\\| chars\""} << DN::Result {{"CN", "Forbidden !@#$%&*()<>[]{},.?/\\| chars"}};
|
||||
QTest::newRow("Quoted quotation") << std::string {"CN=\"Quotation \\\" Mark\""} << DN::Result {{"CN", "Quotation \" Mark"}};
|
||||
QTest::newRow("Quoted quotation") << std::string {"CN=\"Quotation \\\" Mark\\\" Multiples\""} << DN::Result {{"CN", "Quotation \" Mark\" Multiples"}};
|
||||
|
||||
QTest::newRow("frompdf1") << std::string {"2.5.4.97=#5553742D49644E722E20444520313233343735323233,CN=TeleSec PKS eIDAS QES CA 5,O=Deutsche Telekom AG,C=DE"}
|
||||
<< DN::Result {{"2.5.4.97", "USt-IdNr. DE 123475223"}, {"CN", "TeleSec PKS eIDAS QES CA 5"}, {"O", "Deutsche Telekom AG"}, {"C", "DE"}};
|
||||
QTest::newRow("frompdf2") << std::string {"2.5.4.5=#34,CN=Koch\\, Werner,2.5.4.42=#5765726E6572,2.5.4.4=#4B6F6368,C=DE"} << DN::Result {{"SerialNumber", "4"}, {"CN", "Koch, Werner"}, {"GN", "Werner"}, {"SN", "Koch"}, {"C", "DE"}};
|
||||
QTest::newRow("frompdf2a") << std::string {"2.5.4.5=#34,CN=Koch\\, Werner,oid.2.5.4.42=#5765726E6572,OID.2.5.4.4=#4B6F6368,C=DE"}
|
||||
<< DN::Result {{"SerialNumber", "4"}, {"CN", "Koch, Werner"}, {"GN", "Werner"}, {"SN", "Koch"}, {"C", "DE"}};
|
||||
|
||||
// weird spacing
|
||||
QTest::newRow("CN =Simple") << std::string {"CN =Simple"} << DN::Result {{"CN", "Simple"}};
|
||||
QTest::newRow("CN= Simple") << std::string {"CN= Simple"} << DN::Result {{"CN", "Simple"}};
|
||||
QTest::newRow("CN=Simple ") << std::string {"CN=Simple "} << DN::Result {{"CN", "Simple"}};
|
||||
QTest::newRow("CN=Simple,") << std::string {"CN=Simple,"} << DN::Result {{"CN", "Simple"}};
|
||||
QTest::newRow("CN=Simple, O=Silly") << std::string {"CN=Simple, O=Silly"} << DN::Result {{"CN", "Simple"}, {"O", "Silly"}};
|
||||
|
||||
// various malformed
|
||||
QTest::newRow("CN=Simple\\") << std::string {"CN=Simple\\"} << DN::Result {};
|
||||
QTest::newRow("CN=") << std::string {"CN="} << DN::Result {};
|
||||
QTest::newRow("CN=Simple\\X") << std::string {"CN=Simple\\X"} << DN::Result {};
|
||||
QTest::newRow("CN=Simple, O") << std::string {"CN=Simple, O"} << DN::Result {};
|
||||
QTest::newRow("CN=Sim\"ple") << std::string {"CN=Sim\"ple, O"} << DN::Result {};
|
||||
QTest::newRow("CN=Simple\\a") << std::string {"CN=Simple\\a"} << DN::Result {};
|
||||
QTest::newRow("=Simple") << std::string {"=Simple"} << DN::Result {};
|
||||
QTest::newRow("CN=\"Simple") << std::string {"CN=\"Simple"} << DN::Result {};
|
||||
QTest::newRow("CN=\"Simple") << std::string {"CN=\"Simple\\"} << DN::Result {};
|
||||
QTest::newRow("unquoted quotation in quotation") << std::string {"CN=\"Quotation \" Mark\""} << DN::Result {};
|
||||
}
|
||||
|
||||
void TestDistinguishedNameParser::testRemoveLeadingSpaces()
|
||||
{
|
||||
QFETCH(std::string, input);
|
||||
QFETCH(std::string, expectedOutput);
|
||||
|
||||
auto result = DN::detail::removeLeadingSpaces(input);
|
||||
QCOMPARE(result, expectedOutput);
|
||||
}
|
||||
void TestDistinguishedNameParser::testRemoveLeadingSpaces_data()
|
||||
{
|
||||
QTest::addColumn<std::string>("input");
|
||||
QTest::addColumn<std::string>("expectedOutput");
|
||||
|
||||
QTest::newRow("Empty") << std::string {} << std::string {};
|
||||
QTest::newRow("No leading spaces") << std::string {"horse"} << std::string {"horse"};
|
||||
QTest::newRow("Some spaces") << std::string {" horse"} << std::string {"horse"};
|
||||
QTest::newRow("Some leading and trailing") << std::string {" horse "} << std::string {"horse "};
|
||||
}
|
||||
|
||||
void TestDistinguishedNameParser::testRemoveTrailingSpaces()
|
||||
{
|
||||
QFETCH(std::string, input);
|
||||
QFETCH(std::string, expectedOutput);
|
||||
|
||||
auto result = DN::detail::removeTrailingSpaces(input);
|
||||
QCOMPARE(result, expectedOutput);
|
||||
}
|
||||
void TestDistinguishedNameParser::testRemoveTrailingSpaces_data()
|
||||
{
|
||||
QTest::addColumn<std::string>("input");
|
||||
QTest::addColumn<std::string>("expectedOutput");
|
||||
|
||||
QTest::newRow("Empty") << std::string {} << std::string {};
|
||||
QTest::newRow("No leading spaces") << std::string {"horse"} << std::string {"horse"};
|
||||
QTest::newRow("Some spaces") << std::string {"horse "} << std::string {"horse"};
|
||||
QTest::newRow("Some leading and trailing") << std::string {" horse "} << std::string {" horse"};
|
||||
}
|
||||
|
||||
void TestDistinguishedNameParser::testParseHexString()
|
||||
{
|
||||
QFETCH(std::string, input);
|
||||
QFETCH(std::optional<std::string>, expectedOutput);
|
||||
|
||||
auto result = DN::detail::parseHexString(input);
|
||||
QCOMPARE(result, expectedOutput);
|
||||
}
|
||||
|
||||
void TestDistinguishedNameParser::testParseHexString_data()
|
||||
{
|
||||
QTest::addColumn<std::string>("input");
|
||||
QTest::addColumn<std::optional<std::string>>("expectedOutput");
|
||||
|
||||
QTest::newRow("4") << std::string {"34"} << std::optional<std::string>("4");
|
||||
QTest::newRow("Koch") << std::string {"4B6F6368"} << std::optional<std::string>("Koch");
|
||||
QTest::newRow("USt-IdNr. DE 123475223") << std::string {"5553742D49644E722E20444520313233343735323233"} << std::optional<std::string>("USt-IdNr. DE 123475223");
|
||||
|
||||
// various baddies
|
||||
QTest::newRow("empty") << std::string {} << std::optional<std::string> {};
|
||||
QTest::newRow("FFF") << std::string {"FFF"} << std::optional<std::string> {};
|
||||
QTest::newRow("F") << std::string {"F"} << std::optional<std::string> {};
|
||||
QTest::newRow("XX") << std::string {"XX"} << std::optional<std::string> {};
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(TestDistinguishedNameParser);
|
||||
#include "check_distinguished_name_parser.moc"
|
|
@ -4,6 +4,7 @@
|
|||
#include <QDialog>
|
||||
#include <QPushButton>
|
||||
#include <QTest>
|
||||
#include <QTimer>
|
||||
|
||||
namespace TestingUtils
|
||||
{
|
||||
|
@ -39,7 +40,7 @@ CloseDialogHelper::~CloseDialogHelper()
|
|||
void CloseDialogHelper::closeDialog()
|
||||
{
|
||||
QWidget *dialog = (m_widget) ? m_widget->findChild<QDialog *>() : qApp->activeModalWidget();
|
||||
if (!dialog) {
|
||||
if (!dialog || !QTest::qWaitForWindowExposed(dialog)) {
|
||||
QTimer::singleShot(0, this, &CloseDialogHelper::closeDialog);
|
||||
return;
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
BIN
autotests/data/fieldFormat.pdf
Normal file
BIN
autotests/data/fieldFormat.pdf
Normal file
Binary file not shown.
9
autotests/data/strikethrough.md
Normal file
9
autotests/data/strikethrough.md
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Test for strikethrough tag workaround
|
||||
|
||||
Line without strikethrough
|
||||
|
||||
Line ~~with~~ strikethrough
|
||||
|
||||
```
|
||||
~~Strikethrough~~ should be <del>ignored</del> in a <s>code block</s>
|
||||
```
|
BIN
autotests/data/synctextest.pdf
Normal file
BIN
autotests/data/synctextest.pdf
Normal file
Binary file not shown.
BIN
autotests/data/synctextest.synctex.gz
Normal file
BIN
autotests/data/synctextest.synctex.gz
Normal file
Binary file not shown.
|
@ -164,6 +164,12 @@ void DocumentTest::testDiff_data()
|
|||
QTest::addRow("unicode") << "☮🤌"
|
||||
<< "☮🤌❤️"
|
||||
<< "❤️";
|
||||
QTest::addRow("unicode2") << "☮"
|
||||
<< "☮🤌❤️"
|
||||
<< "🤌❤️";
|
||||
QTest::addRow("unicode3") << "🤍"
|
||||
<< "🤌"
|
||||
<< "🤌";
|
||||
}
|
||||
|
||||
void DocumentTest::testDiff()
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <QtTest>
|
||||
#include <QTest>
|
||||
|
||||
#include "../settings_core.h"
|
||||
#include <QLocale>
|
||||
|
@ -30,6 +30,8 @@ private Q_SLOTS:
|
|||
void testFocusAction_data();
|
||||
void testValidateAction();
|
||||
void testValidateAction_data();
|
||||
void testNumberFormat();
|
||||
void testNumberFormat_data();
|
||||
|
||||
private:
|
||||
Okular::Document *m_document;
|
||||
|
@ -168,6 +170,36 @@ void FormatTest::testValidateAction_data()
|
|||
QTest::newRow("invalid text was set") << QStringLiteral("abc") << QStringLiteral("invalid");
|
||||
}
|
||||
|
||||
void FormatTest::testNumberFormat()
|
||||
{
|
||||
m_formattedText = QString();
|
||||
QFETCH(QString, fieldName);
|
||||
QFETCH(QString, text);
|
||||
QFETCH(QString, result);
|
||||
|
||||
Okular::FormFieldText *fft = reinterpret_cast<Okular::FormFieldText *>(m_fields[fieldName]);
|
||||
fft->setText(text);
|
||||
m_document->processFormatAction(fft->additionalAction(Okular::FormField::FormatField), fft);
|
||||
|
||||
QCOMPARE(m_formattedText, result);
|
||||
}
|
||||
|
||||
void FormatTest::testNumberFormat_data()
|
||||
{
|
||||
QTest::addColumn<QString>("fieldName");
|
||||
QTest::addColumn<QString>("text");
|
||||
QTest::addColumn<QString>("result");
|
||||
|
||||
QTest::newRow("EUR on left") << QStringLiteral("number1") << QStringLiteral("1.20") << QStringLiteral("€ 1.20");
|
||||
QTest::newRow("EUR on left with comma") << QStringLiteral("number1") << QStringLiteral("1234.20") << QStringLiteral("€ 1,234.20");
|
||||
QTest::newRow("EUR on right") << QStringLiteral("number2") << QStringLiteral("1.20") << QStringLiteral("1.20 €");
|
||||
QTest::newRow("EUR on right without comma") << QStringLiteral("number2") << QStringLiteral("1234.20") << QStringLiteral("1234.20 €");
|
||||
QTest::newRow("EUR on left using comma sep") << QStringLiteral("number3") << QStringLiteral("1,20") << QStringLiteral("€ 1,20");
|
||||
QTest::newRow("EUR on left using comma sep and thousands with dot") << QStringLiteral("number3") << QStringLiteral("1234,20") << QStringLiteral("€ 1.234,20");
|
||||
QTest::newRow("EUR on right with comma") << QStringLiteral("number4") << QStringLiteral("1,20") << /*true <<*/ QStringLiteral("1,20 €");
|
||||
QTest::newRow("EUR on right with dot sep without thousands sep") << QStringLiteral("number4") << QStringLiteral("1234,20") << QStringLiteral("1234,20 €");
|
||||
}
|
||||
|
||||
void FormatTest::cleanupTestCase()
|
||||
{
|
||||
m_document->closeDocument();
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
*/
|
||||
|
||||
#include <KPluginFactory>
|
||||
#include <KPluginLoader>
|
||||
#include <QDebug>
|
||||
#include <QDirIterator>
|
||||
#include <QLibrary>
|
||||
#include <QStringList>
|
||||
#include <QTest>
|
||||
|
||||
|
@ -40,11 +40,8 @@ void GeneratorsTest::testLoadsCorrectly()
|
|||
}
|
||||
int failures = 0;
|
||||
int successful = 0;
|
||||
for (const QString &lib : qAsConst(generatorLibs)) {
|
||||
KPluginLoader loader(lib);
|
||||
QVERIFY2(!loader.fileName().isEmpty(), qPrintable(lib));
|
||||
qDebug() << loader.fileName();
|
||||
auto factory = loader.factory();
|
||||
for (const QString &lib : std::as_const(generatorLibs)) {
|
||||
auto factory = KPluginFactory::loadFactory(KPluginMetaData(lib)).plugin;
|
||||
if (!factory) {
|
||||
qWarning() << "Could not get KPluginFactory for" << lib;
|
||||
failures++;
|
||||
|
|
|
@ -4,7 +4,12 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <QtTest>
|
||||
#include <QAction>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QMenu>
|
||||
#include <QTest>
|
||||
#include <QTimer>
|
||||
|
||||
#include "../settings_core.h"
|
||||
#include "core/action.h"
|
||||
|
@ -74,7 +79,7 @@ private:
|
|||
bool m_checkBox;
|
||||
};
|
||||
|
||||
class KJSFunctionsTest : public QObject
|
||||
class JSFunctionsTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -87,6 +92,8 @@ private Q_SLOTS:
|
|||
void testGetOCGs();
|
||||
void cleanupTestCase();
|
||||
void testAlert();
|
||||
void testPopUpMenu();
|
||||
void testPopUpMenuEx();
|
||||
void testPrintD();
|
||||
void testPrintD_data();
|
||||
|
||||
|
@ -95,9 +102,9 @@ private:
|
|||
QMap<QString, Okular::FormField *> m_fields;
|
||||
};
|
||||
|
||||
void KJSFunctionsTest::initTestCase()
|
||||
void JSFunctionsTest::initTestCase()
|
||||
{
|
||||
Okular::SettingsCore::instance(QStringLiteral("kjsfunctionstest"));
|
||||
Okular::SettingsCore::instance(QStringLiteral("jsfunctionstest"));
|
||||
m_document = new Okular::Document(nullptr);
|
||||
|
||||
const QString testFile = QStringLiteral(KDESRCDIR "data/kjsfunctionstest.pdf");
|
||||
|
@ -112,7 +119,7 @@ void KJSFunctionsTest::initTestCase()
|
|||
}
|
||||
}
|
||||
|
||||
void KJSFunctionsTest::testNthFieldName()
|
||||
void JSFunctionsTest::testNthFieldName()
|
||||
{
|
||||
for (int i = 0; i < 21; ++i) {
|
||||
Okular::ScriptAction *action = new Okular::ScriptAction(Okular::JavaScript,
|
||||
|
@ -126,7 +133,7 @@ void KJSFunctionsTest::testNthFieldName()
|
|||
}
|
||||
}
|
||||
|
||||
void KJSFunctionsTest::testDisplay()
|
||||
void JSFunctionsTest::testDisplay()
|
||||
{
|
||||
Okular::ScriptAction *action = new Okular::ScriptAction(Okular::JavaScript, QStringLiteral("field = Doc.getField(\"0.0\");field.display=display.hidden;\
|
||||
field = Doc.getField(\"0.10\");field.display=display.visible;"));
|
||||
|
@ -173,7 +180,7 @@ void delay()
|
|||
}
|
||||
}
|
||||
|
||||
void KJSFunctionsTest::testSetClearInterval()
|
||||
void JSFunctionsTest::testSetClearInterval()
|
||||
{
|
||||
Okular::ScriptAction *action = new Okular::ScriptAction(Okular::JavaScript, QStringLiteral("obj = new Object();obj.idx=0;\
|
||||
obj.inc=function(){field = Doc.getField(Doc.getNthFieldName(obj.idx));\
|
||||
|
@ -192,7 +199,7 @@ void KJSFunctionsTest::testSetClearInterval()
|
|||
delete action;
|
||||
}
|
||||
|
||||
void KJSFunctionsTest::testSetClearTimeOut()
|
||||
void JSFunctionsTest::testSetClearTimeOut()
|
||||
{
|
||||
Okular::ScriptAction *action = new Okular::ScriptAction(Okular::JavaScript, QStringLiteral("intv = app.setTimeOut('obj.inc()', 1);obj.idx;"));
|
||||
m_document->processAction(action);
|
||||
|
@ -216,7 +223,7 @@ void KJSFunctionsTest::testSetClearTimeOut()
|
|||
delete action;
|
||||
}
|
||||
|
||||
void KJSFunctionsTest::testGetOCGs()
|
||||
void JSFunctionsTest::testGetOCGs()
|
||||
{
|
||||
QAbstractItemModel *model = m_document->layersModel();
|
||||
|
||||
|
@ -262,7 +269,7 @@ void KJSFunctionsTest::testGetOCGs()
|
|||
delete action;
|
||||
}
|
||||
|
||||
void KJSFunctionsTest::testAlert()
|
||||
void JSFunctionsTest::testAlert()
|
||||
{
|
||||
Okular::ScriptAction *action = new Okular::ScriptAction(Okular::JavaScript, QStringLiteral("ret = app.alert( \"Random Message\" );"));
|
||||
QScopedPointer<MessageBoxHelper> messageBoxHelper;
|
||||
|
@ -292,6 +299,146 @@ void KJSFunctionsTest::testAlert()
|
|||
delete action;
|
||||
}
|
||||
|
||||
class PopupMenuHelper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PopupMenuHelper()
|
||||
: m_menuFound(false)
|
||||
{
|
||||
QTimer::singleShot(0, this, &PopupMenuHelper::closeMenu);
|
||||
}
|
||||
|
||||
~PopupMenuHelper() override
|
||||
{
|
||||
}
|
||||
|
||||
bool menuFound()
|
||||
{
|
||||
return m_menuFound;
|
||||
}
|
||||
|
||||
const QJsonArray &menuTree()
|
||||
{
|
||||
return m_menuTree;
|
||||
}
|
||||
|
||||
private Q_SLOTS:
|
||||
void closeMenu()
|
||||
{
|
||||
const QWidgetList allToplevelWidgets = QApplication::topLevelWidgets();
|
||||
QMenu *menu = nullptr;
|
||||
for (QWidget *w : allToplevelWidgets) {
|
||||
if (w->objectName() == QStringLiteral("popUpMenuEx") && w->inherits("QMenu")) {
|
||||
menu = qobject_cast<QMenu *>(w);
|
||||
|
||||
// Generate an tree of string with all the menu trees
|
||||
processQMenuToJS(menu, m_menuTree);
|
||||
|
||||
menu->close();
|
||||
m_menuFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!menu) {
|
||||
QTimer::singleShot(0, this, &PopupMenuHelper::closeMenu);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static void processQMenuToJS(QMenu *menu, QJsonArray &array)
|
||||
{
|
||||
const QList<QAction *> actions = menu->actions();
|
||||
|
||||
for (QAction *action : actions) {
|
||||
QMenu *itMenu = action->menu();
|
||||
|
||||
if (itMenu != nullptr) {
|
||||
QJsonArray subMenus;
|
||||
subMenus.append(action->text());
|
||||
processQMenuToJS(itMenu, subMenus);
|
||||
array.append(subMenus);
|
||||
} else {
|
||||
array.append(action->text());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_menuFound;
|
||||
QJsonArray m_menuTree;
|
||||
};
|
||||
|
||||
void JSFunctionsTest::testPopUpMenu()
|
||||
{
|
||||
Okular::ScriptAction *action = new Okular::ScriptAction(Okular::JavaScript, QStringLiteral("ret = app.popUpMenu( [\"Fruits\",\"Apples\",\"Oranges\"], \"-\",\"Beans\",\"Corn\" );"));
|
||||
|
||||
QScopedPointer<PopupMenuHelper> popupMenuHelper;
|
||||
popupMenuHelper.reset(new PopupMenuHelper());
|
||||
m_document->processAction(action);
|
||||
QJsonArray expected = {
|
||||
QJsonArray {
|
||||
QJsonValue {QStringLiteral("Fruits")},
|
||||
QJsonValue {QStringLiteral("Apples")},
|
||||
QJsonValue {QStringLiteral("Oranges")},
|
||||
},
|
||||
QJsonValue {QStringLiteral("-")},
|
||||
QJsonValue {QStringLiteral("Beans")},
|
||||
QJsonValue {QStringLiteral("Corn")},
|
||||
};
|
||||
|
||||
QString expectedString = QString::fromUtf8(QJsonDocument(expected).toJson());
|
||||
QString resultString = QString::fromUtf8(QJsonDocument(popupMenuHelper->menuTree()).toJson());
|
||||
QString description = QStringLiteral("Expected:\n") + expectedString + QStringLiteral("But got:\n") + resultString;
|
||||
QVERIFY2(expected == popupMenuHelper->menuTree(), description.toUtf8().constData());
|
||||
|
||||
delete action;
|
||||
}
|
||||
|
||||
void JSFunctionsTest::testPopUpMenuEx()
|
||||
{
|
||||
QScopedPointer<PopupMenuHelper> popupMenuHelper;
|
||||
|
||||
Okular::ScriptAction *action = new Okular::ScriptAction(
|
||||
Okular::JavaScript,
|
||||
QStringLiteral("ret = app.popUpMenuEx( {cName:\"Fruits\", oSubMenu:[{cName:\"Apples\", bMarked:false},{cName:\"Oranges\", bMarked:true}]}, {cName:\"-\"},{cName:\"Beans\", bEnabled:false},{cName:\"Corn\", bEnabled:true} )"));
|
||||
|
||||
popupMenuHelper.reset(new PopupMenuHelper());
|
||||
m_document->processAction(action);
|
||||
QVERIFY(popupMenuHelper->menuFound());
|
||||
|
||||
QJsonArray expected = {
|
||||
QJsonArray {
|
||||
QJsonValue {QStringLiteral("Fruits")},
|
||||
QJsonValue {QStringLiteral("Apples")},
|
||||
QJsonValue {QStringLiteral("Oranges")},
|
||||
},
|
||||
QJsonValue {QStringLiteral("-")},
|
||||
QJsonValue {QStringLiteral("Beans")},
|
||||
QJsonValue {QStringLiteral("Corn")},
|
||||
};
|
||||
|
||||
QString expectedString = QString::fromUtf8(QJsonDocument(expected).toJson());
|
||||
QString resultString = QString::fromUtf8(QJsonDocument(popupMenuHelper->menuTree()).toJson());
|
||||
QString description = QStringLiteral("Expected:\n") + expectedString + QStringLiteral("But got:\n") + resultString;
|
||||
QVERIFY2(expected == popupMenuHelper->menuTree(), description.toUtf8().constData());
|
||||
|
||||
delete action;
|
||||
|
||||
// Test infinite recursion
|
||||
action = new Okular::ScriptAction(Okular::JavaScript, QStringLiteral("\
|
||||
var recursiveMenu = {\"cName\": \"Devil menu\"};\n\
|
||||
recursiveMenu.oSubMenu = [ recursiveMenu ];\n\
|
||||
ret = app.popUpMenuEx( recursiveMenu );"));
|
||||
|
||||
popupMenuHelper.reset(new PopupMenuHelper());
|
||||
m_document->processAction(action);
|
||||
QVERIFY(popupMenuHelper->menuFound());
|
||||
// Must not crash
|
||||
delete action;
|
||||
}
|
||||
|
||||
/** @brief Checks a single JS action against an expected result
|
||||
*
|
||||
* Runs an action with the given @p script and checks that it
|
||||
|
@ -312,7 +459,7 @@ private:
|
|||
QScopedPointer<MessageBoxHelper> box;
|
||||
};
|
||||
|
||||
void KJSFunctionsTest::testPrintD_data()
|
||||
void JSFunctionsTest::testPrintD_data()
|
||||
{
|
||||
// Force consistent locale
|
||||
QLocale locale(QStringLiteral("en_US"));
|
||||
|
@ -333,10 +480,10 @@ void KJSFunctionsTest::testPrintD_data()
|
|||
QTest::newRow("1") << QStringLiteral("ret = app.alert( util.printd( 1, date ) );") << QStringLiteral("2010.01.05 11:10:32");
|
||||
|
||||
QDate date(2010, 1, 5);
|
||||
QTest::newRow("2") << QStringLiteral("ret = app.alert( util.printd( 2, date ) );") << QString(date.toString(locale.dateFormat(QLocale::ShortFormat)) + QStringLiteral(" 11:10:32 AM"));
|
||||
QTest::newRow("2") << QStringLiteral("ret = app.alert( util.printd( 2, date ) );") << QString(date.toString(locale.dateFormat(QLocale::ShortFormat)) + QStringLiteral(" 11:10:32\u202FAM"));
|
||||
}
|
||||
|
||||
void KJSFunctionsTest::testPrintD()
|
||||
void JSFunctionsTest::testPrintD()
|
||||
{
|
||||
QFETCH(QString, script);
|
||||
QFETCH(QString, result);
|
||||
|
@ -345,11 +492,11 @@ void KJSFunctionsTest::testPrintD()
|
|||
PrintDHelper test(m_document, script, result);
|
||||
}
|
||||
|
||||
void KJSFunctionsTest::cleanupTestCase()
|
||||
void JSFunctionsTest::cleanupTestCase()
|
||||
{
|
||||
m_document->closeDocument();
|
||||
delete m_document;
|
||||
}
|
||||
|
||||
QTEST_MAIN(KJSFunctionsTest)
|
||||
#include "kjsfunctionstest.moc"
|
||||
QTEST_MAIN(JSFunctionsTest)
|
||||
#include "jsfunctionstest.moc"
|
|
@ -4,7 +4,7 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <QtTest>
|
||||
#include <QTest>
|
||||
|
||||
#include "../settings_core.h"
|
||||
#include <QLocale>
|
||||
|
|
|
@ -7,14 +7,22 @@
|
|||
// clazy:excludeall=qstring-allocations
|
||||
|
||||
#include <QTest>
|
||||
#include <config-okular.h>
|
||||
|
||||
#include <KConfigGroup>
|
||||
#include <KLineEdit>
|
||||
#include <KRecentFilesAction>
|
||||
|
||||
#if HAVE_DBUS
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusConnectionInterface>
|
||||
#endif // HAVE_DBUS
|
||||
#include <QPrintDialog>
|
||||
#include <QStandardPaths>
|
||||
#include <QTabBar>
|
||||
#include <QTabWidget>
|
||||
#include <QTemporaryFile>
|
||||
#include <QTimer>
|
||||
#include <qwidget.h>
|
||||
|
||||
#include "../core/document_p.h"
|
||||
|
@ -137,16 +145,17 @@ void MainShellTest::initTestCase()
|
|||
Okular::Settings::instance(QStringLiteral("mainshelltest"));
|
||||
|
||||
// Register in bus as okular
|
||||
#if HAVE_DBUS
|
||||
QDBusConnectionInterface *bus = QDBusConnection::sessionBus().interface();
|
||||
const QString myPid = QString::number(getpid());
|
||||
const QString serviceName = QStringLiteral("org.kde.okular-") + myPid;
|
||||
QVERIFY(bus->registerService(serviceName) == QDBusConnectionInterface::ServiceRegistered);
|
||||
|
||||
#endif
|
||||
// Tell the presentationWidget and queryClose to not be annoying
|
||||
KSharedConfigPtr c = KSharedConfig::openConfig();
|
||||
KConfigGroup cg = c->group("Notification Messages");
|
||||
cg.writeEntry("presentationInfo", false);
|
||||
cg.writeEntry("ShowTabWarning", false);
|
||||
KSharedConfigPtr c = KSharedConfig::openConfig(QStringLiteral("mainshelltest.kmessagebox"));
|
||||
KConfigGroup cg = c->group(QStringLiteral("General"));
|
||||
cg.writeEntry("presentationInfo", 4);
|
||||
cg.writeEntry("ShowTabWarning", 4);
|
||||
}
|
||||
|
||||
void MainShellTest::cleanupTestCase()
|
||||
|
@ -211,11 +220,14 @@ void MainShellTest::testShell_data()
|
|||
QTest::newRow("two files no tabs") << file1AndToc << QString() << false << QString() << 0u << false << false << false << 0u << false << false << QString();
|
||||
QTest::newRow("two files with tabs") << file1AndToc << QString() << true << QString() << 0u << false << false << false << 0u << false << false << QString();
|
||||
QTest::newRow("two files sequence no tabs") << file1 << QString() << false << tocReload << 0u << false << false << false << 0u << false << false << QString();
|
||||
#if HAVE_DBUS
|
||||
QTest::newRow("two files sequence with tabs") << file1 << QString() << true << tocReload << 0u << false << false << false << 0u << false << false << QString();
|
||||
#endif // HAVE_DBUS
|
||||
QTest::newRow("open file page number") << contentsEpub << optionsPage2 << false << QString() << 1u << false << false << false << 0u << false << false << QString();
|
||||
QTest::newRow("open file page number and presentation") << contentsEpub << optionsPage2Presentation << false << QString() << 1u << true << false << false << 0u << false << false << QString();
|
||||
QTest::newRow("open file find") << file1 << optionsFind << false << QString() << 0u << false << false << false << 0u << false << false << QStringLiteral("si:next-testing parameters!");
|
||||
QTest::newRow("open file print") << file1 << optionsPrint << false << QString() << 0u << false << true << false << 0u << false << false << QString();
|
||||
#if HAVE_DBUS
|
||||
QTest::newRow("open two files unique") << file1 << optionsUnique << false << tocReload << 0u << false << false << true << 0u << false << false << QString();
|
||||
QTest::newRow("open two files unique tabs") << file1 << optionsUnique << true << tocReload << 0u << false << false << true << 0u << false << false << QString();
|
||||
QTest::newRow("page number attach tabs") << file1 << QString() << true << contentsEpub[0] << 0u << false << false << false << 2u << false << false << QString();
|
||||
|
@ -227,6 +239,7 @@ void MainShellTest::testShell_data()
|
|||
QTest::newRow("page number attach unique tabs") << file1 << optionsUnique << true << contentsEpub[0] << 0u << false << false << true << 3u << false << false << QString();
|
||||
QTest::newRow("presentation attach unique tabs") << file1 << optionsUnique << true << contentsEpub[0] << 0u << false << false << true << 2u << true << false << QString();
|
||||
QTest::newRow("print attach unique tabs") << file1 << optionsUnique << true << contentsEpub[0] << 0u << false << false << true << 2u << false << true << QString();
|
||||
#endif // HAVE_DBUS
|
||||
}
|
||||
|
||||
void MainShellTest::testShell()
|
||||
|
@ -300,7 +313,7 @@ void MainShellTest::testShell()
|
|||
QCOMPARE(partDocument(part2)->currentPage(), expectedPage);
|
||||
openUrls << part2->url().url();
|
||||
|
||||
for (const QString &path : qAsConst(paths)) {
|
||||
for (const QString &path : std::as_const(paths)) {
|
||||
QVERIFY(openUrls.contains(QStringLiteral("file://%1").arg(path)));
|
||||
}
|
||||
}
|
||||
|
@ -469,8 +482,10 @@ void MainShellTest::test2FilesError_data()
|
|||
|
||||
QTest::newRow("startInPresentation") << ShellUtils::serializeOptions(true, false, false, false, false, QString(), QString(), QString());
|
||||
QTest::newRow("showPrintDialog") << ShellUtils::serializeOptions(false, true, false, false, false, QString(), QString(), QString());
|
||||
#if HAVE_DBUS
|
||||
QTest::newRow("unique") << ShellUtils::serializeOptions(false, false, false, true, false, QString(), QString(), QString());
|
||||
QTest::newRow("pageNumber") << ShellUtils::serializeOptions(false, false, false, false, false, QStringLiteral("3"), QString(), QString());
|
||||
#endif // HAVE_DBUS
|
||||
QTest::newRow("find") << ShellUtils::serializeOptions(false, false, false, false, false, QString(), QStringLiteral("silly"), QString());
|
||||
}
|
||||
|
||||
|
@ -524,7 +539,7 @@ void MainShellTest::testSessionRestore()
|
|||
QList<Shell *> shells = getShells();
|
||||
QVERIFY(!shells.isEmpty());
|
||||
int numDocs = 0;
|
||||
for (Shell *shell : qAsConst(shells)) {
|
||||
for (Shell *shell : std::as_const(shells)) {
|
||||
QVERIFY(QTest::qWaitForWindowExposed(shell));
|
||||
numDocs += shell->m_tabs.size();
|
||||
}
|
||||
|
@ -544,7 +559,7 @@ void MainShellTest::testSessionRestore()
|
|||
int numWindows = 0;
|
||||
{ // Scope for config so that we can reconstruct from file
|
||||
KConfig config(configFile.fileName(), KConfig::SimpleConfig);
|
||||
for (Shell *shell : qAsConst(shells)) {
|
||||
for (Shell *shell : std::as_const(shells)) {
|
||||
shell->savePropertiesInternal(&config, ++numWindows);
|
||||
// Windows aren't necessarily closed on shutdown, but we'll use
|
||||
// this as a way to trigger the destructor code, which is normally
|
||||
|
@ -558,8 +573,10 @@ void MainShellTest::testSessionRestore()
|
|||
QEventLoop eventLoop;
|
||||
QTimer::singleShot(100, &eventLoop, &QEventLoop::quit);
|
||||
eventLoop.exec(QEventLoop::AllEvents);
|
||||
// Sometimes the event loop is not enough, so try a bit more to get deferred delete happen
|
||||
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
|
||||
shells = getShells();
|
||||
QVERIFY(shells.isEmpty());
|
||||
QCOMPARE(shells.size(), 0);
|
||||
|
||||
Okular::Settings::self()->setShellOpenFileInTabs(useTabsRestore);
|
||||
|
||||
|
@ -577,7 +594,7 @@ void MainShellTest::testSessionRestore()
|
|||
shells = getShells();
|
||||
QVERIFY(!shells.isEmpty());
|
||||
numDocs = 0;
|
||||
for (Shell *shell : qAsConst(shells)) {
|
||||
for (Shell *shell : std::as_const(shells)) {
|
||||
QVERIFY(QTest::qWaitForWindowExposed(shell));
|
||||
numDocs += shell->m_tabs.size();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <QMimeDatabase>
|
||||
#include <QMimeType>
|
||||
#include <QTextDocument>
|
||||
#include <memory>
|
||||
|
||||
class MarkdownTest : public QObject
|
||||
{
|
||||
|
@ -24,6 +25,8 @@ private Q_SLOTS:
|
|||
void testFancyPantsDisabled();
|
||||
void testImageSizes();
|
||||
void testSpecialCharsInImageFileName();
|
||||
void testStrikeThrough();
|
||||
void testHtmlTagFixup();
|
||||
|
||||
private:
|
||||
void findImages(QTextFrame *parent, QVector<QTextImageFormat> &images);
|
||||
|
@ -39,7 +42,7 @@ void MarkdownTest::testFancyPantsEnabled()
|
|||
{
|
||||
Markdown::Converter converter;
|
||||
converter.setFancyPantsEnabled(true);
|
||||
QTextDocument *document = converter.convert(QStringLiteral(KDESRCDIR "data/imageSizes.md"));
|
||||
std::unique_ptr<QTextDocument> document(converter.convert(QStringLiteral(KDESRCDIR "data/imageSizes.md")));
|
||||
|
||||
QTextFrame::iterator secondFrame = ++(document->rootFrame()->begin());
|
||||
QVERIFY(secondFrame.currentBlock().text().startsWith(QStringLiteral("©")));
|
||||
|
@ -49,7 +52,7 @@ void MarkdownTest::testFancyPantsDisabled()
|
|||
{
|
||||
Markdown::Converter converter;
|
||||
converter.setFancyPantsEnabled(false);
|
||||
QTextDocument *document = converter.convert(QStringLiteral(KDESRCDIR "data/imageSizes.md"));
|
||||
std::unique_ptr<QTextDocument> document(converter.convert(QStringLiteral(KDESRCDIR "data/imageSizes.md")));
|
||||
|
||||
QTextFrame::iterator secondFrame = ++(document->rootFrame()->begin());
|
||||
QVERIFY(secondFrame.currentBlock().text().startsWith(QStringLiteral("(c)")));
|
||||
|
@ -58,7 +61,7 @@ void MarkdownTest::testFancyPantsDisabled()
|
|||
void MarkdownTest::testImageSizes()
|
||||
{
|
||||
Markdown::Converter converter;
|
||||
QTextDocument *document = converter.convert(QStringLiteral(KDESRCDIR "data/imageSizes.md"));
|
||||
std::unique_ptr<QTextDocument> document(converter.convert(QStringLiteral(KDESRCDIR "data/imageSizes.md")));
|
||||
|
||||
QTextFrame *parent = document->rootFrame();
|
||||
|
||||
|
@ -125,7 +128,7 @@ void MarkdownTest::findImages(const QTextBlock &parent, QVector<QTextImageFormat
|
|||
void MarkdownTest::testSpecialCharsInImageFileName()
|
||||
{
|
||||
Markdown::Converter converter;
|
||||
QTextDocument *document = converter.convert(QStringLiteral(KDESRCDIR "data/imageUrlsWithSpecialChars.md"));
|
||||
std::unique_ptr<QTextDocument> document(converter.convert(QStringLiteral(KDESRCDIR "data/imageUrlsWithSpecialChars.md")));
|
||||
|
||||
QTextFrame *parent = document->rootFrame();
|
||||
|
||||
|
@ -137,5 +140,87 @@ void MarkdownTest::testSpecialCharsInImageFileName()
|
|||
QVERIFY(!images[0].name().contains(QStringLiteral("kart%C3%B6ffelchen.jpg")));
|
||||
}
|
||||
|
||||
void MarkdownTest::testStrikeThrough()
|
||||
{
|
||||
Markdown::Converter converter;
|
||||
converter.setFancyPantsEnabled(true);
|
||||
std::unique_ptr<QTextDocument> document(converter.convert(QStringLiteral(KDESRCDIR "data/strikethrough.md")));
|
||||
|
||||
const QTextFrame *rootFrame = document->rootFrame();
|
||||
auto frameIter = rootFrame->begin();
|
||||
|
||||
// Header line.
|
||||
QCOMPARE_NE(frameIter, rootFrame->end());
|
||||
QCOMPARE(frameIter.currentBlock().text(), QStringLiteral("Test for strikethrough tag workaround"));
|
||||
|
||||
// Ordinary line.
|
||||
{
|
||||
++frameIter;
|
||||
QCOMPARE_NE(frameIter, rootFrame->end());
|
||||
auto block = frameIter.currentBlock();
|
||||
QCOMPARE(block.text(), QStringLiteral("Line without strikethrough"));
|
||||
// Single format for the entire line.
|
||||
auto formats = block.textFormats();
|
||||
QCOMPARE(formats.size(), 1);
|
||||
QVERIFY(!formats[0].format.fontStrikeOut());
|
||||
}
|
||||
|
||||
// Part of the line has a strikethrough.
|
||||
{
|
||||
++frameIter;
|
||||
QCOMPARE_NE(frameIter, rootFrame->end());
|
||||
auto block = frameIter.currentBlock();
|
||||
QCOMPARE(block.text(), QStringLiteral("Line with strikethrough"));
|
||||
// The "with" should be the only thing striked out.
|
||||
auto formats = block.textFormats();
|
||||
QCOMPARE(formats.size(), 3);
|
||||
QCOMPARE(block.text().sliced(formats[0].start, formats[0].length), QStringLiteral("Line "));
|
||||
QVERIFY(!formats[0].format.fontStrikeOut());
|
||||
QCOMPARE(block.text().sliced(formats[1].start, formats[1].length), QStringLiteral("with"));
|
||||
QVERIFY(formats[1].format.fontStrikeOut());
|
||||
QCOMPARE(block.text().sliced(formats[2].start, formats[2].length), QStringLiteral(" strikethrough"));
|
||||
QVERIFY(!formats[2].format.fontStrikeOut());
|
||||
}
|
||||
|
||||
// Code block shouldn't have leading spaces, or be modified by our fixup.
|
||||
{
|
||||
++frameIter;
|
||||
QCOMPARE_NE(frameIter, rootFrame->end());
|
||||
auto block = frameIter.currentBlock();
|
||||
QCOMPARE(block.text(), QStringLiteral("~~Strikethrough~~ should be <del>ignored</del> in a <s>code block</s>"));
|
||||
}
|
||||
}
|
||||
|
||||
void MarkdownTest::testHtmlTagFixup()
|
||||
{
|
||||
const QString wrapperTag = QStringLiteral("ignored_by_qt");
|
||||
const QString wrapperTagBegin = QStringLiteral("<ignored_by_qt>");
|
||||
const QString wrapperTagEnd = QStringLiteral("</ignored_by_qt>");
|
||||
|
||||
// These should passthrough unchanged.
|
||||
const QString testCases[] = {
|
||||
QStringLiteral("basic test"),
|
||||
QStringLiteral("<p>test with tag</p>"),
|
||||
QStringLiteral("line with <em>combined <strong>tags</strong></em>"),
|
||||
};
|
||||
for (const QString &inputHtml : testCases) {
|
||||
const QString outputHtml = Markdown::detail::fixupHtmlTags(QString(inputHtml));
|
||||
QCOMPARE(outputHtml, wrapperTagBegin + inputHtml + wrapperTagEnd);
|
||||
}
|
||||
|
||||
// <del> should become <s>.
|
||||
{
|
||||
const QString outputHtml = Markdown::detail::fixupHtmlTags(QStringLiteral("<del>test</del>"));
|
||||
QCOMPARE(outputHtml, wrapperTagBegin + QStringLiteral("<s>test</s>") + wrapperTagEnd);
|
||||
}
|
||||
|
||||
// Check that the wrapper is ignored by Qt.
|
||||
{
|
||||
QTextDocument dom;
|
||||
dom.setHtml(wrapperTagBegin + QStringLiteral("basic test") + wrapperTagEnd);
|
||||
QVERIFY(!dom.toHtml().contains(wrapperTag));
|
||||
}
|
||||
}
|
||||
|
||||
QTEST_MAIN(MarkdownTest)
|
||||
#include "markdowntest.moc"
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
|
||||
// clazy:excludeall=qstring-allocations
|
||||
|
||||
#include <QtTest>
|
||||
#include <QSignalSpy>
|
||||
#include <QTest>
|
||||
|
||||
#include "../core/annotations.h"
|
||||
#include "../core/document_p.h"
|
||||
|
@ -31,13 +32,16 @@
|
|||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QDesktopServices>
|
||||
#include <QLineEdit>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QScrollBar>
|
||||
#include <QTabletEvent>
|
||||
#include <QTemporaryDir>
|
||||
#include <QTemporaryFile>
|
||||
#include <QTextEdit>
|
||||
#include <QTimer>
|
||||
#include <QToolBar>
|
||||
#include <QTreeView>
|
||||
#include <QUrl>
|
||||
|
@ -64,6 +68,7 @@ private Q_SLOTS:
|
|||
void testForwardPDF_data();
|
||||
void testGeneratorPreferences();
|
||||
void testSelectText();
|
||||
void testSelectTextMultiline();
|
||||
void testClickInternalLink();
|
||||
void testScrollBarAndMouseWheel();
|
||||
void testOpenUrlArguments();
|
||||
|
@ -103,6 +108,7 @@ private Q_SLOTS:
|
|||
void testFullScreenRequest();
|
||||
void testZoomInFacingPages();
|
||||
void testLinkWithCrop();
|
||||
void testFieldFormatting();
|
||||
|
||||
private:
|
||||
void simulateMouseSelection(double startX, double startY, double endX, double endY, QWidget *target);
|
||||
|
@ -112,8 +118,8 @@ class PartThatHijacksQueryClose : public Okular::Part
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
PartThatHijacksQueryClose(QWidget *parentWidget, QObject *parent, const QVariantList &args)
|
||||
: Okular::Part(parentWidget, parent, args)
|
||||
PartThatHijacksQueryClose(QObject *parent, const QVariantList &args)
|
||||
: Okular::Part(parent, args)
|
||||
, behavior(PassThru)
|
||||
{
|
||||
}
|
||||
|
@ -168,7 +174,7 @@ void PartTest::init()
|
|||
void PartTest::testReload()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/file1.pdf")));
|
||||
part.reload();
|
||||
qApp->processEvents();
|
||||
|
@ -178,7 +184,7 @@ void PartTest::testReload()
|
|||
void PartTest::testCanceledReload()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
PartThatHijacksQueryClose part(nullptr, nullptr, dummyArgs);
|
||||
PartThatHijacksQueryClose part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/file1.pdf")));
|
||||
|
||||
// When queryClose() returns false, the reload operation is canceled (as if
|
||||
|
@ -193,7 +199,7 @@ void PartTest::testCanceledReload()
|
|||
void PartTest::testTOCReload()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/tocreload.pdf")));
|
||||
QCOMPARE(part.m_toc->expandedNodes().count(), 0);
|
||||
part.m_toc->m_treeView->expandAll();
|
||||
|
@ -208,42 +214,17 @@ void PartTest::testForwardPDF()
|
|||
QFETCH(QString, dir);
|
||||
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
|
||||
// Create temp dir named like this: ${system temp dir}/${random string}/${dir}
|
||||
const QTemporaryDir tempDir;
|
||||
const QDir workDir(QDir(tempDir.path()).filePath(dir));
|
||||
workDir.mkpath(QStringLiteral("."));
|
||||
|
||||
QFile f(QStringLiteral(KDESRCDIR "data/synctextest.tex"));
|
||||
const QString texDestination = workDir.path() + QStringLiteral("/synctextest.tex");
|
||||
QVERIFY(f.copy(texDestination));
|
||||
QProcess process;
|
||||
process.setWorkingDirectory(workDir.path());
|
||||
|
||||
const QString pdflatexPath(QStandardPaths::findExecutable(QStringLiteral("pdflatex")));
|
||||
if (pdflatexPath.isEmpty()) {
|
||||
QFAIL("pdflatex executable not found, but needed for the test. Try installing the respective TeXLive packages.");
|
||||
}
|
||||
process.start(pdflatexPath, QStringList() << QStringLiteral("-synctex=1") << QStringLiteral("-interaction=nonstopmode") << texDestination);
|
||||
bool started = process.waitForStarted();
|
||||
if (!started) {
|
||||
qDebug() << "start error:" << process.error();
|
||||
qDebug() << "start stdout:" << process.readAllStandardOutput();
|
||||
qDebug() << "start stderr:" << process.readAllStandardError();
|
||||
}
|
||||
QVERIFY(started);
|
||||
|
||||
process.waitForFinished();
|
||||
if (process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) {
|
||||
qDebug() << "exit error:" << process.error() << "status" << process.exitStatus() << "code" << process.exitCode();
|
||||
qDebug() << "exit stdout:" << process.readAllStandardOutput();
|
||||
qDebug() << "exit stderr:" << process.readAllStandardError();
|
||||
}
|
||||
|
||||
const QString pdfResult = workDir.path() + QStringLiteral("/synctextest.pdf");
|
||||
|
||||
QVERIFY(QFile::exists(pdfResult));
|
||||
QVERIFY(QFile::copy(QStringLiteral(KDESRCDIR "data/synctextest.pdf"), pdfResult));
|
||||
const QString gzDestination = workDir.path() + QStringLiteral("/synctextest.synctex.gz");
|
||||
QVERIFY(QFile::copy(QStringLiteral(KDESRCDIR "data/synctextest.synctex.gz"), gzDestination));
|
||||
|
||||
QVERIFY(openDocument(&part, pdfResult));
|
||||
part.m_document->setViewportPage(0);
|
||||
|
@ -251,7 +232,8 @@ void PartTest::testForwardPDF()
|
|||
part.closeUrl();
|
||||
|
||||
QUrl u(QUrl::fromLocalFile(pdfResult));
|
||||
u.setFragment(QStringLiteral("src:100") + texDestination);
|
||||
// Update this if you regenerate the synctextest.pdf somewhere else
|
||||
u.setFragment(QStringLiteral("src:100/home/tsdgeos/devel/kde/okular/autotests/data/synctextest.tex"));
|
||||
part.openUrl(u);
|
||||
QCOMPARE(part.m_document->currentPage(), 1u);
|
||||
}
|
||||
|
@ -269,7 +251,7 @@ void PartTest::testGeneratorPreferences()
|
|||
{
|
||||
KConfigDialog *dialog;
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
|
||||
// Test that we don't crash while opening the dialog
|
||||
dialog = part.slotGeneratorPreferences();
|
||||
|
@ -286,7 +268,7 @@ void PartTest::testGeneratorPreferences()
|
|||
void PartTest::testSelectText()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/file2.pdf")));
|
||||
part.widget()->show();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(part.widget()));
|
||||
|
@ -313,10 +295,71 @@ void PartTest::testSelectText()
|
|||
QCOMPARE(QApplication::clipboard()->text(), QStringLiteral("Hola que tal"));
|
||||
}
|
||||
|
||||
void PartTest::testSelectTextMultiline()
|
||||
{
|
||||
// This test tests a specific variation of multiline selection
|
||||
// Select from middle to end of line, then continue to select next line
|
||||
// then move selection back on next line past the point of the first line
|
||||
// https://bugs.kde.org/show_bug.cgi?id=482249 has a nice animation.
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/file2.pdf")));
|
||||
part.widget()->show();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(part.widget()));
|
||||
|
||||
part.m_document->setViewportPage(1);
|
||||
|
||||
// wait for pixmap
|
||||
QTRY_VERIFY(part.m_document->page(0)->hasPixmap(part.m_pageView));
|
||||
|
||||
const int width = part.m_pageView->horizontalScrollBar()->maximum() + part.m_pageView->viewport()->width();
|
||||
const int height = part.m_pageView->verticalScrollBar()->maximum() + part.m_pageView->viewport()->height();
|
||||
|
||||
QVERIFY(QMetaObject::invokeMethod(part.m_pageView, "slotSetMouseTextSelect"));
|
||||
|
||||
const int startY = height * 0.052;
|
||||
const int startX = width * 0.22;
|
||||
const int endY = height * 0.072;
|
||||
const int endX = width * 0.6;
|
||||
|
||||
const int steps = 5;
|
||||
const double diffX = endX - startX;
|
||||
const double diffXStep = diffX / steps;
|
||||
|
||||
QTestEventList events;
|
||||
events.addMouseMove(QPoint(startX, startY));
|
||||
events.addMousePress(Qt::LeftButton, Qt::NoModifier, QPoint(startX, startY));
|
||||
for (int i = 0; i < steps - 1; ++i) {
|
||||
events.addMouseMove(QPoint(startX + i * diffXStep, startY));
|
||||
events.addDelay(100);
|
||||
}
|
||||
events.addMouseMove(QPoint(endX, startY));
|
||||
events.addDelay(100);
|
||||
events.addMouseMove(QPoint(endX, endY));
|
||||
events.addDelay(100);
|
||||
for (int i = 0; i < (steps); i++) {
|
||||
events.addMouseMove(QPoint(endX - (i * diffXStep), endY));
|
||||
events.addDelay(100);
|
||||
}
|
||||
events.addMouseMove(QPoint(endX - (diffXStep * (steps)), endY));
|
||||
events.addDelay(100);
|
||||
events.addMouseMove(QPoint(endX - (diffXStep * (steps + 0.5)), endY));
|
||||
events.addDelay(100);
|
||||
|
||||
events.addMouseRelease(Qt::LeftButton, Qt::NoModifier, QPoint(endX - (diffXStep * (steps + 0.5)), endY));
|
||||
|
||||
events.simulate(part.m_pageView->viewport());
|
||||
|
||||
QApplication::clipboard()->clear();
|
||||
QVERIFY(QMetaObject::invokeMethod(part.m_pageView, "copyTextSelection"));
|
||||
|
||||
QCOMPARE(QApplication::clipboard()->text(), QStringLiteral("cks!\nOf c"));
|
||||
}
|
||||
|
||||
void PartTest::testClickInternalLink()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/file2.pdf")));
|
||||
part.widget()->show();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(part.widget()));
|
||||
|
@ -329,7 +372,7 @@ void PartTest::testClickInternalLink()
|
|||
const int width = part.m_pageView->horizontalScrollBar()->maximum() + part.m_pageView->viewport()->width();
|
||||
const int height = part.m_pageView->verticalScrollBar()->maximum() + part.m_pageView->viewport()->height();
|
||||
|
||||
QMetaObject::invokeMethod(part.m_pageView, "slotMouseNormalToggled", Q_ARG(bool, true));
|
||||
QVERIFY(QMetaObject::invokeMethod(part.m_pageView, "slotSetMouseNormal"));
|
||||
|
||||
QCOMPARE(part.m_document->currentPage(), 0u);
|
||||
QTest::mouseMove(part.m_pageView->viewport(), QPoint(width * 0.17, height * 0.05));
|
||||
|
@ -346,7 +389,7 @@ void PartTest::testClickInternalLink()
|
|||
void PartTest::testScrollBarAndMouseWheel()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/simple-multipage.pdf")));
|
||||
part.widget()->show();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(part.widget()));
|
||||
|
@ -384,7 +427,7 @@ void PartTest::testScrollBarAndMouseWheel()
|
|||
void PartTest::testMouseMoveOverLinkWhileInSelectionMode()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/pdf_with_links.pdf")));
|
||||
// resize window to avoid problem with selection areas
|
||||
part.widget()->resize(800, 600);
|
||||
|
@ -413,7 +456,7 @@ void PartTest::testMouseMoveOverLinkWhileInSelectionMode()
|
|||
void PartTest::testClickUrlLinkWhileInSelectionMode()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/pdf_with_links.pdf")));
|
||||
// resize window to avoid problem with selection areas
|
||||
part.widget()->resize(800, 600);
|
||||
|
@ -463,7 +506,7 @@ void PartTest::testeTextSelectionOverAndAcrossLinks_data()
|
|||
void PartTest::testeTextSelectionOverAndAcrossLinks()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/pdf_with_links.pdf")));
|
||||
// resize window to avoid problem with selection areas
|
||||
part.widget()->resize(800, 600);
|
||||
|
@ -501,7 +544,7 @@ void PartTest::testeTextSelectionOverAndAcrossLinks()
|
|||
void PartTest::testClickUrlLinkWhileLinkTextIsSelected()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/pdf_with_links.pdf")));
|
||||
// resize window to avoid problem with selection areas
|
||||
part.widget()->resize(800, 600);
|
||||
|
@ -546,7 +589,7 @@ void PartTest::testClickUrlLinkWhileLinkTextIsSelected()
|
|||
void PartTest::testRClickWhileLinkTextIsSelected()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/pdf_with_links.pdf")));
|
||||
// resize window to avoid problem with selection areas
|
||||
part.widget()->resize(800, 600);
|
||||
|
@ -612,7 +655,7 @@ void PartTest::testRClickWhileLinkTextIsSelected()
|
|||
void PartTest::testRClickOverLinkWhileLinkTextIsSelected()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/pdf_with_links.pdf")));
|
||||
// resize window to avoid problem with selection areas
|
||||
part.widget()->resize(800, 600);
|
||||
|
@ -673,7 +716,7 @@ void PartTest::testRClickOverLinkWhileLinkTextIsSelected()
|
|||
void PartTest::testRClickOnSelectionModeShoulShowFollowTheLinkMenu()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/pdf_with_links.pdf")));
|
||||
// resize window to avoid problem with selection areas
|
||||
part.widget()->resize(800, 600);
|
||||
|
@ -728,7 +771,7 @@ void PartTest::testRClickOnSelectionModeShoulShowFollowTheLinkMenu()
|
|||
void PartTest::testClickAnywhereAfterSelectionShouldUnselect()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/pdf_with_links.pdf")));
|
||||
// resize window to avoid problem with selection areas
|
||||
part.widget()->resize(800, 600);
|
||||
|
@ -768,7 +811,7 @@ void PartTest::testClickAnywhereAfterSelectionShouldUnselect()
|
|||
void PartTest::testeRectSelectionStartingOnLinks()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/pdf_with_links.pdf")));
|
||||
// hide info messages as they interfere with selection area
|
||||
Okular::Settings::self()->setShowEmbeddedContentMessages(false);
|
||||
|
@ -843,7 +886,7 @@ void PartTest::simulateMouseSelection(double startX, double startY, double endX,
|
|||
|
||||
void PartTest::testSaveAsToNonExistingPath()
|
||||
{
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, {});
|
||||
part.openDocument(QStringLiteral(KDESRCDIR "data/file1.pdf"));
|
||||
|
||||
QString saveFilePath;
|
||||
|
@ -864,7 +907,7 @@ void PartTest::testSaveAsToNonExistingPath()
|
|||
void PartTest::testSaveAsToSymlink()
|
||||
{
|
||||
#ifdef Q_OS_UNIX
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, {});
|
||||
part.openDocument(QStringLiteral(KDESRCDIR "data/file1.pdf"));
|
||||
|
||||
QTemporaryFile newFile(QStringLiteral("%1/okrXXXXXX.pdf").arg(QDir::tempPath()));
|
||||
|
@ -893,7 +936,7 @@ void PartTest::testSaveAsToSymlink()
|
|||
void PartTest::testSaveIsSymlink()
|
||||
{
|
||||
#ifdef Q_OS_UNIX
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, {});
|
||||
|
||||
QString newFilePath;
|
||||
{
|
||||
|
@ -949,7 +992,7 @@ void PartTest::testSaveAs()
|
|||
|
||||
qDebug() << "Open file, add annotation and save both natively and to .okular";
|
||||
{
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, {});
|
||||
part.openDocument(file);
|
||||
part.m_document->documentInfo();
|
||||
|
||||
|
@ -989,7 +1032,7 @@ void PartTest::testSaveAs()
|
|||
|
||||
qDebug() << "Open the .okular, check that the annotation is present and save to native";
|
||||
{
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, {});
|
||||
part.openDocument(archiveSave.fileName());
|
||||
part.m_document->documentInfo();
|
||||
|
||||
|
@ -1015,7 +1058,7 @@ void PartTest::testSaveAs()
|
|||
qDebug() << "Open the native file saved directly, and check that the annot"
|
||||
<< "is there iff we expect it";
|
||||
{
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, {});
|
||||
part.openDocument(nativeDirectSave.fileName());
|
||||
|
||||
QCOMPARE(part.m_document->page(0)->annotations().size(), nativelySupportsAnnotations ? 1 : 0);
|
||||
|
@ -1029,7 +1072,7 @@ void PartTest::testSaveAs()
|
|||
qDebug() << "Open the native file saved from the .okular, and check that the annot"
|
||||
<< "is there iff we expect it";
|
||||
{
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, {});
|
||||
part.openDocument(nativeFromArchiveFile.fileName());
|
||||
|
||||
QCOMPARE(part.m_document->page(0)->annotations().size(), nativelySupportsAnnotations ? 1 : 0);
|
||||
|
@ -1060,8 +1103,7 @@ void PartTest::testSaveAs_data()
|
|||
|
||||
void PartTest::testSidebarItemAfterSaving()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, {});
|
||||
QWidget *currentSidebarItem = part.m_sidebar->currentItem(); // thumbnails
|
||||
openDocument(&part, QStringLiteral(KDESRCDIR "data/tocreload.pdf"));
|
||||
// since it has TOC it changes to TOC
|
||||
|
@ -1077,8 +1119,7 @@ void PartTest::testSidebarItemAfterSaving()
|
|||
|
||||
void PartTest::testViewModeSavingPerFile()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, {});
|
||||
|
||||
// Open some file
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/file1.pdf")));
|
||||
|
@ -1128,7 +1169,7 @@ void PartTest::testSaveAsUndoStackAnnotations()
|
|||
QVERIFY(saveFile2.open());
|
||||
saveFile2.close();
|
||||
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, {});
|
||||
part.openDocument(file);
|
||||
|
||||
QCOMPARE(part.m_document->canSwapBackingFile(), canSwapBackingFile);
|
||||
|
@ -1312,7 +1353,7 @@ void PartTest::testSaveAsUndoStackForms()
|
|||
QVERIFY(saveFile.open());
|
||||
saveFile.close();
|
||||
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, {});
|
||||
part.openDocument(file);
|
||||
|
||||
const QList<Okular::FormField *> pageFormFields = part.m_document->page(0)->formFields();
|
||||
|
@ -1389,8 +1430,7 @@ void PartTest::testSaveAsUndoStackForms_data()
|
|||
|
||||
void PartTest::testOpenUrlArguments()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, {});
|
||||
|
||||
KParts::OpenUrlArguments args;
|
||||
args.setMimeType(QStringLiteral("text/rtf"));
|
||||
|
@ -1404,14 +1444,14 @@ void PartTest::testOpenUrlArguments()
|
|||
|
||||
void PartTest::test388288()
|
||||
{
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, {});
|
||||
|
||||
part.openUrl(QUrl::fromLocalFile(QStringLiteral(KDESRCDIR "data/file1.pdf")));
|
||||
|
||||
part.widget()->show();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(part.widget()));
|
||||
|
||||
QMetaObject::invokeMethod(part.m_pageView, "slotMouseNormalToggled", Q_ARG(bool, true));
|
||||
QVERIFY(QMetaObject::invokeMethod(part.m_pageView, "slotSetMouseNormal"));
|
||||
|
||||
auto annot = new Okular::HighlightAnnotation();
|
||||
annot->setHighlightType(Okular::HighlightAnnotation::Highlight);
|
||||
|
@ -1456,7 +1496,7 @@ void PartTest::test388288()
|
|||
void PartTest::testCheckBoxReadOnly()
|
||||
{
|
||||
const QString testFile = QStringLiteral(KDESRCDIR "data/checkbox_ro.pdf");
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, {});
|
||||
part.openDocument(testFile);
|
||||
|
||||
// The test document uses the activation action of checkboxes
|
||||
|
@ -1569,7 +1609,7 @@ void PartTest::testCheckBoxReadOnly()
|
|||
void PartTest::testCrashTextEditDestroy()
|
||||
{
|
||||
const QString testFile = QStringLiteral(KDESRCDIR "data/formSamples.pdf");
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, {});
|
||||
part.openDocument(testFile);
|
||||
part.widget()->show();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(part.widget()));
|
||||
|
@ -1580,8 +1620,7 @@ void PartTest::testCrashTextEditDestroy()
|
|||
|
||||
void PartTest::testAnnotWindow()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, {});
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/file1.pdf")));
|
||||
part.widget()->show();
|
||||
part.widget()->resize(800, 600);
|
||||
|
@ -1589,7 +1628,7 @@ void PartTest::testAnnotWindow()
|
|||
|
||||
part.m_document->setViewportPage(0);
|
||||
|
||||
QMetaObject::invokeMethod(part.m_pageView, "slotMouseNormalToggled", Q_ARG(bool, true));
|
||||
QVERIFY(QMetaObject::invokeMethod(part.m_pageView, "slotSetMouseNormal"));
|
||||
|
||||
QCOMPARE(part.m_document->currentPage(), 0u);
|
||||
|
||||
|
@ -1682,7 +1721,7 @@ static void verifyTargetStates(const QString &triggerName, const QMap<QString, O
|
|||
void PartTest::testAdditionalActionTriggers()
|
||||
{
|
||||
const QString testFile = QStringLiteral(KDESRCDIR "data/additionalFormActions.pdf");
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, QVariantList());
|
||||
part.openDocument(testFile);
|
||||
part.widget()->resize(800, 600);
|
||||
|
||||
|
@ -1793,7 +1832,7 @@ void PartTest::testAdditionalActionTriggers()
|
|||
|
||||
void PartTest::testTypewriterAnnotTool()
|
||||
{
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, QVariantList());
|
||||
|
||||
part.openUrl(QUrl::fromLocalFile(QStringLiteral(KDESRCDIR "data/file1.pdf")));
|
||||
|
||||
|
@ -1830,7 +1869,7 @@ void PartTest::testJumpToPage()
|
|||
{
|
||||
const QString testFile = QStringLiteral(KDESRCDIR "data/simple-multipage.pdf");
|
||||
const int targetPage = 25;
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, QVariantList());
|
||||
part.openDocument(testFile);
|
||||
part.widget()->resize(800, 600);
|
||||
part.widget()->show();
|
||||
|
@ -1860,7 +1899,7 @@ void PartTest::testOpenAtPage()
|
|||
{
|
||||
const QString testFile = QStringLiteral(KDESRCDIR "data/simple-multipage.pdf");
|
||||
QUrl url = QUrl::fromLocalFile(testFile);
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, QVariantList());
|
||||
|
||||
const uint targetPageNumA = 25;
|
||||
const uint expectedPageA = targetPageNumA - 1;
|
||||
|
@ -1879,7 +1918,7 @@ void PartTest::testOpenAtPage()
|
|||
void PartTest::testForwardBackwardNavigation()
|
||||
{
|
||||
const QString testFile = QStringLiteral(KDESRCDIR "data/simple-multipage.pdf");
|
||||
Okular::Part part(nullptr, nullptr, QVariantList());
|
||||
Okular::Part part(nullptr, QVariantList());
|
||||
part.openDocument(testFile);
|
||||
part.widget()->resize(800, 600);
|
||||
part.widget()->show();
|
||||
|
@ -1908,7 +1947,7 @@ void PartTest::testForwardBackwardNavigation()
|
|||
void PartTest::testTabletProximityBehavior()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part {nullptr, nullptr, dummyArgs};
|
||||
Okular::Part part {nullptr, dummyArgs};
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/file1.pdf")));
|
||||
part.slotShowPresentation();
|
||||
PresentationWidget *w = part.m_presentationWidget;
|
||||
|
@ -1918,8 +1957,9 @@ void PartTest::testTabletProximityBehavior()
|
|||
// close the KMessageBox "There are two ways of exiting[...]"
|
||||
TestingUtils::CloseDialogHelper closeDialogHelper(w, QDialogButtonBox::Ok); // confirm the "To leave, press ESC"
|
||||
|
||||
QTabletEvent enterProximityEvent {QEvent::TabletEnterProximity, QPoint(10, 10), QPoint(10, 10), QTabletEvent::Stylus, QTabletEvent::Pen, 1., 0, 0, 1., 1., 0, Qt::NoModifier, 0, Qt::NoButton, Qt::NoButton};
|
||||
QTabletEvent leaveProximityEvent {QEvent::TabletLeaveProximity, QPoint(10, 10), QPoint(10, 10), QTabletEvent::Stylus, QTabletEvent::Pen, 1., 0, 0, 1., 1., 0, Qt::NoModifier, 0, Qt::NoButton, Qt::NoButton};
|
||||
auto pointingDevice = new QPointingDevice(QStringLiteral("test"), 42, QInputDevice::DeviceType::Stylus, QPointingDevice::PointerType::Pen, QInputDevice::Capability::All, 3, 3);
|
||||
QTabletEvent enterProximityEvent {QEvent::TabletEnterProximity, pointingDevice, QPointF(10, 10), QPointF(10, 10), 1., 0, 0, 1., 1., 0, Qt::NoModifier, Qt::NoButton, Qt::NoButton};
|
||||
QTabletEvent leaveProximityEvent {QEvent::TabletLeaveProximity, pointingDevice, QPointF(10, 10), QPointF(10, 10), 1., 0, 0, 1., 1., 0, Qt::NoModifier, Qt::NoButton, Qt::NoButton};
|
||||
|
||||
// Test with the Okular::Settings::EnumSlidesCursor::Visible setting
|
||||
Okular::Settings::self()->setSlidesCursor(Okular::Settings::EnumSlidesCursor::Visible);
|
||||
|
@ -1968,7 +2008,7 @@ void PartTest::testTabletProximityBehavior()
|
|||
void PartTest::testOpenPrintPreview()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part {nullptr, nullptr, dummyArgs};
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/file1.pdf")));
|
||||
part.widget()->show();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(part.widget()));
|
||||
|
@ -1979,7 +2019,7 @@ void PartTest::testOpenPrintPreview()
|
|||
void PartTest::testMouseModeMenu()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/file1.pdf")));
|
||||
|
||||
QMetaObject::invokeMethod(part.m_pageView, "slotSetMouseNormal");
|
||||
|
@ -2010,7 +2050,7 @@ void PartTest::testMouseModeMenu()
|
|||
void PartTest::testFullScreenRequest()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
|
||||
// Open file. For this particular file, a dialog has to appear asking whether
|
||||
// one wants to comply with the wish to go to presentation mode directly.
|
||||
|
@ -2037,7 +2077,7 @@ void PartTest::testFullScreenRequest()
|
|||
void PartTest::testZoomInFacingPages()
|
||||
{
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/file2.pdf")));
|
||||
QAction *facingAction = part.m_pageView->findChild<QAction *>(QStringLiteral("view_render_mode_facing"));
|
||||
KSelectAction *zoomSelectAction = part.m_pageView->findChild<KSelectAction *>(QStringLiteral("zoom_to"));
|
||||
|
@ -2065,7 +2105,7 @@ void PartTest::testZoomWithCrop()
|
|||
// We test that all zoom levels can be achieved with cropped pages, bug 342003
|
||||
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/file2.pdf")));
|
||||
|
||||
KActionMenu *cropMenu = part.m_pageView->findChild<KActionMenu *>(QStringLiteral("view_trim_mode"));
|
||||
|
@ -2130,7 +2170,7 @@ void PartTest::testLinkWithCrop()
|
|||
// We test that link targets are correct with cropping, related to bug 198427
|
||||
|
||||
QVariantList dummyArgs;
|
||||
Okular::Part part(nullptr, nullptr, dummyArgs);
|
||||
Okular::Part part(nullptr, dummyArgs);
|
||||
QVERIFY(openDocument(&part, QStringLiteral(KDESRCDIR "data/pdf_with_internal_links.pdf")));
|
||||
|
||||
KActionMenu *cropMenu = part.m_pageView->findChild<KActionMenu *>(QStringLiteral("view_trim_mode"));
|
||||
|
@ -2166,6 +2206,10 @@ void PartTest::testLinkWithCrop()
|
|||
// Trim the page
|
||||
simulateMouseSelection(mouseStartX, mouseStartY, mouseEndX, mouseEndY, part.m_pageView->viewport());
|
||||
|
||||
// We seem to have a trimmed view where we just by sheer luck ends up with mouse over a link at least sometimes
|
||||
// So move the mouse
|
||||
QTest::mouseMove(part.m_pageView->viewport(), QPoint(width * 0.1, width * 0.1));
|
||||
|
||||
// The cursor should be normal again
|
||||
QTRY_COMPARE(part.m_pageView->cursor().shape(), Qt::CursorShape(Qt::OpenHandCursor));
|
||||
|
||||
|
@ -2180,6 +2224,122 @@ void PartTest::testLinkWithCrop()
|
|||
cropAction->trigger();
|
||||
}
|
||||
|
||||
void PartTest::testFieldFormatting()
|
||||
{
|
||||
// Test field formatting. This has to be a parttest so that we
|
||||
// can properly test focus in / out which triggers formatting.
|
||||
const QString testFile = QStringLiteral(KDESRCDIR "data/fieldFormat.pdf");
|
||||
Okular::Part part(nullptr, QVariantList());
|
||||
part.openDocument(testFile);
|
||||
part.widget()->resize(800, 600);
|
||||
|
||||
part.widget()->show();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(part.widget()));
|
||||
|
||||
// Field names in test document are:
|
||||
//
|
||||
// us_currency_fmt for formatting like "$ 1,234.56"
|
||||
// de_currency_fmt for formatting like "1.234,56 €"
|
||||
// de_simple_sum for calculation test and formatting like "1.234,56€"
|
||||
// date_mm_dd_yyyy for dates like "18/06/2018"
|
||||
// date_dd_mm_yyyy for dates like "06/18/2018"
|
||||
// percent_fmt for percent format like "100,00%" if you enter 1
|
||||
// time_HH_MM_fmt for times like "23:12"
|
||||
// time_HH_MM_ss_fmt for times like "23:12:34"
|
||||
// special_phone_number for an example of a special format selectable in Acrobat.
|
||||
QMap<QString, Okular::FormField *> fields;
|
||||
const Okular::Page *page = part.m_document->page(0);
|
||||
const auto formFields = page->formFields();
|
||||
for (Okular::FormField *ff : formFields) {
|
||||
fields.insert(ff->name(), static_cast<Okular::FormField *>(ff));
|
||||
}
|
||||
|
||||
const int width = part.m_pageView->horizontalScrollBar()->maximum() + part.m_pageView->viewport()->width();
|
||||
const int height = part.m_pageView->verticalScrollBar()->maximum() + part.m_pageView->viewport()->height();
|
||||
|
||||
part.m_document->setViewportPage(0);
|
||||
|
||||
// wait for pixmap
|
||||
QTRY_VERIFY(part.m_document->page(0)->hasPixmap(part.m_pageView));
|
||||
|
||||
part.actionCollection()->action(QStringLiteral("view_toggle_forms"))->trigger();
|
||||
|
||||
// Note as of version 1.5:
|
||||
// The test document is prepared for future extensions to formatting for dates etc.
|
||||
// Currently we only have the number format to test.
|
||||
const auto ff_us = dynamic_cast<Okular::FormFieldText *>(fields.value(QStringLiteral("us_currency_fmt")));
|
||||
const auto ff_de = dynamic_cast<Okular::FormFieldText *>(fields.value(QStringLiteral("de_currency_fmt")));
|
||||
const auto ff_sum = dynamic_cast<Okular::FormFieldText *>(fields.value(QStringLiteral("de_simple_sum")));
|
||||
|
||||
const QPoint usPos(width * 0.25, height * 0.025);
|
||||
const QPoint dePos(width * 0.25, height * 0.05);
|
||||
const QPoint deSumPos(width * 0.25, height * 0.075);
|
||||
|
||||
const auto viewport = part.m_pageView->viewport();
|
||||
|
||||
QVERIFY(viewport);
|
||||
|
||||
auto usCurrencyWidget = dynamic_cast<QLineEdit *>(viewport->childAt(usPos));
|
||||
auto deCurrencyWidget = dynamic_cast<QLineEdit *>(viewport->childAt(dePos));
|
||||
auto sumCurrencyWidget = dynamic_cast<QLineEdit *>(viewport->childAt(deSumPos));
|
||||
|
||||
// Check that the widgets were found at the right position
|
||||
QVERIFY(usCurrencyWidget);
|
||||
QVERIFY(deCurrencyWidget);
|
||||
QVERIFY(sumCurrencyWidget);
|
||||
|
||||
QTest::mousePress(usCurrencyWidget, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
|
||||
QTRY_VERIFY(usCurrencyWidget->hasFocus());
|
||||
// locale is en_US for this test. Enter a value and check it.
|
||||
usCurrencyWidget->setText(QStringLiteral("1234.56"));
|
||||
// Check that the internal text matches
|
||||
QCOMPARE(ff_us->text(), QStringLiteral("1234.56"));
|
||||
|
||||
// Now move the focus to trigger formatting.
|
||||
QTest::mousePress(deCurrencyWidget, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
|
||||
QTRY_VERIFY(deCurrencyWidget->hasFocus());
|
||||
|
||||
QCOMPARE(usCurrencyWidget->text(), QStringLiteral("$ 1,234.56"));
|
||||
QCOMPARE(ff_us->text(), QStringLiteral("1234.56"));
|
||||
|
||||
// And again with an invalid number
|
||||
QTest::mousePress(usCurrencyWidget, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
|
||||
QTRY_VERIFY(usCurrencyWidget->hasFocus());
|
||||
|
||||
usCurrencyWidget->setText(QStringLiteral("131.234,567"));
|
||||
QTest::mousePress(deCurrencyWidget, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
|
||||
QTRY_VERIFY(deCurrencyWidget->hasFocus());
|
||||
// Check that the internal text still contains it.
|
||||
QCOMPARE(ff_us->text(), QStringLiteral("131.234,567"));
|
||||
|
||||
// Just check that the text does not match the internal text.
|
||||
// We don't check for a concrete value to keep NaN handling flexible
|
||||
QVERIFY(ff_us->text() != usCurrencyWidget->text());
|
||||
|
||||
// Move the focus back and modify it a bit more
|
||||
QTest::mousePress(usCurrencyWidget, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
|
||||
QTRY_VERIFY(usCurrencyWidget->hasFocus());
|
||||
|
||||
usCurrencyWidget->setText(QStringLiteral("1,234.567"));
|
||||
QTest::mousePress(deCurrencyWidget, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
|
||||
QTRY_VERIFY(deCurrencyWidget->hasFocus());
|
||||
|
||||
QCOMPARE(usCurrencyWidget->text(), QStringLiteral("$ 1,234.57"));
|
||||
|
||||
// Sum should already match
|
||||
QCOMPARE(sumCurrencyWidget->text(), QStringLiteral("1.234,57€"));
|
||||
|
||||
// Set a text in the de field
|
||||
deCurrencyWidget->setText(QStringLiteral("1,123,234.567"));
|
||||
QTest::mousePress(usCurrencyWidget, Qt::LeftButton, Qt::NoModifier, QPoint(5, 5));
|
||||
QTRY_VERIFY(usCurrencyWidget->hasFocus());
|
||||
|
||||
QCOMPARE(deCurrencyWidget->text(), QStringLiteral("1.123.234,57 €"));
|
||||
QCOMPARE(ff_de->text(), QStringLiteral("1,123,234.567"));
|
||||
QCOMPARE(sumCurrencyWidget->text(), QStringLiteral("1.124.469,13€"));
|
||||
QCOMPARE(ff_sum->text(), QStringLiteral("1,124,469.1340000000782310962677002"));
|
||||
}
|
||||
|
||||
} // namespace Okular
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
@ -2200,8 +2360,8 @@ int main(int argc, char *argv[])
|
|||
qDebug() << homePath;
|
||||
qputenv("USERPROFILE", homePath);
|
||||
qputenv("HOME", homePath);
|
||||
qputenv("XDG_DATA_HOME", homePath + "/.local");
|
||||
qputenv("XDG_CONFIG_HOME", homePath + "/.kde-unit-test/xdg/config");
|
||||
qputenv("XDG_DATA_HOME", QByteArray(homePath + "/.local"));
|
||||
qputenv("XDG_CONFIG_HOME", QByteArray(homePath + "/.kde-unit-test/xdg/config"));
|
||||
|
||||
// Disable fancy debug output
|
||||
qunsetenv("QT_MESSAGE_PATTERN");
|
||||
|
|
|
@ -62,7 +62,7 @@ static void createTextPage(const QVector<QString> &text, const QVector<Okular::N
|
|||
{
|
||||
tp = new Okular::TextPage();
|
||||
for (int i = 0; i < text.size(); i++) {
|
||||
tp->append(text[i], new Okular::NormalizedRect(rect[i]));
|
||||
tp->append(text[i], rect[i]);
|
||||
}
|
||||
|
||||
// The Page::setTextPage method invokes the layout analysis algorithms tested by some tests here
|
||||
|
|
|
@ -88,35 +88,32 @@ void SignUnsignedFieldTest::testSignUnsignedField()
|
|||
QCOMPARE(forms.count(), 1);
|
||||
Okular::FormFieldSignature *ffs = dynamic_cast<Okular::FormFieldSignature *>(forms.first());
|
||||
|
||||
// This is a hacky way of doing ifdef HAVE_POPPLER_22_02
|
||||
if (m_document->metaData(QStringLiteral("CanSignDocumentWithPassword")).toString() == QLatin1String("yes")) {
|
||||
QCOMPARE(ffs->signatureType(), Okular::FormFieldSignature::UnsignedSignature);
|
||||
QCOMPARE(ffs->signatureType(), Okular::FormFieldSignature::UnsignedSignature);
|
||||
|
||||
const Okular::CertificateStore *certStore = m_document->certificateStore();
|
||||
bool userCancelled, nonDateValidCerts;
|
||||
{
|
||||
EnterPasswordDialogHelper helper;
|
||||
const QList<Okular::CertificateInfo *> &certs = certStore->signingCertificatesForNow(&userCancelled, &nonDateValidCerts);
|
||||
QCOMPARE(certs.count(), 1);
|
||||
}
|
||||
|
||||
Okular::NewSignatureData data;
|
||||
data.setCertNickname(QStringLiteral("fake-okular"));
|
||||
QTemporaryFile f;
|
||||
f.open();
|
||||
QVERIFY(ffs->sign(data, f.fileName()));
|
||||
|
||||
m_document->closeDocument();
|
||||
QMimeDatabase db;
|
||||
const QMimeType mime = db.mimeTypeForFile(f.fileName());
|
||||
QCOMPARE(m_document->openDocument(f.fileName(), QUrl(), mime), Okular::Document::OpenSuccess);
|
||||
|
||||
const QList<Okular::FormField *> newForms = m_document->page(0)->formFields();
|
||||
QCOMPARE(newForms.count(), 1);
|
||||
ffs = dynamic_cast<Okular::FormFieldSignature *>(newForms.first());
|
||||
QCOMPARE(ffs->signatureType(), Okular::FormFieldSignature::AdbePkcs7detached);
|
||||
QCOMPARE(ffs->signatureInfo().signerName(), QStringLiteral("FakeOkular"));
|
||||
const Okular::CertificateStore *certStore = m_document->certificateStore();
|
||||
bool userCancelled, nonDateValidCerts;
|
||||
{
|
||||
EnterPasswordDialogHelper helper;
|
||||
const QList<Okular::CertificateInfo> &certs = certStore->signingCertificatesForNow(&userCancelled, &nonDateValidCerts);
|
||||
QCOMPARE(certs.count(), 1);
|
||||
}
|
||||
|
||||
Okular::NewSignatureData data;
|
||||
data.setCertNickname(QStringLiteral("fake-okular"));
|
||||
QTemporaryFile f;
|
||||
f.open();
|
||||
QVERIFY(ffs->sign(data, f.fileName()));
|
||||
|
||||
m_document->closeDocument();
|
||||
QMimeDatabase db;
|
||||
const QMimeType mime = db.mimeTypeForFile(f.fileName());
|
||||
QCOMPARE(m_document->openDocument(f.fileName(), QUrl(), mime), Okular::Document::OpenSuccess);
|
||||
|
||||
const QList<Okular::FormField *> newForms = m_document->page(0)->formFields();
|
||||
QCOMPARE(newForms.count(), 1);
|
||||
ffs = dynamic_cast<Okular::FormFieldSignature *>(newForms.first());
|
||||
QCOMPARE(ffs->signatureType(), Okular::FormFieldSignature::AdbePkcs7detached);
|
||||
QCOMPARE(ffs->signatureInfo().signerName(), QStringLiteral("FakeOkular"));
|
||||
}
|
||||
|
||||
QTEST_MAIN(SignUnsignedFieldTest)
|
||||
|
|
53
autotests/suggestedfilenametest.cpp
Normal file
53
autotests/suggestedfilenametest.cpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2023 g10 Code GmbH
|
||||
SPDX-FileContributor: Sune Stolborg Vuorela <sune@vuorela.dk>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#include <QTest>
|
||||
|
||||
#include "../part/signaturepartutils.h"
|
||||
|
||||
class SuggestedFileNameTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void testSuggestedSignedDocumentName();
|
||||
void testSuggestedSignedDocumentName_data();
|
||||
};
|
||||
|
||||
void SuggestedFileNameTest::initTestCase()
|
||||
{
|
||||
qputenv("LC_ALL", "en_US.UTF-8");
|
||||
}
|
||||
|
||||
void SuggestedFileNameTest::testSuggestedSignedDocumentName()
|
||||
{
|
||||
QFETCH(QString, input);
|
||||
QFETCH(QString, preferredSuffix);
|
||||
QFETCH(QString, expected);
|
||||
|
||||
auto output = SignaturePartUtils::getSuggestedFileNameForSignedFile(input, preferredSuffix);
|
||||
QCOMPARE(output, expected);
|
||||
}
|
||||
|
||||
void SuggestedFileNameTest::testSuggestedSignedDocumentName_data()
|
||||
{
|
||||
QTest::addColumn<QString>("input");
|
||||
QTest::addColumn<QString>("preferredSuffix"); // normally derived from mimetype of document
|
||||
QTest::addColumn<QString>("expected");
|
||||
|
||||
QTest::newRow("simple") << QStringLiteral("foo.pdf") << QStringLiteral("pdf") << QStringLiteral("foo_signed.pdf");
|
||||
QTest::newRow("double extensions") << QStringLiteral("foo.pdf.gz") << QStringLiteral("pdf") << QStringLiteral("foo_signed.pdf"); // while we might read compressed files, we don't write them out
|
||||
QTest::newRow("versioning") << QStringLiteral("foo-1.2.3.pdf") << QStringLiteral("pdf") << QStringLiteral("foo-1.2.3_signed.pdf");
|
||||
QTest::newRow("versioned and double extensions") << QStringLiteral("foo-1.2.3.pdf.gz") << QStringLiteral("pdf") << QStringLiteral("foo-1.2.3_signed.pdf");
|
||||
QTest::newRow("gif") << QStringLiteral("foo.gif") << QStringLiteral("pdf") << QStringLiteral("foo_signed.pdf");
|
||||
QTest::newRow("version gif") << QStringLiteral("foo-1.2.3.gif") << QStringLiteral("pdf") << QStringLiteral("foo-1.2.3_signed.pdf");
|
||||
QTest::newRow("no extension") << QStringLiteral("foo") << QStringLiteral("pdf") << QStringLiteral("foo_signed.pdf");
|
||||
QTest::newRow("no extension with versions") << QStringLiteral("foo-1.2.3") << QStringLiteral("pdf") << QStringLiteral("foo-1.2_signed.pdf"); // This is not as such expected behavior but more a documentation of implementation.
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(SuggestedFileNameTest)
|
||||
|
||||
#include "suggestedfilenametest.moc"
|
|
@ -7,6 +7,8 @@
|
|||
#include "testingutils.h"
|
||||
#include "core/annotations.h"
|
||||
|
||||
#include <QIODevice>
|
||||
|
||||
namespace TestingUtils
|
||||
{
|
||||
QString getAnnotationXml(const Okular::Annotation *annotation)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <QtTest>
|
||||
#include <QTest>
|
||||
|
||||
#include "../part/toggleactionmenu.h"
|
||||
#include <QToolBar>
|
||||
|
|
|
@ -4,13 +4,14 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include <QtTest>
|
||||
#include <QTest>
|
||||
|
||||
#include "../settings_core.h"
|
||||
#include "core/document.h"
|
||||
#include <QMap>
|
||||
#include <QMimeDatabase>
|
||||
#include <QMimeType>
|
||||
#include <QTemporaryFile>
|
||||
#include <core/form.h>
|
||||
#include <core/page.h>
|
||||
|
||||
|
|
|
@ -325,6 +325,9 @@
|
|||
<default>true</default>
|
||||
<emit signal="viewContinuousChanged" />
|
||||
</entry>
|
||||
<entry key="DragBeyondScreenEdges" type="Bool" >
|
||||
<default>true</default>
|
||||
</entry>
|
||||
<entry key="PrimaryAnnotationToolBar" type="Enum" >
|
||||
<default>FullAnnotationToolBar</default>
|
||||
<choices>
|
||||
|
|
|
@ -2,7 +2,25 @@
|
|||
#define OKULAR_FORCE_DRM ${_OKULAR_FORCE_DRM}
|
||||
|
||||
/* Defines if the purpose framework is available */
|
||||
#define PURPOSE_FOUND ${PURPOSE_FOUND}
|
||||
#cmakedefine01 HAVE_PURPOSE
|
||||
|
||||
/* Defines if qtspeech is available */
|
||||
#cmakedefine01 HAVE_SPEECH
|
||||
|
||||
/* Defines if kwallet is available */
|
||||
#cmakedefine01 HAVE_KWALLET
|
||||
|
||||
/* Defines if QJSEngine is available*/
|
||||
#cmakedefine01 HAVE_JS
|
||||
|
||||
/* Defines whether the malloc_trim method from malloc.h is available */
|
||||
#cmakedefine01 HAVE_MALLOC_TRIM
|
||||
|
||||
/* Defines whether we are building with X11 support */
|
||||
#cmakedefine01 HAVE_X11
|
||||
|
||||
/* Defines wheter we are building with Phonon support */
|
||||
#cmakedefine01 HAVE_PHONON
|
||||
|
||||
/* Defines whether we are building with dbus enabled */
|
||||
#cmakedefine01 HAVE_DBUS
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
// qt/kde includes
|
||||
#include <QApplication>
|
||||
#include <QColor>
|
||||
#include <QFile>
|
||||
#include <QIcon>
|
||||
#include <QPainter>
|
||||
#include <QStandardPaths>
|
||||
|
@ -46,12 +47,11 @@ static bool isLeftOfVector(const NormalizedPoint &a, const NormalizedPoint &b, c
|
|||
static double distanceSqr(double x, double y, double xScale, double yScale, const QList<NormalizedPoint> &path)
|
||||
{
|
||||
double distance = DBL_MAX;
|
||||
double thisDistance;
|
||||
QList<NormalizedPoint>::const_iterator i = path.constBegin();
|
||||
NormalizedPoint lastPoint = *i;
|
||||
|
||||
for (++i; i != path.constEnd(); ++i) {
|
||||
thisDistance = NormalizedPoint::distanceSqr(x, y, xScale, yScale, lastPoint, (*i));
|
||||
double thisDistance = NormalizedPoint::distanceSqr(x, y, xScale, yScale, lastPoint, (*i));
|
||||
|
||||
if (thisDistance < distance) {
|
||||
distance = thisDistance;
|
||||
|
@ -154,7 +154,7 @@ QDomElement AnnotationUtils::findChildElement(const QDomNode &parentNode, const
|
|||
QRect AnnotationUtils::annotationGeometry(const Annotation *annotation, double scaleX, double scaleY)
|
||||
{
|
||||
const QRect rect = annotation->transformedBoundingRectangle().geometry((int)scaleX, (int)scaleY);
|
||||
if (annotation->subType() == Annotation::AText && (((TextAnnotation *)annotation)->textType() == TextAnnotation::Linked)) {
|
||||
if (annotation->subType() == Annotation::AText && (static_cast<const TextAnnotation *>(annotation)->textType() == TextAnnotation::Linked)) {
|
||||
// To be honest i have no clue of why the 24,24 is here, maybe to make sure it's not too small?
|
||||
// But why only for linked text?
|
||||
const QRect rect24 = QRect((int)(annotation->transformedBoundingRectangle().left * scaleX), (int)(annotation->transformedBoundingRectangle().top * scaleY), 24, 24);
|
||||
|
@ -192,11 +192,16 @@ QPixmap AnnotationUtils::loadStamp(const QString &nameOrPath, int size, bool kee
|
|||
}
|
||||
|
||||
// _name is a path (do this before loading as icon name to avoid some rare weirdness )
|
||||
QPixmap pixmap;
|
||||
pixmap.load(nameOrPath);
|
||||
if (!pixmap.isNull()) {
|
||||
pixmap = pixmap.scaled(size, size, keepAspectRatio ? Qt::KeepAspectRatioByExpanding : Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
return pixmap;
|
||||
// Check that it exists up front. While pixmap.load() fails, if it is
|
||||
// actually an icon from theme, the loader will try all supported
|
||||
// extensions in current workdir before failing
|
||||
if (QFile::exists(nameOrPath)) {
|
||||
QPixmap pixmap;
|
||||
pixmap.load(nameOrPath);
|
||||
if (!pixmap.isNull()) {
|
||||
pixmap = pixmap.scaled(size, size, keepAspectRatio ? Qt::KeepAspectRatioByExpanding : Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
return pixmap;
|
||||
}
|
||||
}
|
||||
|
||||
// _name is an icon name
|
||||
|
@ -554,7 +559,7 @@ AnnotationPrivate::~AnnotationPrivate()
|
|||
return;
|
||||
}
|
||||
|
||||
for (const Annotation::Revision &revision : qAsConst(m_revisions)) {
|
||||
for (const Annotation::Revision &revision : std::as_const(m_revisions)) {
|
||||
delete revision.annotation();
|
||||
}
|
||||
}
|
||||
|
@ -869,7 +874,7 @@ void Annotation::store(QDomNode &annNode, QDomDocument &document) const
|
|||
}
|
||||
|
||||
// add all revisions as children of revisions element
|
||||
for (const Revision &revision : qAsConst(d->m_revisions)) {
|
||||
for (const Revision &revision : std::as_const(d->m_revisions)) {
|
||||
// create revision element
|
||||
QDomElement r = document.createElement(QStringLiteral("revision"));
|
||||
annNode.appendChild(r);
|
||||
|
@ -1602,7 +1607,7 @@ void LineAnnotation::store(QDomNode &node, QDomDocument &document) const
|
|||
lineElement.appendChild(pElement);
|
||||
pElement.setAttribute(QStringLiteral("x"), QString::number(p.x));
|
||||
pElement.setAttribute(QStringLiteral("y"), QString::number(p.y));
|
||||
it++; // to avoid loop
|
||||
++it; // to avoid loop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1723,7 +1728,7 @@ double LineAnnotationPrivate::distanceSqr(double x, double y, double xScale, dou
|
|||
|
||||
if (m_lineInnerColor.isValid()) {
|
||||
QPolygonF polygon;
|
||||
for (const NormalizedPoint &p : qAsConst(transformedLinePoints)) {
|
||||
for (const NormalizedPoint &p : std::as_const(transformedLinePoints)) {
|
||||
polygon.append(QPointF(p.x, p.y));
|
||||
}
|
||||
|
||||
|
@ -1930,6 +1935,9 @@ class HighlightAnnotation::Quad::Private
|
|||
{
|
||||
public:
|
||||
Private()
|
||||
: m_capStart(false)
|
||||
, m_capEnd(false)
|
||||
, m_feather(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -243,6 +243,13 @@ QRect NormalizedRect::roundedGeometry(int xScale, int yScale) const
|
|||
return QRect(l, t, r - l + 1, b - t + 1);
|
||||
}
|
||||
|
||||
QRectF NormalizedRect::geometryF(float xScale, float yScale) const
|
||||
{
|
||||
float l = (left * xScale), t = (top * yScale), r = (right * xScale), b = (bottom * yScale);
|
||||
|
||||
return QRectF(l, t, r - l, b - t);
|
||||
}
|
||||
|
||||
void NormalizedRect::transform(const QTransform &matrix)
|
||||
{
|
||||
QRectF rect(left, top, right - left, bottom - top);
|
||||
|
@ -254,9 +261,9 @@ void NormalizedRect::transform(const QTransform &matrix)
|
|||
bottom = rect.bottom();
|
||||
}
|
||||
|
||||
uint Okular::qHash(const NormalizedRect &r, uint seed)
|
||||
size_t Okular::qHash(const NormalizedRect &r, size_t seed)
|
||||
{
|
||||
return ::qHash(r.bottom, ::qHash(r.right, ::qHash(r.top, ::qHash(r.left, seed))));
|
||||
return ::qHashMulti(seed, r.bottom, r.right, r.top, r.left);
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug str, const Okular::NormalizedRect &r)
|
||||
|
|
|
@ -282,6 +282,11 @@ public:
|
|||
*/
|
||||
QRect roundedGeometry(int xScale, int yScale) const;
|
||||
|
||||
/**
|
||||
* Same functionality as geometry, but nothing is converted into int.
|
||||
*/
|
||||
QRectF geometryF(float xScale, float yScale) const;
|
||||
|
||||
/**
|
||||
* Returns the normalized bounding rectangle of the normalized rectangle
|
||||
* combined with the @p other normalized rectangle.
|
||||
|
@ -962,7 +967,7 @@ public:
|
|||
QColor color;
|
||||
};
|
||||
|
||||
uint qHash(const Okular::NormalizedRect &r, uint seed = 0);
|
||||
size_t qHash(const Okular::NormalizedRect &r, size_t seed = 0);
|
||||
}
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
|
|
|
@ -5,25 +5,60 @@
|
|||
*/
|
||||
|
||||
#include "audioplayer.h"
|
||||
#include "audioplayer_p.h"
|
||||
|
||||
// qt/kde includes
|
||||
#include <KRandom>
|
||||
#include <KLocalizedString>
|
||||
#include <QBuffer>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QRandomGenerator>
|
||||
|
||||
#include "config-okular.h"
|
||||
|
||||
#if HAVE_PHONON
|
||||
#include <phonon/abstractmediastream.h>
|
||||
#include <phonon/audiooutput.h>
|
||||
#include <phonon/mediaobject.h>
|
||||
#include <phonon/path.h>
|
||||
#endif
|
||||
|
||||
// local includes
|
||||
#include "action.h"
|
||||
#include "debug_p.h"
|
||||
#include "document.h"
|
||||
#include "sound.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
#if HAVE_PHONON
|
||||
|
||||
class PlayData;
|
||||
class SoundInfo;
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class AudioPlayerPrivate
|
||||
{
|
||||
public:
|
||||
explicit AudioPlayerPrivate(AudioPlayer *qq);
|
||||
|
||||
~AudioPlayerPrivate();
|
||||
|
||||
int newId() const;
|
||||
bool play(const SoundInfo &si);
|
||||
void stopPlayings();
|
||||
|
||||
void finished(int);
|
||||
|
||||
AudioPlayer *q;
|
||||
|
||||
QHash<int, PlayData *> m_playing;
|
||||
QUrl m_currentDocument;
|
||||
AudioPlayer::State m_state;
|
||||
};
|
||||
}
|
||||
|
||||
// helper class used to store info about a sound to be played
|
||||
class SoundInfo
|
||||
{
|
||||
|
@ -98,11 +133,12 @@ AudioPlayerPrivate::~AudioPlayerPrivate()
|
|||
|
||||
int AudioPlayerPrivate::newId() const
|
||||
{
|
||||
auto random = QRandomGenerator::global();
|
||||
int newid = 0;
|
||||
QHash<int, PlayData *>::const_iterator it;
|
||||
QHash<int, PlayData *>::const_iterator itEnd = m_playing.constEnd();
|
||||
do {
|
||||
newid = KRandom::random();
|
||||
newid = random->bounded(RAND_MAX);
|
||||
it = m_playing.constFind(newid);
|
||||
} while (it != itEnd);
|
||||
return newid;
|
||||
|
@ -126,13 +162,7 @@ bool AudioPlayerPrivate::play(const SoundInfo &si)
|
|||
if (!url.isEmpty()) {
|
||||
int newid = newId();
|
||||
QObject::connect(data->m_mediaobject, &Phonon::MediaObject::finished, q, [this, newid]() { finished(newid); });
|
||||
QUrl newurl;
|
||||
if (QUrl::fromUserInput(url).isRelative()) {
|
||||
newurl = m_currentDocument.adjusted(QUrl::RemoveFilename);
|
||||
newurl.setPath(newurl.path() + url);
|
||||
} else {
|
||||
newurl = QUrl::fromLocalFile(url);
|
||||
}
|
||||
const QUrl newurl = QUrl::fromUserInput(url, m_currentDocument.adjusted(QUrl::RemoveFilename).toLocalFile());
|
||||
data->m_mediaobject->setCurrentSource(newurl);
|
||||
m_playing.insert(newid, data);
|
||||
valid = true;
|
||||
|
@ -245,4 +275,70 @@ AudioPlayer::State AudioPlayer::state() const
|
|||
return d->m_state;
|
||||
}
|
||||
|
||||
void AudioPlayer::resetDocument()
|
||||
{
|
||||
d->m_currentDocument = {};
|
||||
}
|
||||
|
||||
void AudioPlayer::setDocument(const QUrl &url, Okular::Document *document)
|
||||
{
|
||||
Q_UNUSED(document);
|
||||
d->m_currentDocument = url;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class AudioPlayerPrivate
|
||||
{
|
||||
public:
|
||||
Document *document;
|
||||
};
|
||||
}
|
||||
|
||||
AudioPlayer::AudioPlayer()
|
||||
: d(new AudioPlayerPrivate())
|
||||
{
|
||||
}
|
||||
|
||||
AudioPlayer *AudioPlayer::instance()
|
||||
{
|
||||
static AudioPlayer ap;
|
||||
return ≈
|
||||
}
|
||||
|
||||
void AudioPlayer::playSound(const Sound *sound, const SoundAction *linksound)
|
||||
{
|
||||
Q_UNUSED(sound);
|
||||
Q_UNUSED(linksound);
|
||||
Q_EMIT d->document->warning(i18n("This Okular is built without audio support"), 2000);
|
||||
}
|
||||
|
||||
AudioPlayer::State Okular::AudioPlayer::state() const
|
||||
{
|
||||
return State::StoppedState;
|
||||
}
|
||||
|
||||
void AudioPlayer::stopPlaybacks()
|
||||
{
|
||||
}
|
||||
|
||||
AudioPlayer::~AudioPlayer() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
void AudioPlayer::resetDocument()
|
||||
{
|
||||
d->document = nullptr;
|
||||
}
|
||||
|
||||
void AudioPlayer::setDocument(const QUrl &url, Okular::Document *document)
|
||||
{
|
||||
Q_UNUSED(url);
|
||||
d->document = document;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#include "moc_audioplayer.cpp"
|
||||
|
|
|
@ -70,6 +70,8 @@ public:
|
|||
|
||||
private:
|
||||
AudioPlayer();
|
||||
void resetDocument();
|
||||
void setDocument(const QUrl &url, Document *document);
|
||||
|
||||
friend class AudioPlayerPrivate;
|
||||
AudioPlayerPrivate *const d;
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2007 Pino Toscano <pino@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef _OKULAR_AUDIOPLAYER_P_H_
|
||||
#define _OKULAR_AUDIOPLAYER_P_H_
|
||||
|
||||
// qt/kde includes
|
||||
#include <QHash>
|
||||
#include <QUrl>
|
||||
|
||||
class PlayData;
|
||||
class SoundInfo;
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class AudioPlayer;
|
||||
|
||||
class AudioPlayerPrivate
|
||||
{
|
||||
public:
|
||||
explicit AudioPlayerPrivate(AudioPlayer *qq);
|
||||
|
||||
~AudioPlayerPrivate();
|
||||
|
||||
int newId() const;
|
||||
bool play(const SoundInfo &si);
|
||||
void stopPlayings();
|
||||
|
||||
void finished(int);
|
||||
|
||||
AudioPlayer *q;
|
||||
|
||||
QHash<int, PlayData *> m_playing;
|
||||
QUrl m_currentDocument;
|
||||
AudioPlayer::State m_state;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -10,6 +10,7 @@
|
|||
#include <KBookmarkAction>
|
||||
#include <KBookmarkManager>
|
||||
#include <KBookmarkMenu>
|
||||
#include <KBookmarkOwner>
|
||||
#include <QDebug>
|
||||
#include <QFileInfo>
|
||||
#include <QGuiApplication>
|
||||
|
@ -117,7 +118,8 @@ public:
|
|||
: KBookmarkOwner()
|
||||
, q(qq)
|
||||
, document(nullptr)
|
||||
, manager(nullptr)
|
||||
, file(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/okular/bookmarks.xml"))
|
||||
, manager(KBookmarkManager(file))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -139,14 +141,14 @@ public:
|
|||
QHash<QUrl, QString>::iterator bookmarkFind(const QUrl &url, bool doCreate, KBookmarkGroup *result = nullptr);
|
||||
|
||||
// slots
|
||||
void _o_changed(const QString &groupAddress, const QString &caller);
|
||||
void _o_changed(const QString &groupAddress);
|
||||
|
||||
BookmarkManager *q;
|
||||
QUrl url;
|
||||
QHash<int, int> urlBookmarks;
|
||||
DocumentPrivate *document;
|
||||
QString file;
|
||||
KBookmarkManager *manager;
|
||||
KBookmarkManager manager;
|
||||
QHash<QUrl, QString> knownFiles;
|
||||
};
|
||||
|
||||
|
@ -167,12 +169,7 @@ BookmarkManager::BookmarkManager(DocumentPrivate *document)
|
|||
|
||||
d->document = document;
|
||||
|
||||
d->file = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/okular/bookmarks.xml");
|
||||
|
||||
d->manager = KBookmarkManager::managerForFile(d->file, QStringLiteral("okular"));
|
||||
d->manager->setEditorOptions(QGuiApplication::applicationDisplayName(), false);
|
||||
d->manager->setUpdate(true);
|
||||
connect(d->manager, &KBookmarkManager::changed, this, [this](const QString &groupAddress, const QString &caller) { d->_o_changed(groupAddress, caller); });
|
||||
connect(&d->manager, &KBookmarkManager::changed, this, [this](const QString &groupAddress) { d->_o_changed(groupAddress); });
|
||||
}
|
||||
|
||||
BookmarkManager::~BookmarkManager()
|
||||
|
@ -203,9 +200,8 @@ void BookmarkManager::Private::openBookmark(const KBookmark &bm, Qt::MouseButton
|
|||
}
|
||||
// END Reimplementations from KBookmarkOwner
|
||||
|
||||
void BookmarkManager::Private::_o_changed(const QString &groupAddress, const QString &caller)
|
||||
void BookmarkManager::Private::_o_changed(const QString &groupAddress)
|
||||
{
|
||||
Q_UNUSED(caller);
|
||||
if (groupAddress.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
@ -221,7 +217,7 @@ void BookmarkManager::Private::_o_changed(const QString &groupAddress, const QSt
|
|||
}
|
||||
}
|
||||
if (!referurl.isValid()) {
|
||||
const KBookmark bm = manager->findByAddress(groupAddress);
|
||||
const KBookmark bm = manager.findByAddress(groupAddress);
|
||||
// better be safe than sorry
|
||||
if (bm.isNull()) {
|
||||
return;
|
||||
|
@ -257,7 +253,7 @@ void BookmarkManager::Private::_o_changed(const QString &groupAddress, const QSt
|
|||
QList<QUrl> BookmarkManager::files() const
|
||||
{
|
||||
QList<QUrl> ret;
|
||||
KBookmarkGroup group = d->manager->root();
|
||||
KBookmarkGroup group = d->manager.root();
|
||||
for (KBookmark bm = group.first(); !bm.isNull(); bm = group.next(bm)) {
|
||||
if (bm.isSeparator() || !bm.isGroup()) {
|
||||
continue;
|
||||
|
@ -272,7 +268,7 @@ KBookmark::List BookmarkManager::bookmarks(const QUrl &documentUrl) const
|
|||
{
|
||||
const QUrl url = mostCanonicalUrl(documentUrl);
|
||||
KBookmark::List ret;
|
||||
KBookmarkGroup group = d->manager->root();
|
||||
KBookmarkGroup group = d->manager.root();
|
||||
for (KBookmark bm = group.first(); !bm.isNull(); bm = group.next(bm)) {
|
||||
if (!bm.isGroup() || urlForGroup(bm) != url) {
|
||||
continue;
|
||||
|
@ -351,7 +347,7 @@ KBookmark BookmarkManager::bookmark(const DocumentViewport &viewport) const
|
|||
|
||||
void BookmarkManager::save() const
|
||||
{
|
||||
d->manager->emitChanged();
|
||||
d->manager.emitChanged();
|
||||
Q_EMIT const_cast<BookmarkManager *>(this)->saved();
|
||||
}
|
||||
|
||||
|
@ -363,7 +359,7 @@ QHash<QUrl, QString>::iterator BookmarkManager::Private::bookmarkFind(const QUrl
|
|||
// known files, then first try to find the file among the top-level
|
||||
// "folder" names
|
||||
bool found = false;
|
||||
KBookmarkGroup root = manager->root();
|
||||
KBookmarkGroup root = manager.root();
|
||||
for (KBookmark bm = root.first(); !found && !bm.isNull(); bm = root.next(bm)) {
|
||||
if (bm.isSeparator() || !bm.isGroup()) {
|
||||
continue;
|
||||
|
@ -393,7 +389,7 @@ QHash<QUrl, QString>::iterator BookmarkManager::Private::bookmarkFind(const QUrl
|
|||
}
|
||||
}
|
||||
} else if (result) {
|
||||
const KBookmark bm = manager->findByAddress(it.value());
|
||||
const KBookmark bm = manager.findByAddress(it.value());
|
||||
Q_ASSERT(bm.isGroup());
|
||||
*result = bm.toGroup();
|
||||
}
|
||||
|
@ -473,7 +469,7 @@ bool BookmarkManager::addBookmark(const QUrl &documentUrl, const Okular::Documen
|
|||
d->urlBookmarks[vp.pageNumber]++;
|
||||
foreachObserver(notifyPageChanged(vp.pageNumber, DocumentObserver::Bookmark));
|
||||
}
|
||||
d->manager->emitChanged(thebg);
|
||||
d->manager.emitChanged(thebg);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -503,7 +499,7 @@ void BookmarkManager::renameBookmark(KBookmark *bm, const QString &newName)
|
|||
}
|
||||
|
||||
bm->setFullText(newName);
|
||||
d->manager->emitChanged(thebg);
|
||||
d->manager.emitChanged(thebg);
|
||||
}
|
||||
|
||||
void BookmarkManager::renameBookmark(const QUrl &documentUrl, const QString &newName)
|
||||
|
@ -522,7 +518,7 @@ void BookmarkManager::renameBookmark(const QUrl &documentUrl, const QString &new
|
|||
}
|
||||
|
||||
thebg.setFullText(newName);
|
||||
d->manager->emitChanged(thebg);
|
||||
d->manager.emitChanged(thebg);
|
||||
}
|
||||
|
||||
QString BookmarkManager::titleForUrl(const QUrl &documentUrl) const
|
||||
|
@ -559,7 +555,7 @@ int BookmarkManager::removeBookmark(const QUrl &documentUrl, const KBookmark &bm
|
|||
d->urlBookmarks[vp.pageNumber]--;
|
||||
foreachObserver(notifyPageChanged(vp.pageNumber, DocumentObserver::Bookmark));
|
||||
}
|
||||
d->manager->emitChanged(thebg);
|
||||
d->manager.emitChanged(thebg);
|
||||
|
||||
return vp.pageNumber;
|
||||
}
|
||||
|
@ -605,7 +601,7 @@ void BookmarkManager::removeBookmarks(const QUrl &documentUrl, const KBookmark::
|
|||
}
|
||||
}
|
||||
if (deletedAny) {
|
||||
d->manager->emitChanged(thebg);
|
||||
d->manager.emitChanged(thebg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -613,7 +609,7 @@ QList<QAction *> BookmarkManager::actionsForUrl(const QUrl &documentUrl) const
|
|||
{
|
||||
const QUrl url = mostCanonicalUrl(documentUrl);
|
||||
QList<QAction *> ret;
|
||||
KBookmarkGroup group = d->manager->root();
|
||||
KBookmarkGroup group = d->manager.root();
|
||||
for (KBookmark bm = group.first(); !bm.isNull(); bm = group.next(bm)) {
|
||||
if (!bm.isGroup() || urlForGroup(bm) != url) {
|
||||
continue;
|
||||
|
@ -681,7 +677,7 @@ bool BookmarkManager::setPageBookmark(int page)
|
|||
newurl.setFragment(vp.toString(), QUrl::DecodedMode);
|
||||
thebg.addBookmark(QLatin1String("#") + QString::number(vp.pageNumber + 1), newurl, QString());
|
||||
added = true;
|
||||
d->manager->emitChanged(thebg);
|
||||
d->manager.emitChanged(thebg);
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
@ -705,7 +701,7 @@ bool BookmarkManager::removePageBookmark(int page)
|
|||
found = true;
|
||||
thebg.deleteBookmark(bm);
|
||||
d->urlBookmarks[page]--;
|
||||
d->manager->emitChanged(thebg);
|
||||
d->manager.emitChanged(thebg);
|
||||
}
|
||||
}
|
||||
return found;
|
||||
|
@ -729,7 +725,7 @@ KBookmark BookmarkManager::nextBookmark(const DocumentViewport &viewport) const
|
|||
std::sort(bmarks.begin(), bmarks.end(), bookmarkLessThan);
|
||||
|
||||
KBookmark bookmark;
|
||||
for (const KBookmark &bm : qAsConst(bmarks)) {
|
||||
for (const KBookmark &bm : std::as_const(bmarks)) {
|
||||
DocumentViewport vp(bm.url().fragment(QUrl::FullyDecoded));
|
||||
if (viewport < vp) {
|
||||
bookmark = bm;
|
||||
|
|
|
@ -47,20 +47,21 @@
|
|||
#include <QUndoCommand>
|
||||
#include <QWindow>
|
||||
#include <QtAlgorithms>
|
||||
#include <private/qstringiterator_p.h>
|
||||
|
||||
#include <KApplicationTrader>
|
||||
#include <KAuthorized>
|
||||
#include <KConfigDialog>
|
||||
#include <KFormat>
|
||||
#include <KIO/Global>
|
||||
#include <KIO/JobUiDelegate>
|
||||
#include <KIO/JobUiDelegateFactory>
|
||||
#include <KIO/OpenUrlJob>
|
||||
#include <KLocalizedString>
|
||||
#include <KMacroExpander>
|
||||
#include <KPluginMetaData>
|
||||
#include <KProcess>
|
||||
#include <KRun>
|
||||
#include <KShell>
|
||||
#include <Kdelibs4Migration>
|
||||
#include <kio_version.h>
|
||||
#include <kzip.h>
|
||||
|
||||
// local includes
|
||||
|
@ -68,7 +69,6 @@
|
|||
#include "annotations.h"
|
||||
#include "annotations_p.h"
|
||||
#include "audioplayer.h"
|
||||
#include "audioplayer_p.h"
|
||||
#include "bookmarkmanager.h"
|
||||
#include "chooseenginedialog_p.h"
|
||||
#include "debug_p.h"
|
||||
|
@ -164,7 +164,10 @@ struct RunningSearch {
|
|||
#define OKULAR_HISTORY_SAVEDSTEPS 10
|
||||
|
||||
// how often to run slotTimedMemoryCheck
|
||||
const int kMemCheckTime = 2000; // in msec
|
||||
constexpr int kMemCheckTime = 2000; // in msec
|
||||
// getFreeMemory is called every two seconds when checking to see if the system is low on memory. If this timeout was left at kMemCheckTime, half of these checks are useless (when okular is idle) since the cache is used when the cache is
|
||||
// <=2 seconds old. This means that after the system is out of memory, up to 4 seconds (instead of 2) could go by before okular starts to free memory.
|
||||
constexpr int kFreeMemCacheTimeout = kMemCheckTime - 100;
|
||||
|
||||
/***** Document ******/
|
||||
|
||||
|
@ -213,14 +216,14 @@ QString DocumentPrivate::pagesSizeString() const
|
|||
|
||||
QString DocumentPrivate::namePaperSize(double inchesWidth, double inchesHeight) const
|
||||
{
|
||||
const QPrinter::Orientation orientation = inchesWidth > inchesHeight ? QPrinter::Landscape : QPrinter::Portrait;
|
||||
const QPageLayout::Orientation orientation = inchesWidth > inchesHeight ? QPageLayout::Landscape : QPageLayout::Portrait;
|
||||
|
||||
const QSize pointsSize(inchesWidth * 72.0, inchesHeight * 72.0);
|
||||
const QPageSize::PageSizeId paperSize = QPageSize::id(pointsSize, QPageSize::FuzzyOrientationMatch);
|
||||
|
||||
const QString paperName = QPageSize::name(paperSize);
|
||||
|
||||
if (orientation == QPrinter::Portrait) {
|
||||
if (orientation == QPageLayout::Portrait) {
|
||||
return i18nc("paper type and orientation (eg: Portrait A4)", "Portrait %1", paperName);
|
||||
} else {
|
||||
return i18nc("paper type and orientation (eg: Portrait A4)", "Landscape %1", paperName);
|
||||
|
@ -350,7 +353,7 @@ void DocumentPrivate::cleanupPixmapMemory(qulonglong memoryToFree)
|
|||
std::list<AllocatedPixmap *> pixmapsToKeep;
|
||||
while (memoryToFree > 0) {
|
||||
int clean_hits = 0;
|
||||
for (DocumentObserver *observer : qAsConst(m_observers)) {
|
||||
for (DocumentObserver *observer : std::as_const(m_observers)) {
|
||||
AllocatedPixmap *p = searchLowestPriorityPixmap(false, true, observer);
|
||||
if (!p) { // No pixmap to remove
|
||||
continue;
|
||||
|
@ -390,6 +393,7 @@ void DocumentPrivate::cleanupPixmapMemory(qulonglong memoryToFree)
|
|||
}
|
||||
|
||||
m_allocatedPixmaps.splice(m_allocatedPixmaps.end(), pixmapsToKeep);
|
||||
Q_UNUSED(pagesFreed);
|
||||
// p--rintf("freeMemory A:[%d -%d = %d] \n", m_allocatedPixmaps.count() + pagesFreed, pagesFreed, m_allocatedPixmaps.count() );
|
||||
}
|
||||
|
||||
|
@ -474,11 +478,11 @@ qulonglong DocumentPrivate::getTotalMemory()
|
|||
|
||||
qulonglong DocumentPrivate::getFreeMemory(qulonglong *freeSwap)
|
||||
{
|
||||
static QTime lastUpdate = QTime::currentTime().addSecs(-3);
|
||||
static QDeadlineTimer cacheTimer(0);
|
||||
static qulonglong cachedValue = 0;
|
||||
static qulonglong cachedFreeSwap = 0;
|
||||
|
||||
if (qAbs(lastUpdate.msecsTo(QTime::currentTime())) <= kMemCheckTime - 100) {
|
||||
if (!cacheTimer.hasExpired()) {
|
||||
if (freeSwap) {
|
||||
*freeSwap = cachedFreeSwap;
|
||||
}
|
||||
|
@ -537,7 +541,7 @@ qulonglong DocumentPrivate::getFreeMemory(qulonglong *freeSwap)
|
|||
return 0;
|
||||
}
|
||||
|
||||
lastUpdate = QTime::currentTime();
|
||||
cacheTimer.setRemainingTime(kFreeMemCacheTimeout);
|
||||
|
||||
if (freeSwap) {
|
||||
*freeSwap = (cachedFreeSwap = (Q_UINT64_C(1024) * values[3]));
|
||||
|
@ -553,7 +557,7 @@ qulonglong DocumentPrivate::getFreeMemory(qulonglong *freeSwap)
|
|||
// sum up inactive, cached and free memory
|
||||
if (sysctlbyname("vm.stats.vm.v_cache_count", &cache, &cachelen, NULL, 0) == 0 && sysctlbyname("vm.stats.vm.v_inactive_count", &inact, &inactlen, NULL, 0) == 0 &&
|
||||
sysctlbyname("vm.stats.vm.v_free_count", &free, &freelen, NULL, 0) == 0 && sysctlbyname("vm.stats.vm.v_page_size", &psize, &psizelen, NULL, 0) == 0) {
|
||||
lastUpdate = QTime::currentTime();
|
||||
cacheTimer.setRemainingTime(kFreeMemCacheTimeout);
|
||||
return (cachedValue = (cache + inact + free) * psize);
|
||||
} else {
|
||||
return 0;
|
||||
|
@ -563,7 +567,7 @@ qulonglong DocumentPrivate::getFreeMemory(qulonglong *freeSwap)
|
|||
stat.dwLength = sizeof(stat);
|
||||
GlobalMemoryStatusEx(&stat);
|
||||
|
||||
lastUpdate = QTime::currentTime();
|
||||
cacheTimer.setRemainingTime(kFreeMemCacheTimeout);
|
||||
|
||||
if (freeSwap)
|
||||
*freeSwap = (cachedFreeSwap = stat.ullAvailPageFile);
|
||||
|
@ -675,7 +679,7 @@ bool DocumentPrivate::loadDocumentInfo(QFile &infoFile, LoadDocumentInfoFlags lo
|
|||
QDomElement viewElement = viewNode.toElement();
|
||||
if (viewElement.tagName() == QLatin1String("view")) {
|
||||
const QString viewName = viewElement.attribute(QStringLiteral("name"));
|
||||
for (View *view : qAsConst(m_views)) {
|
||||
for (View *view : std::as_const(m_views)) {
|
||||
if (view->name() == viewName) {
|
||||
loadViewsInfo(view, viewElement);
|
||||
loadedAnything = true;
|
||||
|
@ -809,19 +813,16 @@ bool DocumentPrivate::openRelativeFile(const QString &fileName)
|
|||
|
||||
Generator *DocumentPrivate::loadGeneratorLibrary(const KPluginMetaData &service)
|
||||
{
|
||||
KPluginLoader loader(service.fileName());
|
||||
qCDebug(OkularCoreDebug) << service.fileName();
|
||||
KPluginFactory *factory = loader.factory();
|
||||
if (!factory) {
|
||||
qCWarning(OkularCoreDebug).nospace() << "Invalid plugin factory for " << service.fileName() << ":" << loader.errorString();
|
||||
const auto result = KPluginFactory::instantiatePlugin<Okular::Generator>(service);
|
||||
|
||||
if (!result) {
|
||||
qCWarning(OkularCoreDebug).nospace() << "Failed to load plugin " << service.fileName() << ": " << result.errorText;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Generator *plugin = factory->create<Okular::Generator>();
|
||||
|
||||
GeneratorInfo info(plugin, service);
|
||||
GeneratorInfo info(result.plugin, service);
|
||||
m_loadedGenerators.insert(service.pluginId(), info);
|
||||
return plugin;
|
||||
return result.plugin;
|
||||
}
|
||||
|
||||
void DocumentPrivate::loadAllGeneratorLibraries()
|
||||
|
@ -1008,8 +1009,9 @@ bool DocumentPrivate::savePageDocumentInfo(QTemporaryFile *infoFile, int what) c
|
|||
|
||||
// 3. Save DOM to XML file
|
||||
QString xml = doc.toString();
|
||||
|
||||
QTextStream os(infoFile);
|
||||
os.setCodec("UTF-8");
|
||||
os.setEncoding(QStringConverter::Utf8);
|
||||
os << xml;
|
||||
return true;
|
||||
}
|
||||
|
@ -1302,7 +1304,7 @@ void DocumentPrivate::saveDocumentInfo() const
|
|||
// create views root node
|
||||
QDomElement viewsNode = doc.createElement(QStringLiteral("views"));
|
||||
generalInfo.appendChild(viewsNode);
|
||||
for (View *view : qAsConst(m_views)) {
|
||||
for (View *view : std::as_const(m_views)) {
|
||||
QDomElement viewEntry = doc.createElement(QStringLiteral("view"));
|
||||
viewEntry.setAttribute(QStringLiteral("name"), view->name());
|
||||
viewsNode.appendChild(viewEntry);
|
||||
|
@ -1312,7 +1314,7 @@ void DocumentPrivate::saveDocumentInfo() const
|
|||
// 3. Save DOM to XML file
|
||||
QString xml = doc.toString();
|
||||
QTextStream os(&infoFile);
|
||||
os.setCodec("UTF-8");
|
||||
os.setEncoding(QStringConverter::Utf8);
|
||||
os << xml;
|
||||
infoFile.close();
|
||||
}
|
||||
|
@ -1366,6 +1368,9 @@ void DocumentPrivate::sendGeneratorPixmapRequest()
|
|||
}
|
||||
const long screenSize = screen->devicePixelRatio() * screen->size().width() * screen->devicePixelRatio() * screen->size().height();
|
||||
|
||||
// Make sure the page is the right size to receive the pixmap
|
||||
r->page()->setPageSize(r->observer(), r->width(), r->height());
|
||||
|
||||
// If it's a preload but the generator is not threaded no point in trying to preload
|
||||
if (r->preload() && !m_generator->hasFeature(Generator::Threaded)) {
|
||||
m_pixmapRequestsStack.pop_back();
|
||||
|
@ -1386,7 +1391,7 @@ void DocumentPrivate::sendGeneratorPixmapRequest()
|
|||
delete r;
|
||||
}
|
||||
// If the requested area is above 4*screenSize pixels, and we're not rendering most of the page, switch on the tile manager
|
||||
else if (!tilesManager && m_generator->hasFeature(Generator::TiledRendering) && (long)r->width() * (long)r->height() > 4L * screenSize && normalizedArea < 0.75 && normalizedArea != 0) {
|
||||
else if (!tilesManager && m_generator->hasFeature(Generator::TiledRendering) && (long)r->width() * (long)r->height() > 4L * screenSize && normalizedArea < 0.75) {
|
||||
// if the image is too big. start using tiles
|
||||
qCDebug(OkularCoreDebug).nospace() << "Start using tiles on page " << r->pageNumber() << " (" << r->width() << "x" << r->height() << " px);";
|
||||
|
||||
|
@ -1518,7 +1523,7 @@ void DocumentPrivate::rotationFinished(int page, Okular::Page *okularPage)
|
|||
return;
|
||||
}
|
||||
|
||||
for (DocumentObserver *o : qAsConst(m_observers)) {
|
||||
for (DocumentObserver *o : std::as_const(m_observers)) {
|
||||
o->notifyPageChanged(page, DocumentObserver::Pixmap | DocumentObserver::Annotations);
|
||||
}
|
||||
}
|
||||
|
@ -1602,13 +1607,13 @@ void DocumentPrivate::refreshPixmaps(int pageNumber)
|
|||
|
||||
// Need to do this ↑↓ in two steps since requestPixmaps can end up calling cancelRenderingBecauseOf
|
||||
// which changes m_pixmaps and thus breaks the loop above
|
||||
for (PixmapRequest *pr : qAsConst(pixmapsToRequest)) {
|
||||
for (PixmapRequest *pr : std::as_const(pixmapsToRequest)) {
|
||||
QList<Okular::PixmapRequest *> requestedPixmaps;
|
||||
requestedPixmaps.push_back(pr);
|
||||
m_parent->requestPixmaps(requestedPixmaps, Okular::Document::NoOption);
|
||||
}
|
||||
|
||||
for (DocumentObserver *observer : qAsConst(m_observers)) {
|
||||
for (DocumentObserver *observer : std::as_const(m_observers)) {
|
||||
QList<Okular::PixmapRequest *> requestedPixmaps;
|
||||
|
||||
TilesManager *tilesManager = page->d->tilesManager(observer);
|
||||
|
@ -1755,8 +1760,8 @@ void DocumentPrivate::doProcessSearchMatch(RegularAreaRect *match, RunningSearch
|
|||
}
|
||||
|
||||
// notify observers about highlights changes
|
||||
for (int pageNumber : qAsConst(*pagesToNotify)) {
|
||||
for (DocumentObserver *observer : qAsConst(m_observers)) {
|
||||
for (int pageNumber : std::as_const(*pagesToNotify)) {
|
||||
for (DocumentObserver *observer : std::as_const(m_observers)) {
|
||||
observer->notifyPageChanged(pageNumber, DocumentObserver::Highlights);
|
||||
}
|
||||
}
|
||||
|
@ -1786,7 +1791,7 @@ void DocumentPrivate::doContinueAllDocumentSearch(void *pagesToNotifySet, void *
|
|||
}
|
||||
|
||||
Q_EMIT m_parent->searchFinished(searchID, Document::SearchCancelled);
|
||||
for (const MatchesVector &mv : qAsConst(*pageMatches)) {
|
||||
for (const MatchesVector &mv : std::as_const(*pageMatches)) {
|
||||
qDeleteAll(mv);
|
||||
}
|
||||
delete pageMatches;
|
||||
|
@ -1841,13 +1846,13 @@ void DocumentPrivate::doContinueAllDocumentSearch(void *pagesToNotifySet, void *
|
|||
pagesToNotify->insert(it.key()->number());
|
||||
}
|
||||
|
||||
for (DocumentObserver *observer : qAsConst(m_observers)) {
|
||||
for (DocumentObserver *observer : std::as_const(m_observers)) {
|
||||
observer->notifySetup(m_pagesVector, 0);
|
||||
}
|
||||
|
||||
// notify observers about highlights changes
|
||||
for (int pageNumber : qAsConst(*pagesToNotify)) {
|
||||
for (DocumentObserver *observer : qAsConst(m_observers)) {
|
||||
for (int pageNumber : std::as_const(*pagesToNotify)) {
|
||||
for (DocumentObserver *observer : std::as_const(m_observers)) {
|
||||
observer->notifyPageChanged(pageNumber, DocumentObserver::Highlights);
|
||||
}
|
||||
}
|
||||
|
@ -1881,7 +1886,7 @@ void DocumentPrivate::doContinueGooglesDocumentSearch(void *pagesToNotifySet, vo
|
|||
|
||||
Q_EMIT m_parent->searchFinished(searchID, Document::SearchCancelled);
|
||||
|
||||
for (const MatchesVector &mv : qAsConst(*pageMatches)) {
|
||||
for (const MatchesVector &mv : std::as_const(*pageMatches)) {
|
||||
for (const MatchColor &mc : mv) {
|
||||
delete mc.first;
|
||||
}
|
||||
|
@ -1967,13 +1972,13 @@ void DocumentPrivate::doContinueGooglesDocumentSearch(void *pagesToNotifySet, vo
|
|||
}
|
||||
|
||||
// send page lists to update observers (since some filter on bookmarks)
|
||||
for (DocumentObserver *observer : qAsConst(m_observers)) {
|
||||
for (DocumentObserver *observer : std::as_const(m_observers)) {
|
||||
observer->notifySetup(m_pagesVector, 0);
|
||||
}
|
||||
|
||||
// notify observers about highlights changes
|
||||
for (int pageNumber : qAsConst(*pagesToNotify)) {
|
||||
for (DocumentObserver *observer : qAsConst(m_observers)) {
|
||||
for (int pageNumber : std::as_const(*pagesToNotify)) {
|
||||
for (DocumentObserver *observer : std::as_const(m_observers)) {
|
||||
observer->notifyPageChanged(pageNumber, DocumentObserver::Highlights);
|
||||
}
|
||||
}
|
||||
|
@ -2077,7 +2082,7 @@ void DocumentPrivate::loadSyncFile(const QString &filePath)
|
|||
const QString versionstr = ts.readLine();
|
||||
// anchor the pattern with \A and \z to match the entire subject string
|
||||
// TODO: with Qt 5.12 QRegularExpression::anchoredPattern() can be used instead
|
||||
QRegularExpression versionre(QStringLiteral("\\AVersion \\d+\\z"), QRegularExpression::CaseInsensitiveOption);
|
||||
static QRegularExpression versionre(QStringLiteral("\\AVersion \\d+\\z"), QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpressionMatch match = versionre.match(versionstr);
|
||||
if (!match.hasMatch()) {
|
||||
return;
|
||||
|
@ -2096,7 +2101,7 @@ void DocumentPrivate::loadSyncFile(const QString &filePath)
|
|||
QString line;
|
||||
while (!ts.atEnd()) {
|
||||
line = ts.readLine();
|
||||
const QStringList tokens = line.split(spaceChar, QString::SkipEmptyParts);
|
||||
const QStringList tokens = line.split(spaceChar, Qt::SkipEmptyParts);
|
||||
const int tokenSize = tokens.count();
|
||||
if (tokenSize < 1) {
|
||||
continue;
|
||||
|
@ -2147,7 +2152,7 @@ void DocumentPrivate::loadSyncFile(const QString &filePath)
|
|||
}
|
||||
|
||||
QVector<QList<Okular::SourceRefObjectRect *>> refRects(m_pagesVector.size());
|
||||
for (const pdfsyncpoint &pt : qAsConst(points)) {
|
||||
for (const pdfsyncpoint &pt : std::as_const(points)) {
|
||||
// drop pdfsync points not completely valid
|
||||
if (pt.page < 0 || pt.page >= m_pagesVector.size()) {
|
||||
continue;
|
||||
|
@ -2184,7 +2189,7 @@ void DocumentPrivate::clearAndWaitForRequests()
|
|||
startEventLoop = !m_executingPixmapRequests.empty();
|
||||
|
||||
if (m_generator->hasFeature(Generator::SupportsCancelling)) {
|
||||
for (PixmapRequest *executingRequest : qAsConst(m_executingPixmapRequests)) {
|
||||
for (PixmapRequest *executingRequest : std::as_const(m_executingPixmapRequests)) {
|
||||
executingRequest->d->mShouldAbortRender = 1;
|
||||
}
|
||||
|
||||
|
@ -2281,21 +2286,7 @@ QString DocumentPrivate::docDataFileName(const QUrl &url, qint64 document_size)
|
|||
QDir().mkpath(docdataDir);
|
||||
}
|
||||
QString newokularfile = docdataDir + QLatin1Char('/') + fn;
|
||||
// we don't want to accidentally migrate old files when running unit tests
|
||||
if (!QFile::exists(newokularfile) && !QStandardPaths::isTestModeEnabled()) {
|
||||
// see if an KDE4 file still exists
|
||||
static Kdelibs4Migration k4migration;
|
||||
QString oldfile = k4migration.locateLocal("data", QStringLiteral("okular/docdata/") + fn);
|
||||
if (oldfile.isEmpty()) {
|
||||
oldfile = k4migration.locateLocal("data", QStringLiteral("kpdf/") + fn);
|
||||
}
|
||||
if (!oldfile.isEmpty() && QFile::exists(oldfile)) {
|
||||
// ### copy or move?
|
||||
if (!QFile::copy(oldfile, newokularfile)) {
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newokularfile;
|
||||
}
|
||||
|
||||
|
@ -2303,7 +2294,7 @@ QVector<KPluginMetaData> DocumentPrivate::availableGenerators()
|
|||
{
|
||||
static QVector<KPluginMetaData> result;
|
||||
if (result.isEmpty()) {
|
||||
result = KPluginLoader::findPlugins(QStringLiteral("okular/generators"));
|
||||
result = KPluginMetaData::findPlugins(QStringLiteral("okular_generators"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -2351,7 +2342,7 @@ KPluginMetaData DocumentPrivate::generatorForMimeType(const QMimeType &type, QWi
|
|||
// sort the offers: the offers with an higher priority come before
|
||||
auto cmp = [](const KPluginMetaData &s1, const KPluginMetaData &s2) {
|
||||
const QString property = QStringLiteral("X-KDE-Priority");
|
||||
return s1.rawData()[property].toInt() > s2.rawData()[property].toInt();
|
||||
return s1.rawData().value(property).toInt() > s2.rawData().value(property).toInt();
|
||||
};
|
||||
std::stable_sort(offers.begin(), offers.end(), cmp);
|
||||
|
||||
|
@ -2381,7 +2372,7 @@ Document::OpenResult Document::openDocument(const QString &docFile, const QUrl &
|
|||
int fd = -1;
|
||||
if (url.scheme() == QLatin1String("fd")) {
|
||||
bool ok;
|
||||
fd = url.path().midRef(1).toInt(&ok);
|
||||
fd = QStringView {url.path()}.mid(1).toInt(&ok);
|
||||
if (!ok) {
|
||||
return OpenError;
|
||||
}
|
||||
|
@ -2508,11 +2499,10 @@ Document::OpenResult Document::openDocument(const QString &docFile, const QUrl &
|
|||
d->m_pageController = new PageController();
|
||||
connect(d->m_pageController, &PageController::rotationFinished, this, [this](int p, Okular::Page *op) { d->rotationFinished(p, op); });
|
||||
|
||||
for (Page *p : qAsConst(d->m_pagesVector)) {
|
||||
for (Page *p : std::as_const(d->m_pagesVector)) {
|
||||
p->d->m_doc = d;
|
||||
}
|
||||
|
||||
d->m_metadataLoadingCompleted = false;
|
||||
d->m_docdataMigrationNeeded = false;
|
||||
|
||||
// 2. load Additional Data (bookmarks, local annotations and metadata) about the document
|
||||
|
@ -2528,7 +2518,6 @@ Document::OpenResult Document::openDocument(const QString &docFile, const QUrl &
|
|||
d->loadDocumentInfo(LoadGeneralInfo);
|
||||
}
|
||||
|
||||
d->m_metadataLoadingCompleted = true;
|
||||
d->m_bookmarkManager->setUrl(d->m_url);
|
||||
|
||||
// 3. setup observers internal lists and data
|
||||
|
@ -2567,7 +2556,7 @@ Document::OpenResult Document::openDocument(const QString &docFile, const QUrl &
|
|||
d->m_nextDocumentDestination = QString();
|
||||
}
|
||||
|
||||
AudioPlayer::instance()->d->m_currentDocument = fromFileDescriptor ? QUrl() : d->m_url;
|
||||
AudioPlayer::instance()->setDocument(fromFileDescriptor ? QUrl() : d->m_url, this);
|
||||
|
||||
const QStringList docScripts = d->m_generator->metaData(QStringLiteral("DocumentScripts"), QStringLiteral("JavaScript")).toStringList();
|
||||
if (!docScripts.isEmpty()) {
|
||||
|
@ -2652,7 +2641,7 @@ void Document::closeDocument()
|
|||
// ideally we would just do that in the BackendOpaqueAction destructor
|
||||
// but that's too late in the cleanup process, i.e. the generator has already closed its document
|
||||
// and the document generator is nullptr
|
||||
for (Page *p : qAsConst(d->m_pagesVector)) {
|
||||
for (Page *p : std::as_const(d->m_pagesVector)) {
|
||||
const QList<ObjectRect *> &oRects = p->objectRects();
|
||||
for (ObjectRect *oRect : oRects) {
|
||||
if (oRect->objectType() == ObjectRect::Action) {
|
||||
|
@ -2754,7 +2743,7 @@ void Document::closeDocument()
|
|||
// reset internal variables
|
||||
|
||||
d->m_viewportHistory.clear();
|
||||
d->m_viewportHistory.emplace_back(DocumentViewport());
|
||||
d->m_viewportHistory.emplace_back();
|
||||
d->m_viewportIterator = d->m_viewportHistory.begin();
|
||||
d->m_allocatedPixmapsTotalMemory = 0;
|
||||
d->m_allocatedTextPagesFifo.clear();
|
||||
|
@ -2764,7 +2753,7 @@ void Document::closeDocument()
|
|||
d->m_documentInfo = DocumentInfo();
|
||||
d->m_documentInfoAskedKeys.clear();
|
||||
|
||||
AudioPlayer::instance()->d->m_currentDocument = QUrl();
|
||||
AudioPlayer::instance()->resetDocument();
|
||||
|
||||
d->m_undoStack->clear();
|
||||
d->m_docdataMigrationNeeded = false;
|
||||
|
@ -2812,7 +2801,7 @@ void Document::removeObserver(DocumentObserver *pObserver)
|
|||
}
|
||||
}
|
||||
|
||||
for (PixmapRequest *executingRequest : qAsConst(d->m_executingPixmapRequests)) {
|
||||
for (PixmapRequest *executingRequest : std::as_const(d->m_executingPixmapRequests)) {
|
||||
if (executingRequest->observer() == pObserver) {
|
||||
d->cancelRenderingBecauseOf(executingRequest, nullptr);
|
||||
}
|
||||
|
@ -2931,10 +2920,10 @@ DocumentInfo Document::documentInfo(const QSet<DocumentInfo::Key> &keys) const
|
|||
info.set(DocumentInfo::Pages, QString::number(this->pages()));
|
||||
}
|
||||
|
||||
d->m_documentInfo.d->values.unite(info.d->values);
|
||||
d->m_documentInfo.d->titles.unite(info.d->titles);
|
||||
result.d->values.unite(info.d->values);
|
||||
result.d->titles.unite(info.d->titles);
|
||||
d->m_documentInfo.d->values.insert(info.d->values);
|
||||
d->m_documentInfo.d->titles.insert(info.d->titles);
|
||||
result.d->values.insert(info.d->values);
|
||||
result.d->titles.insert(info.d->titles);
|
||||
}
|
||||
d->m_documentInfoAskedKeys += keys;
|
||||
|
||||
|
@ -3022,7 +3011,7 @@ void Document::setVisiblePageRects(const QVector<VisiblePageRect *> &visiblePage
|
|||
}
|
||||
d->m_pageRects = visiblePageRects;
|
||||
// notify change to all other (different from id) observers
|
||||
for (DocumentObserver *o : qAsConst(d->m_observers)) {
|
||||
for (DocumentObserver *o : std::as_const(d->m_observers)) {
|
||||
if (o != excludeObserver) {
|
||||
o->notifyVisibleRectsChanged();
|
||||
}
|
||||
|
@ -3403,7 +3392,7 @@ void Document::requestPixmaps(const QList<PixmapRequest *> &requests, PixmapRequ
|
|||
|
||||
// 1.C [CANCEL REQUESTS] cancel those requests that are running and should be cancelled because of the new requests coming in
|
||||
if (d->m_generator->hasFeature(Generator::SupportsCancelling)) {
|
||||
for (PixmapRequest *executingRequest : qAsConst(d->m_executingPixmapRequests)) {
|
||||
for (PixmapRequest *executingRequest : std::as_const(d->m_executingPixmapRequests)) {
|
||||
bool newRequestsContainExecutingRequestPage = false;
|
||||
bool requestCancelled = false;
|
||||
for (PixmapRequest *newRequest : requests) {
|
||||
|
@ -3452,7 +3441,7 @@ void Document::requestPixmaps(const QList<PixmapRequest *> &requests, PixmapRequ
|
|||
// if ( generator->canRequestPixmap() )
|
||||
d->sendGeneratorPixmapRequest();
|
||||
|
||||
for (DocumentObserver *o : qAsConst(observersPixmapCleared)) {
|
||||
for (DocumentObserver *o : std::as_const(observersPixmapCleared)) {
|
||||
o->notifyContentsCleared(Okular::DocumentObserver::Pixmap);
|
||||
}
|
||||
}
|
||||
|
@ -3633,7 +3622,7 @@ bool DocumentPrivate::canRemoveExternalAnnotations() const
|
|||
return false;
|
||||
}
|
||||
|
||||
void Document::setPageTextSelection(int page, RegularAreaRect *rect, const QColor &color)
|
||||
void Document::setPageTextSelection(int page, std::unique_ptr<RegularAreaRect> &&rect, const QColor &color)
|
||||
{
|
||||
Page *kp = d->m_pagesVector[page];
|
||||
if (!d->m_generator || !kp) {
|
||||
|
@ -3642,7 +3631,7 @@ void Document::setPageTextSelection(int page, RegularAreaRect *rect, const QColo
|
|||
|
||||
// add or remove the selection basing whether rect is null or not
|
||||
if (rect) {
|
||||
kp->d->setTextSelections(rect, color);
|
||||
kp->d->setTextSelections(*rect, color);
|
||||
} else {
|
||||
kp->d->deleteTextSelections();
|
||||
}
|
||||
|
@ -3677,7 +3666,7 @@ void Document::setPrevPage()
|
|||
}
|
||||
*/
|
||||
|
||||
void Document::setViewportWithHistory(const DocumentViewport &viewport, DocumentObserver *excludeObserver, bool smoothMove, bool updateHistory)
|
||||
void Document::setViewport(const DocumentViewport &viewport, DocumentObserver *excludeObserver, bool smoothMove, bool updateHistory)
|
||||
{
|
||||
if (!viewport.isValid()) {
|
||||
qCDebug(OkularCoreDebug) << "invalid viewport:" << viewport.toString();
|
||||
|
@ -3718,7 +3707,7 @@ void Document::setViewportWithHistory(const DocumentViewport &viewport, Document
|
|||
const bool currentPageChanged = (oldPageNumber != currentViewportPage);
|
||||
|
||||
// notify change to all other (different from id) observers
|
||||
for (DocumentObserver *o : qAsConst(d->m_observers)) {
|
||||
for (DocumentObserver *o : std::as_const(d->m_observers)) {
|
||||
if (o != excludeObserver) {
|
||||
o->notifyViewportChanged(smoothMove);
|
||||
}
|
||||
|
@ -3742,16 +3731,10 @@ void Document::setViewportPage(int page, DocumentObserver *excludeObserver, bool
|
|||
setViewport(DocumentViewport(page), excludeObserver, smoothMove);
|
||||
}
|
||||
|
||||
void Document::setViewport(const DocumentViewport &viewport, DocumentObserver *excludeObserver, bool smoothMove)
|
||||
{
|
||||
// set viewport, updating history
|
||||
setViewportWithHistory(viewport, excludeObserver, smoothMove, true);
|
||||
}
|
||||
|
||||
void Document::setZoom(int factor, DocumentObserver *excludeObserver)
|
||||
{
|
||||
// notify change to all other (different from id) observers
|
||||
for (DocumentObserver *o : qAsConst(d->m_observers)) {
|
||||
for (DocumentObserver *o : std::as_const(d->m_observers)) {
|
||||
if (o != excludeObserver) {
|
||||
o->notifyZoom(factor);
|
||||
}
|
||||
|
@ -3835,7 +3818,7 @@ void Document::searchText(int searchID, const QString &text, bool fromStart, Qt:
|
|||
|
||||
// remove highlights from pages and queue them for notifying changes
|
||||
*pagesToNotify += s->highlightedPages;
|
||||
for (const int pageNumber : qAsConst(s->highlightedPages)) {
|
||||
for (const int pageNumber : std::as_const(s->highlightedPages)) {
|
||||
d->m_pagesVector.at(pageNumber)->d->deleteHighlights(searchID);
|
||||
}
|
||||
s->highlightedPages.clear();
|
||||
|
@ -3892,7 +3875,7 @@ void Document::searchText(int searchID, const QString &text, bool fromStart, Qt:
|
|||
// 4. GOOGLE* - process all document marking pages
|
||||
else if (type == GoogleAll || type == GoogleAny) {
|
||||
QMap<Page *, QVector<QPair<RegularAreaRect *, QColor>>> *pageMatches = new QMap<Page *, QVector<QPair<RegularAreaRect *, QColor>>>;
|
||||
const QStringList words = text.split(QLatin1Char(' '), QString::SkipEmptyParts);
|
||||
const QStringList words = text.split(QLatin1Char(' '), Qt::SkipEmptyParts);
|
||||
|
||||
// search and highlight every word in 'text' on all pages
|
||||
QTimer::singleShot(0, this, [this, pagesToNotify, pageMatches, searchID, words] { d->doContinueGooglesDocumentSearch(pagesToNotify, pageMatches, 0, searchID, words); });
|
||||
|
@ -3948,7 +3931,7 @@ void Document::resetSearch(int searchID)
|
|||
RunningSearch *s = *searchIt;
|
||||
|
||||
// unhighlight pages and inform observers about that
|
||||
for (const int pageNumber : qAsConst(s->highlightedPages)) {
|
||||
for (const int pageNumber : std::as_const(s->highlightedPages)) {
|
||||
d->m_pagesVector.at(pageNumber)->d->deleteHighlights(searchID);
|
||||
foreachObserver(notifyPageChanged(pageNumber, DocumentObserver::Highlights));
|
||||
}
|
||||
|
@ -4085,9 +4068,35 @@ QString Document::bookmarkedPageRange() const
|
|||
return range;
|
||||
}
|
||||
|
||||
struct ExecuteNextActionsHelper : public QObject {
|
||||
struct ExecuteNextActionsHelper : public QObject, private DocumentObserver {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ExecuteNextActionsHelper(Document *doc)
|
||||
: m_doc(doc)
|
||||
{
|
||||
doc->addObserver(this);
|
||||
connect(doc, &Document::aboutToClose, this, [this] { b = false; });
|
||||
}
|
||||
|
||||
~ExecuteNextActionsHelper() override
|
||||
{
|
||||
m_doc->removeObserver(this);
|
||||
}
|
||||
|
||||
void notifySetup(const QVector<Okular::Page *> & /*pages*/, int setupFlags) override
|
||||
{
|
||||
if (setupFlags == DocumentChanged || setupFlags == UrlChanged) {
|
||||
b = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool shouldExecuteNextAction() const
|
||||
{
|
||||
return b;
|
||||
}
|
||||
|
||||
private:
|
||||
Document *const m_doc;
|
||||
bool b = true;
|
||||
};
|
||||
|
||||
|
@ -4098,8 +4107,7 @@ void Document::processAction(const Action *action)
|
|||
}
|
||||
|
||||
// Don't execute next actions if the action itself caused the closing of the document
|
||||
ExecuteNextActionsHelper executeNextActions;
|
||||
connect(this, &Document::aboutToClose, &executeNextActions, [&executeNextActions] { executeNextActions.b = false; });
|
||||
const ExecuteNextActionsHelper executeNextActionsHelper(this);
|
||||
|
||||
switch (action->actionType()) {
|
||||
case Action::Goto: {
|
||||
|
@ -4148,13 +4156,13 @@ void Document::processAction(const Action *action)
|
|||
QMimeDatabase db;
|
||||
QMimeType mime = db.mimeTypeForUrl(url);
|
||||
// Check executables
|
||||
if (KRun::isExecutableFile(url, mime.name())) {
|
||||
if (KIO::OpenUrlJob::isExecutableFile(url, mime.name())) {
|
||||
// Don't have any pdf that uses this code path, just a guess on how it should work
|
||||
if (!exe->parameters().isEmpty()) {
|
||||
url = d->giveAbsoluteUrl(exe->parameters());
|
||||
mime = db.mimeTypeForUrl(url);
|
||||
|
||||
if (KRun::isExecutableFile(url, mime.name())) {
|
||||
if (KIO::OpenUrlJob::isExecutableFile(url, mime.name())) {
|
||||
// this case is a link pointing to an executable with a parameter
|
||||
// that also is an executable, possibly a hand-crafted pdf
|
||||
Q_EMIT error(i18n("The document is trying to execute an external application and, for your safety, Okular does not allow that."), -1);
|
||||
|
@ -4168,14 +4176,14 @@ void Document::processAction(const Action *action)
|
|||
}
|
||||
}
|
||||
|
||||
KService::Ptr ptr = KApplicationTrader::preferredService(mime.name());
|
||||
if (ptr) {
|
||||
QList<QUrl> lst;
|
||||
lst.append(url);
|
||||
KRun::runService(*ptr, lst, nullptr);
|
||||
} else {
|
||||
Q_EMIT error(i18n("No application found for opening file of mimetype %1.", mime.name()), -1);
|
||||
}
|
||||
KIO::OpenUrlJob *job = new KIO::OpenUrlJob(url, mime.name());
|
||||
job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, d->m_widget));
|
||||
job->start();
|
||||
connect(job, &KIO::OpenUrlJob::result, this, [this, mime](KJob *job) {
|
||||
if (job->error()) {
|
||||
Q_EMIT error(i18n("No application found for opening file of mimetype %1.", mime.name()), -1);
|
||||
}
|
||||
});
|
||||
} break;
|
||||
|
||||
case Action::DocAction: {
|
||||
|
@ -4250,11 +4258,16 @@ void Document::processAction(const Action *action)
|
|||
}
|
||||
|
||||
// handle documents with relative path
|
||||
QUrl realUrl;
|
||||
if (d->m_url.isValid()) {
|
||||
const QUrl realUrl = KIO::upUrl(d->m_url).resolved(url);
|
||||
// KRun autodeletes
|
||||
KRun *r = new KRun(realUrl, d->m_widget);
|
||||
r->setRunExecutables(false);
|
||||
realUrl = KIO::upUrl(d->m_url).resolved(url);
|
||||
} else if (!url.isRelative()) {
|
||||
realUrl = url;
|
||||
}
|
||||
if (realUrl.isValid()) {
|
||||
auto *job = new KIO::OpenUrlJob(realUrl);
|
||||
job->setUiDelegate(KIO::createDefaultJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, d->m_widget.data()));
|
||||
job->start();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
@ -4291,7 +4304,7 @@ void Document::processAction(const Action *action)
|
|||
} break;
|
||||
}
|
||||
|
||||
if (executeNextActions.b) {
|
||||
if (executeNextActionsHelper.shouldExecuteNextAction()) {
|
||||
const QVector<Action *> nextActions = action->nextActions();
|
||||
for (const Action *a : nextActions) {
|
||||
processAction(a);
|
||||
|
@ -4345,25 +4358,25 @@ void Document::processFormatAction(const Action *action, Okular::FormFieldText *
|
|||
|
||||
QString DocumentPrivate::diff(const QString &oldVal, const QString &newVal)
|
||||
{
|
||||
QString diff;
|
||||
// We need to consider unicode surrogate pairs and others so working
|
||||
// with QString directly, even with the private QStringIterator is
|
||||
// not that simple to get right
|
||||
// so let's just convert to ucs4
|
||||
// also, given that toUcs4 is either a QList or a QVector depending on
|
||||
// qt version, let's try keep it very auto-typed to ease Qt6 porting
|
||||
|
||||
QStringIterator oldIt(oldVal);
|
||||
QStringIterator newIt(newVal);
|
||||
auto oldUcs4 = oldVal.toStdU32String();
|
||||
auto newUcs4 = newVal.toStdU32String();
|
||||
|
||||
while (oldIt.hasNext() && newIt.hasNext()) {
|
||||
QChar oldToken = oldIt.next();
|
||||
QChar newToken = newIt.next();
|
||||
|
||||
if (oldToken != newToken) {
|
||||
diff += newToken;
|
||||
break;
|
||||
for (size_t i = 0; i < std::min(oldUcs4.size(), newUcs4.size()); i++) {
|
||||
if (oldUcs4.at(i) != newUcs4.at(i)) {
|
||||
return QString::fromUcs4(std::u32string_view {newUcs4}.substr(i).data(), newUcs4.size() - i);
|
||||
}
|
||||
}
|
||||
|
||||
while (newIt.hasNext()) {
|
||||
diff += newIt.next();
|
||||
if (oldUcs4.size() < newUcs4.size()) {
|
||||
return QString::fromUcs4(std::u32string_view {newUcs4}.substr(oldUcs4.size()).data(), newUcs4.size() - oldUcs4.size());
|
||||
}
|
||||
return diff;
|
||||
return {};
|
||||
}
|
||||
|
||||
void Document::processKeystrokeAction(const Action *action, Okular::FormFieldText *fft, const QVariant &newValue)
|
||||
|
@ -4466,6 +4479,27 @@ void Document::processValidateAction(const Action *action, Okular::FormFieldText
|
|||
returnCode = event->returnCode();
|
||||
}
|
||||
|
||||
void Document::processFormMouseUpScripAction(const Action *action, Okular::FormField *ff)
|
||||
{
|
||||
if (!action || action->actionType() != Action::Script) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Lookup the page of the FormFieldText
|
||||
int foundPage = d->findFieldPageNumber(ff);
|
||||
|
||||
if (foundPage == -1) {
|
||||
qCDebug(OkularCoreDebug) << "Could not find page for formfield!";
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<Event> event = Event::createFieldMouseUpEvent(ff, d->m_pagesVector[foundPage]);
|
||||
|
||||
const ScriptAction *linkscript = static_cast<const ScriptAction *>(action);
|
||||
|
||||
d->executeScriptEvent(event, linkscript);
|
||||
}
|
||||
|
||||
void Document::processSourceReference(const SourceReference *ref)
|
||||
{
|
||||
if (!ref) {
|
||||
|
@ -4687,7 +4721,7 @@ QVector<KPluginMetaData> DocumentPrivate::configurableGenerators()
|
|||
const QVector<KPluginMetaData> available = availableGenerators();
|
||||
QVector<KPluginMetaData> result;
|
||||
for (const KPluginMetaData &md : available) {
|
||||
if (md.rawData()[QStringLiteral("X-KDE-okularHasInternalSettings")].toBool()) {
|
||||
if (md.rawData().value(QStringLiteral("X-KDE-okularHasInternalSettings")).toBool()) {
|
||||
result << md;
|
||||
}
|
||||
}
|
||||
|
@ -4723,7 +4757,7 @@ QStringList Document::supportedMimeTypes() const
|
|||
// Remove duplicate mimetypes represented by different names
|
||||
QMimeDatabase mimeDatabase;
|
||||
QSet<QMimeType> uniqueMimetypes;
|
||||
for (const QString &mimeName : qAsConst(result)) {
|
||||
for (const QString &mimeName : std::as_const(result)) {
|
||||
uniqueMimetypes.insert(mimeDatabase.mimeTypeForName(mimeName));
|
||||
}
|
||||
result.clear();
|
||||
|
@ -5212,7 +5246,7 @@ bool Document::extractArchivedFile(const QString &destFileName)
|
|||
return d->m_archiveData->document.copy(destFileName);
|
||||
}
|
||||
|
||||
QPrinter::Orientation Document::orientation() const
|
||||
QPageLayout::Orientation Document::orientation() const
|
||||
{
|
||||
double width, height;
|
||||
int landscape, portrait;
|
||||
|
@ -5227,7 +5261,7 @@ QPrinter::Orientation Document::orientation() const
|
|||
width = currentPage->width();
|
||||
height = currentPage->height();
|
||||
if (currentPage->orientation() == Okular::Rotation90 || currentPage->orientation() == Okular::Rotation270) {
|
||||
qSwap(width, height);
|
||||
std::swap(width, height);
|
||||
}
|
||||
if (width > height) {
|
||||
landscape++;
|
||||
|
@ -5235,7 +5269,7 @@ QPrinter::Orientation Document::orientation() const
|
|||
portrait++;
|
||||
}
|
||||
}
|
||||
return (landscape > portrait) ? QPrinter::Landscape : QPrinter::Portrait;
|
||||
return (landscape > portrait) ? QPageLayout::Landscape : QPageLayout::Portrait;
|
||||
}
|
||||
|
||||
void Document::setAnnotationEditingEnabled(bool enable)
|
||||
|
@ -5890,7 +5924,10 @@ struct Okular::NewSignatureDataPrivate {
|
|||
QString certSubjectCommonName;
|
||||
QString password;
|
||||
QString documentPassword;
|
||||
int page;
|
||||
QString location;
|
||||
QString reason;
|
||||
QString backgroundImagePath;
|
||||
int page = -1;
|
||||
NormalizedRect boundingRectangle;
|
||||
};
|
||||
|
||||
|
@ -5964,6 +6001,36 @@ void NewSignatureData::setDocumentPassword(const QString &password)
|
|||
d->documentPassword = password;
|
||||
}
|
||||
|
||||
QString NewSignatureData::location() const
|
||||
{
|
||||
return d->location;
|
||||
}
|
||||
|
||||
void NewSignatureData::setLocation(const QString &location)
|
||||
{
|
||||
d->location = location;
|
||||
}
|
||||
|
||||
QString NewSignatureData::reason() const
|
||||
{
|
||||
return d->reason;
|
||||
}
|
||||
|
||||
void NewSignatureData::setReason(const QString &reason)
|
||||
{
|
||||
d->reason = reason;
|
||||
}
|
||||
|
||||
QString Okular::NewSignatureData::backgroundImagePath() const
|
||||
{
|
||||
return d->backgroundImagePath;
|
||||
}
|
||||
|
||||
void Okular::NewSignatureData::setBackgroundImagePath(const QString &path)
|
||||
{
|
||||
d->backgroundImagePath = path;
|
||||
}
|
||||
|
||||
#undef foreachObserver
|
||||
#undef foreachObserverD
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <QMimeType>
|
||||
#include <QUrl>
|
||||
#include <QVariant>
|
||||
|
||||
class KConfigDialog;
|
||||
class KPluginMetaData;
|
||||
|
@ -433,19 +434,9 @@ public:
|
|||
* @param viewport The document viewport.
|
||||
* @param excludeObserver The observer which shouldn't be effected by this change.
|
||||
* @param smoothMove Whether the move shall be animated smoothly.
|
||||
*/
|
||||
void setViewport(const DocumentViewport &viewport, DocumentObserver *excludeObserver = nullptr, bool smoothMove = false);
|
||||
|
||||
/**
|
||||
* Sets the current document viewport to the given @p viewport.
|
||||
* BCI TODO: merge with setViewport, adding a parameter "bool updateHistory = true"
|
||||
*
|
||||
* @param viewport The document viewport.
|
||||
* @param excludeObserver The observer which shouldn't be effected by this change.
|
||||
* @param smoothMove Whether the move shall be animated smoothly.
|
||||
* @param updateHistory Whether to consider the change of viewport for the history navigation
|
||||
*/
|
||||
void setViewportWithHistory(const DocumentViewport &viewport, DocumentObserver *excludeObserver = nullptr, bool smoothMove = false, bool updateHistory = true);
|
||||
void setViewport(const DocumentViewport &viewport, DocumentObserver *excludeObserver = nullptr, bool smoothMove = false, bool updateHistory = true);
|
||||
|
||||
/**
|
||||
* Sets the current document viewport to the next viewport in the
|
||||
|
@ -601,7 +592,7 @@ public:
|
|||
* @param rect The rectangle of the selection.
|
||||
* @param color The color of the selection.
|
||||
*/
|
||||
void setPageTextSelection(int page, RegularAreaRect *rect, const QColor &color);
|
||||
void setPageTextSelection(int page, std::unique_ptr<RegularAreaRect> &&rect, const QColor &color);
|
||||
|
||||
/**
|
||||
* Returns true if there is an undo command available; otherwise returns false.
|
||||
|
@ -712,6 +703,13 @@ public:
|
|||
*/
|
||||
void processValidateAction(const Action *action, Okular::FormFieldText *fft, bool &returnCode);
|
||||
|
||||
/**
|
||||
* Processes the mouse up @p action on @p ff.
|
||||
*
|
||||
* @since 23.12
|
||||
*/
|
||||
void processFormMouseUpScripAction(const Action *action, Okular::FormField *ff);
|
||||
|
||||
/**
|
||||
* Returns a list of the bookmarked.pages
|
||||
*/
|
||||
|
@ -962,7 +960,7 @@ public:
|
|||
*
|
||||
* @since 0.14 (KDE 4.8)
|
||||
*/
|
||||
QPrinter::Orientation orientation() const;
|
||||
QPageLayout::Orientation orientation() const;
|
||||
|
||||
/**
|
||||
* Control annotation editing (creation, modification and removal),
|
||||
|
@ -1565,6 +1563,24 @@ public:
|
|||
/// @since 22.04
|
||||
void setDocumentPassword(const QString &password);
|
||||
|
||||
/// @since 23.08
|
||||
QString reason() const;
|
||||
|
||||
/// @since 23.08
|
||||
void setReason(const QString &reason);
|
||||
|
||||
/// @since 23.08
|
||||
QString location() const;
|
||||
|
||||
/// @since 23.08
|
||||
void setLocation(const QString &location);
|
||||
|
||||
/// @since 23.08
|
||||
QString backgroundImagePath() const;
|
||||
|
||||
/// @since 23.08
|
||||
void setBackgroundImagePath(const QString &path);
|
||||
|
||||
private:
|
||||
NewSignatureDataPrivate *const d;
|
||||
};
|
||||
|
|
|
@ -106,6 +106,7 @@ class DocumentPrivate
|
|||
public:
|
||||
explicit DocumentPrivate(Document *parent)
|
||||
: m_parent(parent)
|
||||
, m_searchCancelled(false)
|
||||
, m_tempFile(nullptr)
|
||||
, m_docSize(-1)
|
||||
, m_allocatedPixmapsTotalMemory(0)
|
||||
|
@ -126,6 +127,7 @@ public:
|
|||
, m_fontsCached(false)
|
||||
, m_annotationEditingEnabled(true)
|
||||
, m_annotationBeingModified(false)
|
||||
, m_undoStack(nullptr)
|
||||
, m_docdataMigrationNeeded(false)
|
||||
, m_synctex_scanner(nullptr)
|
||||
{
|
||||
|
@ -326,7 +328,6 @@ public:
|
|||
|
||||
bool m_annotationEditingEnabled;
|
||||
bool m_annotationBeingModified; // is an annotation currently being moved or resized?
|
||||
bool m_metadataLoadingCompleted;
|
||||
|
||||
QUndoStack *m_undoStack;
|
||||
QDomNode m_prevPropsOfAnnotBeingModified;
|
||||
|
|
|
@ -337,14 +337,16 @@ EditTextCommand::EditTextCommand(const QString &newContents, int newCursorPos, c
|
|||
if (m_prevCursorPos != m_prevAnchorPos) {
|
||||
qCDebug(OkularCoreDebug) << "OtherEdit, selection";
|
||||
m_editType = OtherEdit;
|
||||
} else if (newContentsRightOfCursor() == oldContentsRightOfCursor() && newContentsLeftOfCursor() == oldContentsLeftOfCursor().left(oldContentsLeftOfCursor().length() - 1) && oldContentsLeftOfCursor().rightRef(1) != QLatin1Char('\n')) {
|
||||
} else if (newContentsRightOfCursor() == oldContentsRightOfCursor() && newContentsLeftOfCursor() == oldContentsLeftOfCursor().left(oldContentsLeftOfCursor().length() - 1) &&
|
||||
QStringView {oldContentsLeftOfCursor()}.right(1) != QLatin1Char('\n')) {
|
||||
qCDebug(OkularCoreDebug) << "CharBackspace";
|
||||
m_editType = CharBackspace;
|
||||
} else if (newContentsLeftOfCursor() == oldContentsLeftOfCursor() && newContentsRightOfCursor() == oldContentsRightOfCursor().right(oldContentsRightOfCursor().length() - 1) &&
|
||||
oldContentsRightOfCursor().leftRef(1) != QLatin1Char('\n')) {
|
||||
QStringView {oldContentsRightOfCursor()}.left(1) != QLatin1Char('\n')) {
|
||||
qCDebug(OkularCoreDebug) << "CharDelete";
|
||||
m_editType = CharDelete;
|
||||
} else if (newContentsRightOfCursor() == oldContentsRightOfCursor() && newContentsLeftOfCursor().left(newContentsLeftOfCursor().length() - 1) == oldContentsLeftOfCursor() && newContentsLeftOfCursor().rightRef(1) != QLatin1Char('\n')) {
|
||||
} else if (newContentsRightOfCursor() == oldContentsRightOfCursor() && newContentsLeftOfCursor().left(newContentsLeftOfCursor().length() - 1) == oldContentsLeftOfCursor() &&
|
||||
QStringView {newContentsLeftOfCursor()}.right(1) != QLatin1Char('\n')) {
|
||||
qCDebug(OkularCoreDebug) << "CharInsert";
|
||||
m_editType = CharInsert;
|
||||
} else {
|
||||
|
@ -598,34 +600,23 @@ EditFormButtonsCommand::EditFormButtonsCommand(Okular::DocumentPrivate *docPriv,
|
|||
, m_prevButtonStates(QList<bool>())
|
||||
{
|
||||
setText(i18nc("Edit the state of a group of form buttons", "edit form button states"));
|
||||
for (const FormFieldButton *formButton : qAsConst(m_formButtons)) {
|
||||
for (const FormFieldButton *formButton : std::as_const(m_formButtons)) {
|
||||
m_prevButtonStates.append(formButton->state());
|
||||
m_pageNumbers.append(formButton->page()->number());
|
||||
}
|
||||
}
|
||||
|
||||
void EditFormButtonsCommand::undo()
|
||||
{
|
||||
clearFormButtonStates();
|
||||
QSet<int> extraPages;
|
||||
for (int i = 0; i < m_formButtons.size(); i++) {
|
||||
bool checked = m_prevButtonStates.at(i);
|
||||
if (checked) {
|
||||
m_formButtons.at(i)->setState(checked);
|
||||
}
|
||||
}
|
||||
|
||||
Okular::NormalizedRect boundingRect = buildBoundingRectangleForButtons(m_formButtons);
|
||||
moveViewportIfBoundingRectNotFullyVisible(boundingRect, m_docPriv, m_pageNumber);
|
||||
Q_EMIT m_docPriv->m_parent->formButtonsChangedByUndoRedo(m_pageNumber, m_formButtons);
|
||||
m_docPriv->notifyFormChanges(m_pageNumber);
|
||||
}
|
||||
|
||||
void EditFormButtonsCommand::redo()
|
||||
{
|
||||
clearFormButtonStates();
|
||||
for (int i = 0; i < m_formButtons.size(); i++) {
|
||||
bool checked = m_newButtonStates.at(i);
|
||||
if (checked) {
|
||||
m_formButtons.at(i)->setState(checked);
|
||||
if (m_pageNumbers.at(i) != m_pageNumber) {
|
||||
extraPages << m_pageNumbers.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -633,14 +624,40 @@ void EditFormButtonsCommand::redo()
|
|||
moveViewportIfBoundingRectNotFullyVisible(boundingRect, m_docPriv, m_pageNumber);
|
||||
Q_EMIT m_docPriv->m_parent->formButtonsChangedByUndoRedo(m_pageNumber, m_formButtons);
|
||||
m_docPriv->notifyFormChanges(m_pageNumber);
|
||||
for (auto page : std::as_const(extraPages)) {
|
||||
m_docPriv->notifyFormChanges(page);
|
||||
}
|
||||
}
|
||||
|
||||
void EditFormButtonsCommand::redo()
|
||||
{
|
||||
clearFormButtonStates();
|
||||
QSet<int> extraPages;
|
||||
for (int i = 0; i < m_formButtons.size(); i++) {
|
||||
bool checked = m_newButtonStates.at(i);
|
||||
if (checked) {
|
||||
m_formButtons.at(i)->setState(checked);
|
||||
}
|
||||
if (m_pageNumbers.at(i) != m_pageNumber) {
|
||||
extraPages << m_pageNumbers.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
Okular::NormalizedRect boundingRect = buildBoundingRectangleForButtons(m_formButtons);
|
||||
moveViewportIfBoundingRectNotFullyVisible(boundingRect, m_docPriv, m_pageNumber);
|
||||
Q_EMIT m_docPriv->m_parent->formButtonsChangedByUndoRedo(m_pageNumber, m_formButtons);
|
||||
m_docPriv->notifyFormChanges(m_pageNumber);
|
||||
for (auto page : std::as_const(extraPages)) {
|
||||
m_docPriv->notifyFormChanges(page);
|
||||
}
|
||||
}
|
||||
|
||||
bool EditFormButtonsCommand::refreshInternalPageReferences(const QVector<Okular::Page *> &newPagesVector)
|
||||
{
|
||||
const QList<FormFieldButton *> oldFormButtons = m_formButtons;
|
||||
m_formButtons.clear();
|
||||
for (FormFieldButton *oldFormButton : oldFormButtons) {
|
||||
FormFieldButton *button = dynamic_cast<FormFieldButton *>(Okular::PagePrivate::findEquivalentForm(newPagesVector[m_pageNumber], oldFormButton));
|
||||
for (int i = 0; i < oldFormButtons.size(); i++) {
|
||||
FormFieldButton *button = dynamic_cast<FormFieldButton *>(Okular::PagePrivate::findEquivalentForm(newPagesVector[m_pageNumbers[i]], oldFormButtons[i]));
|
||||
if (!button) {
|
||||
return false;
|
||||
}
|
||||
|
@ -652,7 +669,7 @@ bool EditFormButtonsCommand::refreshInternalPageReferences(const QVector<Okular:
|
|||
|
||||
void EditFormButtonsCommand::clearFormButtonStates()
|
||||
{
|
||||
for (FormFieldButton *formButton : qAsConst(m_formButtons)) {
|
||||
for (FormFieldButton *formButton : std::as_const(m_formButtons)) {
|
||||
formButton->setState(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -250,6 +250,7 @@ private:
|
|||
Okular::DocumentPrivate *m_docPriv;
|
||||
int m_pageNumber;
|
||||
QList<FormFieldButton *> m_formButtons;
|
||||
QList<int> m_pageNumbers;
|
||||
QList<bool> m_newButtonStates;
|
||||
QList<bool> m_prevButtonStates;
|
||||
};
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
using namespace Okular;
|
||||
|
||||
Document::PrintError
|
||||
FilePrinter::printFile(QPrinter &printer, const QString &file, QPrinter::Orientation documentOrientation, FileDeletePolicy fileDeletePolicy, PageSelectPolicy pageSelectPolicy, const QString &pageRange, ScaleMode scaleMode)
|
||||
FilePrinter::printFile(QPrinter &printer, const QString &file, QPageLayout::Orientation documentOrientation, FileDeletePolicy fileDeletePolicy, PageSelectPolicy pageSelectPolicy, const QString &pageRange, ScaleMode scaleMode)
|
||||
{
|
||||
FilePrinter fp;
|
||||
return fp.doPrintFiles(printer, QStringList(file), fileDeletePolicy, pageSelectPolicy, pageRange, documentOrientation, scaleMode);
|
||||
|
@ -51,7 +51,7 @@ static Document::PrintError doKProcessExecute(const QString &exe, const QStringL
|
|||
}
|
||||
|
||||
Document::PrintError
|
||||
FilePrinter::doPrintFiles(QPrinter &printer, const QStringList &fileList, FileDeletePolicy fileDeletePolicy, PageSelectPolicy pageSelectPolicy, const QString &pageRange, QPrinter::Orientation documentOrientation, ScaleMode scaleMode)
|
||||
FilePrinter::doPrintFiles(QPrinter &printer, const QStringList &fileList, FileDeletePolicy fileDeletePolicy, PageSelectPolicy pageSelectPolicy, const QString &pageRange, QPageLayout::Orientation documentOrientation, ScaleMode scaleMode)
|
||||
{
|
||||
if (fileList.size() < 1) {
|
||||
return Document::NoFileToPrintError;
|
||||
|
@ -144,11 +144,6 @@ FilePrinter::doPrintFiles(QPrinter &printer, const QStringList &fileList, FileDe
|
|||
return ret;
|
||||
}
|
||||
|
||||
QList<int> FilePrinter::pageList(QPrinter &printer, int lastPage, const QList<int> &selectedPageList)
|
||||
{
|
||||
return pageList(printer, lastPage, 0, selectedPageList);
|
||||
}
|
||||
|
||||
QList<int> FilePrinter::pageList(QPrinter &printer, int lastPage, int currentPage, const QList<int> &selectedPageList)
|
||||
{
|
||||
if (printer.printRange() == QPrinter::Selection) {
|
||||
|
@ -176,50 +171,6 @@ QList<int> FilePrinter::pageList(QPrinter &printer, int lastPage, int currentPag
|
|||
return list;
|
||||
}
|
||||
|
||||
QString FilePrinter::pageRange(QPrinter &printer, int lastPage, const QList<int> &selectedPageList)
|
||||
{
|
||||
if (printer.printRange() == QPrinter::Selection) {
|
||||
return pageListToPageRange(selectedPageList);
|
||||
}
|
||||
|
||||
if (printer.printRange() == QPrinter::PageRange) {
|
||||
return QStringLiteral("%1-%2").arg(printer.fromPage()).arg(printer.toPage());
|
||||
}
|
||||
|
||||
return QStringLiteral("1-%2").arg(lastPage);
|
||||
}
|
||||
|
||||
QString FilePrinter::pageListToPageRange(const QList<int> &pageList)
|
||||
{
|
||||
QString pageRange;
|
||||
int count = pageList.count();
|
||||
int i = 0;
|
||||
int seqStart = i;
|
||||
int seqEnd;
|
||||
|
||||
while (i != count) {
|
||||
if (i + 1 == count || pageList[i] + 1 != pageList[i + 1]) {
|
||||
seqEnd = i;
|
||||
|
||||
if (!pageRange.isEmpty()) {
|
||||
pageRange.append(QLatin1Char(','));
|
||||
}
|
||||
|
||||
if (seqStart == seqEnd) {
|
||||
pageRange.append(pageList[i]);
|
||||
} else {
|
||||
pageRange.append(QStringLiteral("%1-%2").arg(seqStart).arg(seqEnd));
|
||||
}
|
||||
|
||||
seqStart = i + 1;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return pageRange;
|
||||
}
|
||||
|
||||
bool FilePrinter::ps2pdfAvailable()
|
||||
{
|
||||
return (!QStandardPaths::findExecutable(QStringLiteral("ps2pdf")).isEmpty());
|
||||
|
@ -235,68 +186,23 @@ bool FilePrinter::cupsAvailable()
|
|||
#if defined(Q_OS_UNIX) && !defined(Q_OS_OSX)
|
||||
// Ideally we would have access to the private Qt method
|
||||
// QCUPSSupport::cupsAvailable() to do this as it is very complex routine.
|
||||
// However, if CUPS is available then QPrinter::numCopies() will always return 1
|
||||
// whereas if CUPS is not available it will return the real number of copies.
|
||||
// However, if CUPS is available then QPrinter::supportsMultipleCopies() will always return true
|
||||
// whereas if CUPS is not available it will return false.
|
||||
// This behaviour is guaranteed never to change, so we can use it as a reliable substitute.
|
||||
QPrinter testPrinter;
|
||||
testPrinter.setNumCopies(2);
|
||||
return (testPrinter.numCopies() == 1);
|
||||
return testPrinter.supportsMultipleCopies();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FilePrinter::detectCupsService()
|
||||
{
|
||||
QTcpSocket qsock;
|
||||
qsock.connectToHost(QStringLiteral("localhost"), 631);
|
||||
bool rtn = qsock.waitForConnected() && qsock.isValid();
|
||||
qsock.abort();
|
||||
return rtn;
|
||||
}
|
||||
|
||||
bool FilePrinter::detectCupsConfig()
|
||||
{
|
||||
if (QFile::exists(QStringLiteral("/etc/cups/cupsd.conf"))) {
|
||||
return true;
|
||||
}
|
||||
if (QFile::exists(QStringLiteral("/usr/etc/cups/cupsd.conf"))) {
|
||||
return true;
|
||||
}
|
||||
if (QFile::exists(QStringLiteral("/usr/local/etc/cups/cupsd.conf"))) {
|
||||
return true;
|
||||
}
|
||||
if (QFile::exists(QStringLiteral("/opt/etc/cups/cupsd.conf"))) {
|
||||
return true;
|
||||
}
|
||||
if (QFile::exists(QStringLiteral("/opt/local/etc/cups/cupsd.conf"))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QSize FilePrinter::psPaperSize(QPrinter &printer)
|
||||
{
|
||||
QSize size = printer.pageLayout().pageSize().sizePoints();
|
||||
|
||||
if (printer.pageSize() == QPrinter::Custom) {
|
||||
return QSize((int)printer.widthMM() * (25.4 / 72), (int)printer.heightMM() * (25.4 / 72));
|
||||
}
|
||||
|
||||
if (printer.orientation() == QPrinter::Landscape) {
|
||||
size.transpose();
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
QStringList FilePrinter::printArguments(QPrinter &printer,
|
||||
FileDeletePolicy fileDeletePolicy,
|
||||
PageSelectPolicy pageSelectPolicy,
|
||||
bool useCupsOptions,
|
||||
const QString &pageRange,
|
||||
const QString &version,
|
||||
QPrinter::Orientation documentOrientation,
|
||||
QPageLayout::Orientation documentOrientation,
|
||||
ScaleMode scaleMode)
|
||||
{
|
||||
QStringList argList;
|
||||
|
@ -347,7 +253,7 @@ QStringList FilePrinter::destination(QPrinter &printer, const QString &version)
|
|||
|
||||
QStringList FilePrinter::copies(QPrinter &printer, const QString &version)
|
||||
{
|
||||
int cp = printer.actualNumCopies();
|
||||
int cp = printer.copyCount();
|
||||
|
||||
if (version == QLatin1String("lp")) {
|
||||
return QStringList(QStringLiteral("-n")) << QStringLiteral("%1").arg(cp);
|
||||
|
@ -412,7 +318,7 @@ QStringList FilePrinter::pages(QPrinter &printer, PageSelectPolicy pageSelectPol
|
|||
return QStringList(); // AllPages
|
||||
}
|
||||
|
||||
QStringList FilePrinter::cupsOptions(QPrinter &printer, QPrinter::Orientation documentOrientation, ScaleMode scaleMode)
|
||||
QStringList FilePrinter::cupsOptions(QPrinter &printer, QPageLayout::Orientation documentOrientation, ScaleMode scaleMode)
|
||||
{
|
||||
QStringList optionList;
|
||||
|
||||
|
@ -464,68 +370,68 @@ QStringList FilePrinter::optionMedia(QPrinter &printer)
|
|||
|
||||
QString FilePrinter::mediaPageSize(QPrinter &printer)
|
||||
{
|
||||
switch (printer.pageSize()) {
|
||||
case QPrinter::A0:
|
||||
switch (printer.pageLayout().pageSize().id()) {
|
||||
case QPageSize::A0:
|
||||
return QStringLiteral("A0");
|
||||
case QPrinter::A1:
|
||||
case QPageSize::A1:
|
||||
return QStringLiteral("A1");
|
||||
case QPrinter::A2:
|
||||
case QPageSize::A2:
|
||||
return QStringLiteral("A2");
|
||||
case QPrinter::A3:
|
||||
case QPageSize::A3:
|
||||
return QStringLiteral("A3");
|
||||
case QPrinter::A4:
|
||||
case QPageSize::A4:
|
||||
return QStringLiteral("A4");
|
||||
case QPrinter::A5:
|
||||
case QPageSize::A5:
|
||||
return QStringLiteral("A5");
|
||||
case QPrinter::A6:
|
||||
case QPageSize::A6:
|
||||
return QStringLiteral("A6");
|
||||
case QPrinter::A7:
|
||||
case QPageSize::A7:
|
||||
return QStringLiteral("A7");
|
||||
case QPrinter::A8:
|
||||
case QPageSize::A8:
|
||||
return QStringLiteral("A8");
|
||||
case QPrinter::A9:
|
||||
case QPageSize::A9:
|
||||
return QStringLiteral("A9");
|
||||
case QPrinter::B0:
|
||||
case QPageSize::B0:
|
||||
return QStringLiteral("B0");
|
||||
case QPrinter::B1:
|
||||
case QPageSize::B1:
|
||||
return QStringLiteral("B1");
|
||||
case QPrinter::B10:
|
||||
case QPageSize::B10:
|
||||
return QStringLiteral("B10");
|
||||
case QPrinter::B2:
|
||||
case QPageSize::B2:
|
||||
return QStringLiteral("B2");
|
||||
case QPrinter::B3:
|
||||
case QPageSize::B3:
|
||||
return QStringLiteral("B3");
|
||||
case QPrinter::B4:
|
||||
case QPageSize::B4:
|
||||
return QStringLiteral("B4");
|
||||
case QPrinter::B5:
|
||||
case QPageSize::B5:
|
||||
return QStringLiteral("B5");
|
||||
case QPrinter::B6:
|
||||
case QPageSize::B6:
|
||||
return QStringLiteral("B6");
|
||||
case QPrinter::B7:
|
||||
case QPageSize::B7:
|
||||
return QStringLiteral("B7");
|
||||
case QPrinter::B8:
|
||||
case QPageSize::B8:
|
||||
return QStringLiteral("B8");
|
||||
case QPrinter::B9:
|
||||
case QPageSize::B9:
|
||||
return QStringLiteral("B9");
|
||||
case QPrinter::C5E:
|
||||
case QPageSize::C5E:
|
||||
return QStringLiteral("C5"); // Correct Translation?
|
||||
case QPrinter::Comm10E:
|
||||
case QPageSize::Comm10E:
|
||||
return QStringLiteral("Comm10"); // Correct Translation?
|
||||
case QPrinter::DLE:
|
||||
case QPageSize::DLE:
|
||||
return QStringLiteral("DL"); // Correct Translation?
|
||||
case QPrinter::Executive:
|
||||
case QPageSize::Executive:
|
||||
return QStringLiteral("Executive");
|
||||
case QPrinter::Folio:
|
||||
case QPageSize::Folio:
|
||||
return QStringLiteral("Folio");
|
||||
case QPrinter::Ledger:
|
||||
case QPageSize::Ledger:
|
||||
return QStringLiteral("Ledger");
|
||||
case QPrinter::Legal:
|
||||
case QPageSize::Legal:
|
||||
return QStringLiteral("Legal");
|
||||
case QPrinter::Letter:
|
||||
case QPageSize::Letter:
|
||||
return QStringLiteral("Letter");
|
||||
case QPrinter::Tabloid:
|
||||
case QPageSize::Tabloid:
|
||||
return QStringLiteral("Tabloid");
|
||||
case QPrinter::Custom:
|
||||
case QPageSize::Custom:
|
||||
return QStringLiteral("Custom.%1x%2mm").arg(printer.widthMM()).arg(printer.heightMM());
|
||||
default:
|
||||
return QString();
|
||||
|
@ -569,12 +475,12 @@ QString FilePrinter::mediaPaperSource(QPrinter &printer)
|
|||
}
|
||||
}
|
||||
|
||||
QStringList FilePrinter::optionOrientation(QPrinter &printer, QPrinter::Orientation documentOrientation)
|
||||
QStringList FilePrinter::optionOrientation(QPrinter &printer, QPageLayout::Orientation documentOrientation)
|
||||
{
|
||||
// portrait and landscape options rotate the document according to the document orientation
|
||||
// If we want to print a landscape document as one would expect it, we have to pass the
|
||||
// portrait option so that the document is not rotated additionally
|
||||
if (printer.orientation() == documentOrientation) {
|
||||
if (printer.pageLayout().orientation() == documentOrientation) {
|
||||
// the user wants the document printed as is
|
||||
return QStringList(QStringLiteral("-o")) << QStringLiteral("portrait");
|
||||
} else {
|
||||
|
@ -589,7 +495,7 @@ QStringList FilePrinter::optionDoubleSidedPrinting(QPrinter &printer)
|
|||
case QPrinter::DuplexNone:
|
||||
return QStringList(QStringLiteral("-o")) << QStringLiteral("sides=one-sided");
|
||||
case QPrinter::DuplexAuto:
|
||||
if (printer.orientation() == QPrinter::Landscape) {
|
||||
if (printer.pageLayout().orientation() == QPageLayout::Landscape) {
|
||||
return QStringList(QStringLiteral("-o")) << QStringLiteral("sides=two-sided-short-edge");
|
||||
} else {
|
||||
return QStringList(QStringLiteral("-o")) << QStringLiteral("sides=two-sided-long-edge");
|
||||
|
@ -626,7 +532,11 @@ QStringList FilePrinter::optionPageMargins(QPrinter &printer, ScaleMode scaleMod
|
|||
} else {
|
||||
qreal l(0), t(0), r(0), b(0);
|
||||
if (!printer.fullPage()) {
|
||||
printer.getPageMargins(&l, &t, &r, &b, QPrinter::Point);
|
||||
auto marginsf = printer.pageLayout().margins(QPageLayout::Point);
|
||||
l = marginsf.left();
|
||||
t = marginsf.top();
|
||||
r = marginsf.right();
|
||||
b = marginsf.bottom();
|
||||
}
|
||||
QStringList marginOptions;
|
||||
marginOptions << (QStringLiteral("-o")) << QStringLiteral("page-left=%1").arg(l) << QStringLiteral("-o") << QStringLiteral("page-top=%1").arg(t) << QStringLiteral("-o") << QStringLiteral("page-right=%1").arg(r)
|
||||
|
|
|
@ -84,7 +84,7 @@ public:
|
|||
*/
|
||||
static Document::PrintError printFile(QPrinter &printer,
|
||||
const QString &file,
|
||||
QPrinter::Orientation documentOrientation,
|
||||
QPageLayout::Orientation documentOrientation,
|
||||
FileDeletePolicy fileDeletePolicy = FilePrinter::ApplicationDeletesFiles,
|
||||
PageSelectPolicy pageSelectPolicy = FilePrinter::ApplicationSelectsPages,
|
||||
const QString &pageRange = QString(),
|
||||
|
@ -100,31 +100,6 @@ public:
|
|||
*/
|
||||
static QList<int> pageList(QPrinter &printer, int lastPage, int currentPage, const QList<int> &selectedPageList);
|
||||
|
||||
/** Return the list of pages selected by the user in the Print Dialog
|
||||
*
|
||||
* @param printer the print settings to use
|
||||
* @param lastPage the last page number, needed if AllPages option is selected
|
||||
* @param selectedPageList list of pages to use if Selection option is selected
|
||||
* @returns Returns list of pages to print
|
||||
*/
|
||||
static QList<int> pageList(QPrinter &printer, int lastPage, const QList<int> &selectedPageList);
|
||||
|
||||
/** Return the range of pages selected by the user in the Print Dialog
|
||||
*
|
||||
* @param printer the print settings to use
|
||||
* @param lastPage the last page number, needed if AllPages option is selected
|
||||
* @param selectedPageList list of pages to use if Selection option is selected
|
||||
* @returns Returns range of pages to print
|
||||
*/
|
||||
static QString pageRange(QPrinter &printer, int lastPage, const QList<int> &selectedPageList);
|
||||
|
||||
/** convert a Page List into a Page Range
|
||||
*
|
||||
* @param pageList list of pages to convert
|
||||
* @returns Returns equivalent page range
|
||||
*/
|
||||
static QString pageListToPageRange(const QList<int> &pageList);
|
||||
|
||||
/** Return if Ghostscript ps2pdf is available on this system
|
||||
*
|
||||
* @returns Returns true if Ghostscript ps2pdf available
|
||||
|
@ -137,24 +112,15 @@ public:
|
|||
*/
|
||||
static bool pdf2psAvailable();
|
||||
|
||||
private:
|
||||
/** Return if CUPS Print System is available on this system
|
||||
*
|
||||
* @returns Returns true if CUPS available
|
||||
*/
|
||||
static bool cupsAvailable();
|
||||
|
||||
/** Returns the postscript standard page size
|
||||
*
|
||||
* @returns Returns paper size in ps points
|
||||
*/
|
||||
static QSize psPaperSize(QPrinter &printer);
|
||||
|
||||
protected:
|
||||
bool detectCupsService();
|
||||
bool detectCupsConfig();
|
||||
|
||||
Document::PrintError
|
||||
doPrintFiles(QPrinter &printer, const QStringList &fileList, FileDeletePolicy fileDeletePolicy, PageSelectPolicy pageSelectPolicy, const QString &pageRange, QPrinter::Orientation documentOrientation, ScaleMode scaleMode);
|
||||
doPrintFiles(QPrinter &printer, const QStringList &fileList, FileDeletePolicy fileDeletePolicy, PageSelectPolicy pageSelectPolicy, const QString &pageRange, QPageLayout::Orientation documentOrientation, ScaleMode scaleMode);
|
||||
|
||||
/// @since 1.8
|
||||
QStringList printArguments(QPrinter &printer,
|
||||
|
@ -163,7 +129,7 @@ protected:
|
|||
bool useCupsOptions,
|
||||
const QString &pageRange,
|
||||
const QString &version,
|
||||
QPrinter::Orientation documentOrientation,
|
||||
QPageLayout::Orientation documentOrientation,
|
||||
ScaleMode scaleMode);
|
||||
|
||||
QStringList destination(QPrinter &printer, const QString &version);
|
||||
|
@ -173,11 +139,11 @@ protected:
|
|||
QStringList pages(QPrinter &printer, PageSelectPolicy pageSelectPolicy, const QString &pageRange, bool useCupsOptions, const QString &version);
|
||||
|
||||
/// @since 1.8
|
||||
QStringList cupsOptions(QPrinter &printer, QPrinter::Orientation documentOrientation, ScaleMode scaleMode);
|
||||
QStringList cupsOptions(QPrinter &printer, QPageLayout::Orientation documentOrientation, ScaleMode scaleMode);
|
||||
QStringList optionMedia(QPrinter &printer);
|
||||
QString mediaPageSize(QPrinter &printer);
|
||||
QString mediaPaperSource(QPrinter &printer);
|
||||
QStringList optionOrientation(QPrinter &printer, QPrinter::Orientation documentOrientation);
|
||||
QStringList optionOrientation(QPrinter &printer, QPageLayout::Orientation documentOrientation);
|
||||
QStringList optionDoubleSidedPrinting(QPrinter &printer);
|
||||
QStringList optionPageOrder(QPrinter &printer);
|
||||
QStringList optionCollateCopies(QPrinter &printer);
|
||||
|
|
|
@ -17,6 +17,7 @@ using namespace Okular;
|
|||
FormFieldPrivate::FormFieldPrivate(FormField::FieldType type)
|
||||
: m_type(type)
|
||||
, m_activateAction(nullptr)
|
||||
, q_ptr(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -242,7 +243,7 @@ public:
|
|||
void setValue(const QString &v) override
|
||||
{
|
||||
Q_Q(FormFieldChoice);
|
||||
const QStringList choices = v.split(QLatin1Char(';'), QString::SkipEmptyParts);
|
||||
const QStringList choices = v.split(QLatin1Char(';'), Qt::SkipEmptyParts);
|
||||
QList<int> newchoices;
|
||||
for (const QString &str : choices) {
|
||||
bool ok = true;
|
||||
|
@ -262,7 +263,7 @@ public:
|
|||
QList<int> choices = q->currentChoices();
|
||||
std::sort(choices.begin(), choices.end());
|
||||
QStringList list;
|
||||
for (const int c : qAsConst(choices)) {
|
||||
for (const int c : std::as_const(choices)) {
|
||||
list.append(QString::number(c));
|
||||
}
|
||||
return list.join(QStringLiteral(";"));
|
||||
|
|
|
@ -474,8 +474,9 @@ public:
|
|||
|
||||
/**
|
||||
* The signature info
|
||||
* @since 23.08
|
||||
*/
|
||||
virtual const SignatureInfo &signatureInfo() const = 0;
|
||||
virtual SignatureInfo signatureInfo() const = 0;
|
||||
|
||||
/**
|
||||
Signs a field of UnsignedSignature type.
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "config-okular.h"
|
||||
|
||||
#include "generator.h"
|
||||
#include "generator_p.h"
|
||||
#include "observer.h"
|
||||
|
@ -22,7 +24,7 @@
|
|||
#include <QMimeDatabase>
|
||||
#include <QTimer>
|
||||
|
||||
#ifdef WITH_KWALLET
|
||||
#if HAVE_KWALLET
|
||||
#include <KWallet>
|
||||
#endif
|
||||
|
||||
|
@ -35,7 +37,8 @@
|
|||
using namespace Okular;
|
||||
|
||||
GeneratorPrivate::GeneratorPrivate()
|
||||
: m_document(nullptr)
|
||||
: q_ptr(nullptr)
|
||||
, m_document(nullptr)
|
||||
, mPixmapGenerationThread(nullptr)
|
||||
, mTextPageGenerationThread(nullptr)
|
||||
, mPixmapReady(true)
|
||||
|
@ -414,7 +417,7 @@ bool Generator::exportTo(const QString &, const ExportFormat &)
|
|||
|
||||
void Generator::walletDataForFile(const QString &fileName, QString *walletName, QString *walletFolder, QString *walletKey) const
|
||||
{
|
||||
#ifdef WITH_KWALLET
|
||||
#if HAVE_KWALLET
|
||||
*walletKey = fileName.section(QLatin1Char('/'), -1, -1);
|
||||
*walletName = KWallet::Wallet::NetworkWallet();
|
||||
*walletFolder = QStringLiteral("KPdf");
|
||||
|
@ -559,11 +562,6 @@ TextRequestPrivate *TextRequestPrivate::get(const TextRequest *req)
|
|||
return req->d;
|
||||
}
|
||||
|
||||
PixmapRequest::PixmapRequest(DocumentObserver *observer, int pageNumber, int width, int height, int priority, PixmapRequestFeatures features)
|
||||
: PixmapRequest(observer, pageNumber, width, height, qApp->devicePixelRatio(), priority, features)
|
||||
{
|
||||
}
|
||||
|
||||
PixmapRequest::PixmapRequest(DocumentObserver *observer, int pageNumber, int width, int height, qreal dpr, int priority, PixmapRequestFeatures features)
|
||||
: d(new PixmapRequestPrivate)
|
||||
{
|
||||
|
@ -676,7 +674,7 @@ PixmapRequestPrivate *PixmapRequestPrivate::get(const PixmapRequest *req)
|
|||
|
||||
void PixmapRequestPrivate::swap()
|
||||
{
|
||||
qSwap(mWidth, mHeight);
|
||||
std::swap(mWidth, mHeight);
|
||||
}
|
||||
|
||||
class Okular::ExportFormatPrivate : public QSharedData
|
||||
|
|
|
@ -616,18 +616,6 @@ public:
|
|||
enum PixmapRequestFeature { NoFeature = 0, Asynchronous = 1, Preload = 2 };
|
||||
Q_DECLARE_FLAGS(PixmapRequestFeatures, PixmapRequestFeature)
|
||||
|
||||
/**
|
||||
* Creates a new pixmap request.
|
||||
*
|
||||
* @param observer The observer.
|
||||
* @param pageNumber The page number.
|
||||
* @param width The width of the page in logical pixels.
|
||||
* @param height The height of the page in logical pixels.
|
||||
* @param priority The priority of the request.
|
||||
* @param features The features of generation.
|
||||
*/
|
||||
[[deprecated("This PixmapRequest constructor is deprecated, use the one including the device pixel ratio")]] PixmapRequest(DocumentObserver *observer, int pageNumber, int width, int height, int priority, PixmapRequestFeatures features);
|
||||
|
||||
/**
|
||||
* Creates a new pixmap request.
|
||||
*
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#ifndef OKULAR_GLOBAL_H
|
||||
#define OKULAR_GLOBAL_H
|
||||
|
||||
#include <QFlags>
|
||||
#include <QGlobalStatic>
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,12 +16,11 @@ class TextSelection::Private
|
|||
{
|
||||
public:
|
||||
int direction;
|
||||
int it[2];
|
||||
NormalizedPoint cur[2];
|
||||
};
|
||||
|
||||
TextSelection::TextSelection(const NormalizedPoint &start, const NormalizedPoint &end)
|
||||
: d(new Private)
|
||||
: d(std::make_unique<Private>())
|
||||
{
|
||||
if (end.y - start.y < 0 || (end.y - start.y == 0 && end.x - start.x < 0)) {
|
||||
d->direction = 1;
|
||||
|
@ -31,41 +30,9 @@ TextSelection::TextSelection(const NormalizedPoint &start, const NormalizedPoint
|
|||
|
||||
d->cur[0] = start;
|
||||
d->cur[1] = end;
|
||||
d->it[d->direction % 2] = -1;
|
||||
d->it[(d->direction + 1) % 2] = -1;
|
||||
}
|
||||
|
||||
TextSelection::~TextSelection()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void TextSelection::end(const NormalizedPoint &p)
|
||||
{
|
||||
// changing direction as in 2b , assuming the bool->int conversion is correct
|
||||
int dir1 = d->direction;
|
||||
d->direction = (p.y - d->cur[0].y < 0 || (p.y - d->cur[0].y == 0 && p.x - d->cur[0].x < 0));
|
||||
if (d->direction != dir1) {
|
||||
qCDebug(OkularCoreDebug) << "changing direction in selection";
|
||||
}
|
||||
|
||||
d->cur[1] = p;
|
||||
}
|
||||
|
||||
void TextSelection::itE(int p)
|
||||
{
|
||||
d->it[(d->direction + 1) % 2] = p;
|
||||
}
|
||||
|
||||
void TextSelection::itB(int p)
|
||||
{
|
||||
d->it[(d->direction) % 2] = p;
|
||||
}
|
||||
|
||||
int TextSelection::direction() const
|
||||
{
|
||||
return d->direction;
|
||||
}
|
||||
TextSelection::~TextSelection() = default;
|
||||
|
||||
NormalizedPoint TextSelection::start() const
|
||||
{
|
||||
|
@ -76,13 +43,3 @@ NormalizedPoint TextSelection::end() const
|
|||
{
|
||||
return d->cur[(d->direction + 1) % 2];
|
||||
}
|
||||
|
||||
int TextSelection::itB() const
|
||||
{
|
||||
return d->it[d->direction % 2];
|
||||
}
|
||||
|
||||
int TextSelection::itE() const
|
||||
{
|
||||
return d->it[(d->direction + 1) % 2];
|
||||
}
|
||||
|
|
33
core/misc.h
33
core/misc.h
|
@ -14,21 +14,6 @@ namespace Okular
|
|||
{
|
||||
/**
|
||||
@short Wrapper around the information needed to generate the selection area
|
||||
There are two assumptions inside this class:
|
||||
1. the start never changes, one instance of this class is used for one selection,
|
||||
therefore the start of the selection will not change, only end and direction of
|
||||
the selection will change.
|
||||
By direction we mean the direction in which the end moves in relation to the start,
|
||||
forward selection is when end is after the start, backward when its before.
|
||||
|
||||
2. The following changes might appear during selection:
|
||||
a. the end moves without changing the direction (it can move up and down but not past the start):
|
||||
only itE will be updated
|
||||
b. the end moves with changing the direction then itB becomes itE if the previous direction was forward
|
||||
or itE becomes itB
|
||||
|
||||
3. Internally it that is related to the start cursor is always at it[0] while it related to end is it[1],
|
||||
transition between meanings (itB/itE) is done with dir modifier;
|
||||
*/
|
||||
class OKULARCORE_EXPORT TextSelection
|
||||
{
|
||||
|
@ -46,19 +31,6 @@ public:
|
|||
TextSelection(const TextSelection &) = delete;
|
||||
TextSelection &operator=(const TextSelection &) = delete;
|
||||
|
||||
/**
|
||||
* Changes the end point of the selection to the given @p point.
|
||||
*/
|
||||
void end(const NormalizedPoint &point);
|
||||
|
||||
void itE(int pos);
|
||||
void itB(int pos);
|
||||
|
||||
/**
|
||||
* Returns the direction of the selection.
|
||||
*/
|
||||
int direction() const;
|
||||
|
||||
/**
|
||||
* Returns the start point of the selection.
|
||||
*/
|
||||
|
@ -69,12 +41,9 @@ public:
|
|||
*/
|
||||
NormalizedPoint end() const;
|
||||
|
||||
int itB() const;
|
||||
int itE() const;
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private *const d;
|
||||
std::unique_ptr<Private> d;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ public:
|
|||
, m_tmp(nullptr)
|
||||
, m_showControls(false)
|
||||
, m_autoPlay(false)
|
||||
, m_startPaused(false)
|
||||
, m_showPosterImage(false)
|
||||
{
|
||||
}
|
||||
|
@ -43,6 +44,7 @@ public:
|
|||
QImage m_posterImage;
|
||||
bool m_showControls : 1;
|
||||
bool m_autoPlay : 1;
|
||||
bool m_startPaused : 1;
|
||||
bool m_showPosterImage : 1;
|
||||
};
|
||||
|
||||
|
@ -145,6 +147,16 @@ bool Movie::autoPlay() const
|
|||
return d->m_autoPlay;
|
||||
}
|
||||
|
||||
void Movie::setStartPaused(bool startPaused)
|
||||
{
|
||||
d->m_startPaused = startPaused;
|
||||
}
|
||||
|
||||
bool Movie::startPaused() const
|
||||
{
|
||||
return d->m_startPaused;
|
||||
}
|
||||
|
||||
void Movie::setShowPosterImage(bool show)
|
||||
{
|
||||
d->m_showPosterImage = show;
|
||||
|
|
10
core/movie.h
10
core/movie.h
|
@ -117,6 +117,16 @@ public:
|
|||
*/
|
||||
bool autoPlay() const;
|
||||
|
||||
/**
|
||||
* Sets whether to start the movie in paused mode
|
||||
*/
|
||||
void setStartPaused(bool startPaused);
|
||||
|
||||
/**
|
||||
* Whether to start the movie in paused mode
|
||||
*/
|
||||
bool startPaused() const;
|
||||
|
||||
/**
|
||||
* Sets whether to show a poster image.
|
||||
*
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
using namespace Okular;
|
||||
|
||||
DocumentObserver::DocumentObserver()
|
||||
: d(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@ public:
|
|||
TextSelection = 8, ///< Text selection has been changed
|
||||
Annotations = 16, ///< Annotations have been changed
|
||||
BoundingBox = 32, ///< Bounding boxes have been changed
|
||||
NeedSaveAs = 64 ///< Set when "Save" is needed or annotation/form changes will be lost @since 0.15 (KDE 4.9) @deprecated
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,6 +4,7 @@ X-KDE-ServiceType=okular/Generator
|
|||
Comment=File format backend for Okular
|
||||
Comment[ar]=المنتهى الخلفي لـنسق الملف لأوكلار
|
||||
Comment[az]=Okulyar üçün fayl formatı modulu
|
||||
Comment[be]=Рухавік для апрацоўвання фарматаў файлаў для Okular
|
||||
Comment[bg]=Ядро на Okular за файлови формати
|
||||
Comment[bs]=Pozadina formata datoteke za Okular
|
||||
Comment[ca]=Dorsal del format de fitxer per a l'Okular
|
||||
|
@ -13,18 +14,21 @@ Comment[da]=Filformatmotor til Okular
|
|||
Comment[de]=Dateiformat-Modul für Okular
|
||||
Comment[el]=Σύστημα υποστήριξης τύπου αρχείων για το Okular
|
||||
Comment[en_GB]=File format backend for Okular
|
||||
Comment[eo]=Dosierformato backend por Okular
|
||||
Comment[es]=Motor de formatos de archivos para Okular
|
||||
Comment[et]=Okulari failivormingu taustaprogramm
|
||||
Comment[eu]=Okularrentzako Fitxategi formatuaren bizkarraldekoa
|
||||
Comment[fi]=Tiedostomuototaustaosa Okularille
|
||||
Comment[fr]=Moteur de formats de fichiers pour Okular
|
||||
Comment[ga]=Inneall formáide comhaid le haghaidh Okular
|
||||
Comment[gl]=Infraestrutura dun formato de ficheiro para Okular
|
||||
Comment[gl]=Infraestrutura dun formato de ficheiro para Okular.
|
||||
Comment[he]=מנגנון סוגי קבצים ל־Okular
|
||||
Comment[hne]=ओकुलर बर फाइल प्रारूप बैकएंड
|
||||
Comment[hr]=Podrška za oblike datoteka za Okular
|
||||
Comment[hu]=Fájlformátumkezelő az Okularhoz
|
||||
Comment[ia]=Retro-administration de formato de file pro Okular
|
||||
Comment[is]=Skráasniðsstuðningur fyrir Okular
|
||||
Comment[ie]=Infrastructura de formate de file por Okular
|
||||
Comment[is]=Skráasniðsbakendi fyrir Okular
|
||||
Comment[it]=Backend per i formati di file di Okular
|
||||
Comment[ja]=Okular のファイル形式バックエンド
|
||||
Comment[ka]=ფაილის ფორმატის უკანაბოლო Okular-სთვის
|
||||
|
@ -33,7 +37,7 @@ Comment[km]=ផ្នែកខាងក្រោយទ្រង់ទ
|
|||
Comment[ko]=Okular용 파일 형식 백엔드
|
||||
Comment[ku]=Binesazî ya teşeya pelê Okular
|
||||
Comment[lt]=Okular failų formato programinė sąsaja
|
||||
Comment[lv]=Failu formātu Okular aizmugure
|
||||
Comment[lv]=„Okular“ datņu formātu aizmugursistēma
|
||||
Comment[mr]=ओक्युलर करिता फाईल प्रकार बॅकएन्ड
|
||||
Comment[nb]=Filformatmotor for Okular
|
||||
Comment[nds]=Dateiformaat-Hülpprogramm för Okular
|
||||
|
@ -47,7 +51,7 @@ Comment[ro]=Platformă Okular pentru formate de fișiere
|
|||
Comment[ru]=Модуль поддержки формата для Okular
|
||||
Comment[sk]=Backend formátu súborov pre Okular
|
||||
Comment[sl]=Zaledje za vrste datotek za Okular
|
||||
Comment[sq]=Mbështetës për formatet e skedarëve në Okular
|
||||
Comment[sq]=Mbështetës për formatet e skedave në Okular
|
||||
Comment[sr]=Позадина формата фајла за Окулар
|
||||
Comment[sr@ijekavian]=Позадина формата фајла за Окулар
|
||||
Comment[sr@ijekavianlatin]=Pozadina formata fajla za Okular
|
||||
|
@ -59,7 +63,7 @@ Comment[tr]=Okular için dosya biçimi arka ucu
|
|||
Comment[uk]=Модуль типів файлів для okular
|
||||
Comment[vi]=Hậu phương định dạng tệp cho Okular
|
||||
Comment[x-test]=xxFile format backend for Okularxx
|
||||
Comment[zh_CN]=Okular 文件格式后端
|
||||
Comment[zh_CN]=Okular 的文件格式后端程序
|
||||
Comment[zh_TW]=Okular 檔案格式後端
|
||||
# Priority of the plugin. 0 - disabled
|
||||
[PropertyDef::X-KDE-Priority]
|
||||
|
|
|
@ -221,11 +221,6 @@ bool Page::hasPixmap(DocumentObserver *observer, int width, int height, const No
|
|||
TilesManager *tm = d->tilesManager(observer);
|
||||
if (tm) {
|
||||
if (width != tm->width() || height != tm->height()) {
|
||||
// FIXME hasPixmap should not be calling setSize on the TilesManager this is not very "const"
|
||||
// as this function claims to be
|
||||
if (width != -1 && height != -1) {
|
||||
tm->setSize(width, height);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -250,21 +245,29 @@ bool Page::hasPixmap(DocumentObserver *observer, int width, int height, const No
|
|||
return (pixmap->width() == width && pixmap->height() == height);
|
||||
}
|
||||
|
||||
void Page::setPageSize(DocumentObserver *observer, int width, int height)
|
||||
{
|
||||
TilesManager *tm = d->tilesManager(observer);
|
||||
if (tm) {
|
||||
tm->setSize(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
bool Page::hasTextPage() const
|
||||
{
|
||||
return d->m_text != nullptr;
|
||||
}
|
||||
|
||||
RegularAreaRect *Page::wordAt(const NormalizedPoint &p, QString *word) const
|
||||
std::unique_ptr<RegularAreaRect> Page::wordAt(const NormalizedPoint &p) const
|
||||
{
|
||||
if (d->m_text) {
|
||||
return d->m_text->wordAt(p, word);
|
||||
return d->m_text->wordAt(p);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RegularAreaRect *Page::textArea(TextSelection *selection) const
|
||||
std::unique_ptr<RegularAreaRect> Page::textArea(const TextSelection &selection) const
|
||||
{
|
||||
if (d->m_text) {
|
||||
return d->m_text->textArea(selection);
|
||||
|
@ -371,9 +374,7 @@ TextEntity::List Page::words(const RegularAreaRect *area, TextPage::TextAreaIncl
|
|||
}
|
||||
|
||||
for (auto &retI : ret) {
|
||||
const TextEntity *orig = retI;
|
||||
retI = new TextEntity(orig->text(), new Okular::NormalizedRect(orig->transformedArea(d->rotationMatrix())));
|
||||
delete orig;
|
||||
retI = TextEntity(retI.text(), Okular::NormalizedRect(retI.transformedArea(d->rotationMatrix())));
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -388,7 +389,7 @@ void PagePrivate::rotateAt(Rotation orientation)
|
|||
deleteTextSelections();
|
||||
|
||||
if (((int)m_orientation + (int)m_rotation) % 2 != ((int)m_orientation + (int)orientation) % 2) {
|
||||
qSwap(m_width, m_height);
|
||||
std::swap(m_width, m_height);
|
||||
}
|
||||
|
||||
Rotation oldRotation = m_rotation;
|
||||
|
@ -425,12 +426,12 @@ void PagePrivate::rotateAt(Rotation orientation)
|
|||
* Rotate the object rects on the page.
|
||||
*/
|
||||
const QTransform matrix = rotationMatrix();
|
||||
for (ObjectRect *objRect : qAsConst(m_page->m_rects)) {
|
||||
for (ObjectRect *objRect : std::as_const(m_page->m_rects)) {
|
||||
objRect->transform(matrix);
|
||||
}
|
||||
|
||||
const QTransform highlightRotationMatrix = Okular::buildRotationMatrix((Rotation)(((int)m_rotation - (int)oldRotation + 4) % 4));
|
||||
for (HighlightAreaRect *hlar : qAsConst(m_page->m_highlights)) {
|
||||
for (HighlightAreaRect *hlar : std::as_const(m_page->m_highlights)) {
|
||||
hlar->transform(highlightRotationMatrix);
|
||||
}
|
||||
}
|
||||
|
@ -448,7 +449,7 @@ void PagePrivate::changeSize(const PageSize &size)
|
|||
m_width = size.width();
|
||||
m_height = size.height();
|
||||
if (m_rotation % 2) {
|
||||
qSwap(m_width, m_height);
|
||||
std::swap(m_width, m_height);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -625,16 +626,13 @@ void PagePrivate::setHighlight(int s_id, RegularAreaRect *rect, const QColor &co
|
|||
m_page->m_highlights.append(hr);
|
||||
}
|
||||
|
||||
void PagePrivate::setTextSelections(RegularAreaRect *r, const QColor &color)
|
||||
void PagePrivate::setTextSelections(const RegularAreaRect &r, const QColor &color)
|
||||
{
|
||||
deleteTextSelections();
|
||||
if (r) {
|
||||
HighlightAreaRect *hr = new HighlightAreaRect(r);
|
||||
hr->s_id = -1;
|
||||
hr->color = color;
|
||||
m_textSelections = hr;
|
||||
delete r;
|
||||
}
|
||||
HighlightAreaRect *hr = new HighlightAreaRect(&r);
|
||||
hr->s_id = -1;
|
||||
hr->color = color;
|
||||
m_textSelections = hr;
|
||||
}
|
||||
|
||||
void Page::setSourceReferences(const QList<SourceRefObjectRect *> &refRects)
|
||||
|
@ -746,7 +744,7 @@ void Page::setFormFields(const QList<FormField *> &fields)
|
|||
{
|
||||
qDeleteAll(d->formfields);
|
||||
d->formfields = fields;
|
||||
for (FormField *ff : qAsConst(d->formfields)) {
|
||||
for (FormField *ff : std::as_const(d->formfields)) {
|
||||
ff->d_ptr->setDefault();
|
||||
ff->d_ptr->m_page = this;
|
||||
}
|
||||
|
@ -875,7 +873,7 @@ bool PagePrivate::restoreLocalContents(const QDomNode &pageNode)
|
|||
}
|
||||
|
||||
QHash<int, FormField *> hashedforms;
|
||||
for (FormField *ff : qAsConst(formfields)) {
|
||||
for (FormField *ff : std::as_const(formfields)) {
|
||||
hashedforms[ff->id()] = ff;
|
||||
}
|
||||
|
||||
|
@ -930,7 +928,7 @@ void PagePrivate::saveLocalContents(QDomNode &parentNode, QDomDocument &document
|
|||
QDomElement annotListElement = document.createElement(QStringLiteral("annotationList"));
|
||||
|
||||
// add every annotation to the annotationList
|
||||
for (const Annotation *a : qAsConst(m_page->m_annotations)) {
|
||||
for (const Annotation *a : std::as_const(m_page->m_annotations)) {
|
||||
// only save okular annotations (not the embedded in file ones)
|
||||
if (!(a->flags() & Annotation::External)) {
|
||||
// append an filled-up element called 'annotation' to the list
|
||||
|
@ -1065,26 +1063,26 @@ FormField *PagePrivate::findEquivalentForm(const Page *p, FormField *oldField)
|
|||
{
|
||||
// given how id is not very good of id (at least for pdf) we do a few passes
|
||||
// same rect, type and id
|
||||
for (FormField *f : qAsConst(p->d->formfields)) {
|
||||
for (FormField *f : std::as_const(p->d->formfields)) {
|
||||
if (f->rect() == oldField->rect() && f->type() == oldField->type() && f->id() == oldField->id()) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
// same rect and type
|
||||
for (FormField *f : qAsConst(p->d->formfields)) {
|
||||
for (FormField *f : std::as_const(p->d->formfields)) {
|
||||
if (f->rect() == oldField->rect() && f->type() == oldField->type()) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
// fuzzy rect, same type and id
|
||||
for (FormField *f : qAsConst(p->d->formfields)) {
|
||||
for (FormField *f : std::as_const(p->d->formfields)) {
|
||||
if (f->type() == oldField->type() && f->id() == oldField->id() && qFuzzyCompare(f->rect().left, oldField->rect().left) && qFuzzyCompare(f->rect().top, oldField->rect().top) &&
|
||||
qFuzzyCompare(f->rect().right, oldField->rect().right) && qFuzzyCompare(f->rect().bottom, oldField->rect().bottom)) {
|
||||
return f;
|
||||
}
|
||||
}
|
||||
// fuzzy rect and same type
|
||||
for (FormField *f : qAsConst(p->d->formfields)) {
|
||||
for (FormField *f : std::as_const(p->d->formfields)) {
|
||||
if (f->type() == oldField->type() && qFuzzyCompare(f->rect().left, oldField->rect().left) && qFuzzyCompare(f->rect().top, oldField->rect().top) && qFuzzyCompare(f->rect().right, oldField->rect().right) &&
|
||||
qFuzzyCompare(f->rect().bottom, oldField->rect().bottom)) {
|
||||
return f;
|
||||
|
|
|
@ -141,6 +141,11 @@ public:
|
|||
*/
|
||||
bool hasPixmap(DocumentObserver *observer, int width = -1, int height = -1, const NormalizedRect &rect = NormalizedRect()) const;
|
||||
|
||||
/**
|
||||
* Sets the size of the page (in screen pixels) if there is a TilesManager.
|
||||
*/
|
||||
void setPageSize(DocumentObserver *observer, int width, int height);
|
||||
|
||||
/**
|
||||
* Returns whether the page provides a text page (@ref TextPage).
|
||||
*/
|
||||
|
@ -210,12 +215,12 @@ public:
|
|||
* @see TextPage::wordAt()
|
||||
* @since 0.15 (KDE 4.9)
|
||||
*/
|
||||
RegularAreaRect *wordAt(const NormalizedPoint &p, QString *word = nullptr) const;
|
||||
std::unique_ptr<RegularAreaRect> wordAt(const NormalizedPoint &p) const;
|
||||
|
||||
/**
|
||||
* Returns the rectangular area of the given @p selection.
|
||||
*/
|
||||
RegularAreaRect *textArea(TextSelection *selection) const;
|
||||
std::unique_ptr<RegularAreaRect> textArea(const TextSelection &selection) const;
|
||||
|
||||
/**
|
||||
* Returns the object rect of the given @p type which is at point (@p x, @p y) at scale (@p xScale, @p yScale).
|
||||
|
|
|
@ -95,7 +95,7 @@ public:
|
|||
* @param r Areas of new text selections.
|
||||
* @param color Color of new text selections.
|
||||
*/
|
||||
void setTextSelections(RegularAreaRect *r, const QColor &color);
|
||||
void setTextSelections(const RegularAreaRect &r, const QColor &color);
|
||||
|
||||
/**
|
||||
* Sets the @p color and @p rect of the highlight for the observer with
|
||||
|
|
|
@ -4,6 +4,19 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
/* QJSEngine limits what we can do with the global object in C++, so map Doc into this here. */
|
||||
{
|
||||
const props = Object.getOwnPropertyDescriptors(Doc);
|
||||
for (prop in props) {
|
||||
Object.defineProperty(this, prop, props[prop]);
|
||||
}
|
||||
for (const name of Object.getOwnPropertyNames(Doc)) {
|
||||
if (typeof Doc[name] === 'function') {
|
||||
this.__proto__[name] = Doc[name];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Builtin functions for Okular's PDF JavaScript interpretation. */
|
||||
|
||||
/** AFSimple_Calculate
|
||||
|
@ -348,3 +361,49 @@ function AFPercent_Keystroke( nDec, sepStyle )
|
|||
event.rc = !isNaN(event.change) || event.change == "." || event.change == ","
|
||||
}
|
||||
}
|
||||
|
||||
app.popUpMenuEx = function() {
|
||||
return app.okular_popUpMenuEx(arguments);
|
||||
}
|
||||
|
||||
app.popUpMenu = function() {
|
||||
// Convert arguments like this:
|
||||
// app.popUpMenu(["Fruits","Apples","Oranges"], "-","Beans","Corn");
|
||||
// into this:
|
||||
// app.popUpMenuEx(
|
||||
// {cName:"Fruits", oSubMenu:[
|
||||
// {cName:"Apples"},
|
||||
// {cName:"Oranges"}
|
||||
// ]},
|
||||
// {cName:"-"},
|
||||
// {cName:"Beans"},
|
||||
// {cName:"Corn"}
|
||||
// );
|
||||
function convertArgument(arg) {
|
||||
var exArguments = [];
|
||||
|
||||
for (element of arg) {
|
||||
var newElement = null;
|
||||
|
||||
if (Array.isArray(element) && element.length > 0) {
|
||||
newElement = {
|
||||
cName: element[0],
|
||||
oSubMenu: convertArgument(element.slice(1))
|
||||
};
|
||||
} else if (!Array.isArray(element)) {
|
||||
newElement = {
|
||||
cName: element
|
||||
};
|
||||
}
|
||||
|
||||
if (newElement !== null)
|
||||
exArguments.push(newElement);
|
||||
}
|
||||
|
||||
return exArguments;
|
||||
}
|
||||
|
||||
var exArguments = convertArgument(arguments);
|
||||
var result = app.okular_popUpMenuEx(exArguments);
|
||||
return result;
|
||||
}
|
|
@ -57,17 +57,19 @@ Event::EventType Event::eventType() const
|
|||
QString Event::name() const
|
||||
{
|
||||
switch (d->m_eventType) {
|
||||
case (FieldCalculate):
|
||||
case FieldCalculate:
|
||||
return QStringLiteral("Calculate");
|
||||
case (FieldFormat):
|
||||
case FieldFormat:
|
||||
return QStringLiteral("Format");
|
||||
case (FieldKeystroke):
|
||||
case FieldKeystroke:
|
||||
return QStringLiteral("Keystroke");
|
||||
case (FieldFocus):
|
||||
case FieldFocus:
|
||||
return QStringLiteral("Focus");
|
||||
case (FieldValidate):
|
||||
case FieldValidate:
|
||||
return QStringLiteral("Validate");
|
||||
case (UnknownEvent):
|
||||
case FieldMouseUp:
|
||||
return QStringLiteral("MouseUp");
|
||||
case UnknownEvent:
|
||||
default:
|
||||
return QStringLiteral("Unknown");
|
||||
}
|
||||
|
@ -76,13 +78,14 @@ QString Event::name() const
|
|||
QString Event::type() const
|
||||
{
|
||||
switch (d->m_eventType) {
|
||||
case (FieldCalculate):
|
||||
case (FieldFormat):
|
||||
case (FieldKeystroke):
|
||||
case (FieldFocus):
|
||||
case (FieldValidate):
|
||||
case FieldCalculate:
|
||||
case FieldFormat:
|
||||
case FieldKeystroke:
|
||||
case FieldFocus:
|
||||
case FieldValidate:
|
||||
case FieldMouseUp:
|
||||
return QStringLiteral("Field");
|
||||
case (UnknownEvent):
|
||||
case UnknownEvent:
|
||||
default:
|
||||
return QStringLiteral("Unknown");
|
||||
}
|
||||
|
@ -269,3 +272,12 @@ std::shared_ptr<Event> Event::createFormValidateEvent(FormField *target, Page *t
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::shared_ptr<Event> Event::createFieldMouseUpEvent(FormField *target, Page *targetPage)
|
||||
{
|
||||
std::shared_ptr<Event> ret = std::make_shared<Event>(Event::FieldMouseUp);
|
||||
ret->setTarget(target);
|
||||
ret->setTargetPage(targetPage);
|
||||
ret->setShiftModifier(QApplication::keyboardModifiers() & Qt::ShiftModifier);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ class Page;
|
|||
*
|
||||
* The implementation is currently limited. To implement support
|
||||
* for a new event create the according data fields / getters
|
||||
* and setters and update the handling in kjs_event
|
||||
* and setters and update the handling in js_event
|
||||
* accordingly.
|
||||
*
|
||||
* See Acrobat JavaScript Scripting Reference for the meaning
|
||||
|
@ -59,7 +59,7 @@ public:
|
|||
FieldMouseDown, /// < Not implemented.
|
||||
FieldMouseEnter, /// < Not implemented.
|
||||
FieldMouseExit, /// < Not implemented.
|
||||
FieldMouseUp, /// < Not implemented.
|
||||
FieldMouseUp, /// < This event is the result of a mouse up on a field.
|
||||
/* Validates the field after every change is committed
|
||||
* (clicked outside or tabbed to another field).
|
||||
* The enter event is not handled
|
||||
|
@ -116,6 +116,7 @@ public:
|
|||
static std::shared_ptr<Event> createKeystrokeEvent(FormField *target, Page *targetPage);
|
||||
static std::shared_ptr<Event> createFormFocusEvent(FormField *target, Page *targetPage, const QString &targetName = QString());
|
||||
static std::shared_ptr<Event> createFormValidateEvent(FormField *target, Page *targetPage, const QString &targetName = QString());
|
||||
static std::shared_ptr<Event> createFieldMouseUpEvent(FormField *target, Page *targetPage);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
|
|
107
core/script/executor_js.cpp
Normal file
107
core/script/executor_js.cpp
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "config-okular.h"
|
||||
#include "executor_js_p.h"
|
||||
|
||||
#include "../debug_p.h"
|
||||
#include "../document_p.h"
|
||||
|
||||
#include "event_p.h"
|
||||
#include "js_app_p.h"
|
||||
#include "js_console_p.h"
|
||||
#include "js_data_p.h"
|
||||
#include "js_display_p.h"
|
||||
#include "js_document_p.h"
|
||||
#include "js_event_p.h"
|
||||
#include "js_field_p.h"
|
||||
#include "js_fullscreen_p.h"
|
||||
#include "js_ocg_p.h"
|
||||
#include "js_spell_p.h"
|
||||
#include "js_util_p.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QJSEngine>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
class Okular::ExecutorJSPrivate
|
||||
{
|
||||
public:
|
||||
explicit ExecutorJSPrivate(DocumentPrivate *doc)
|
||||
: m_doc(doc)
|
||||
{
|
||||
initTypes();
|
||||
}
|
||||
~ExecutorJSPrivate()
|
||||
{
|
||||
m_watchdogTimer->deleteLater();
|
||||
m_watchdogThread.quit();
|
||||
m_watchdogThread.wait();
|
||||
}
|
||||
|
||||
void initTypes();
|
||||
|
||||
DocumentPrivate *m_doc;
|
||||
QJSEngine m_interpreter;
|
||||
|
||||
QThread m_watchdogThread;
|
||||
QTimer *m_watchdogTimer = nullptr;
|
||||
};
|
||||
|
||||
void ExecutorJSPrivate::initTypes()
|
||||
{
|
||||
m_watchdogThread.start();
|
||||
m_watchdogTimer = new QTimer;
|
||||
m_watchdogTimer->setInterval(std::chrono::seconds(2)); // max 2 secs allowed
|
||||
m_watchdogTimer->setSingleShot(true);
|
||||
m_watchdogTimer->moveToThread(&m_watchdogThread);
|
||||
QObject::connect(
|
||||
m_watchdogTimer, &QTimer::timeout, &m_interpreter, [this]() { m_interpreter.setInterrupted(true); }, Qt::DirectConnection);
|
||||
|
||||
m_interpreter.globalObject().setProperty(QStringLiteral("app"), m_interpreter.newQObject(new JSApp(m_doc, m_watchdogTimer)));
|
||||
m_interpreter.globalObject().setProperty(QStringLiteral("console"), m_interpreter.newQObject(new JSConsole));
|
||||
m_interpreter.globalObject().setProperty(QStringLiteral("Doc"), m_interpreter.newQObject(new JSDocument(m_doc)));
|
||||
m_interpreter.globalObject().setProperty(QStringLiteral("display"), m_interpreter.newQObject(new JSDisplay));
|
||||
m_interpreter.globalObject().setProperty(QStringLiteral("spell"), m_interpreter.newQObject(new JSSpell));
|
||||
m_interpreter.globalObject().setProperty(QStringLiteral("util"), m_interpreter.newQObject(new JSUtil));
|
||||
}
|
||||
|
||||
ExecutorJS::ExecutorJS(DocumentPrivate *doc)
|
||||
: d(new ExecutorJSPrivate(doc))
|
||||
{
|
||||
}
|
||||
|
||||
ExecutorJS::~ExecutorJS()
|
||||
{
|
||||
JSField::clearCachedFields();
|
||||
JSApp::clearCachedFields();
|
||||
delete d;
|
||||
}
|
||||
|
||||
void ExecutorJS::execute(const QString &script, Event *event)
|
||||
{
|
||||
const auto eventVal = event ? d->m_interpreter.newQObject(new JSEvent(event)) : QJSValue(QJSValue::UndefinedValue);
|
||||
d->m_interpreter.globalObject().setProperty(QStringLiteral("event"), eventVal);
|
||||
|
||||
QMetaObject::invokeMethod(d->m_watchdogTimer, qOverload<>(&QTimer::start));
|
||||
d->m_interpreter.setInterrupted(false);
|
||||
auto result = d->m_interpreter.evaluate(script, QStringLiteral("okular.js"));
|
||||
QMetaObject::invokeMethod(d->m_watchdogTimer, qOverload<>(&QTimer::stop));
|
||||
|
||||
if (result.isError()) {
|
||||
qCDebug(OkularCoreDebug) << "JS exception" << result.toString() << "(line " << result.property(QStringLiteral("lineNumber")).toInt() << ")";
|
||||
} else {
|
||||
qCDebug(OkularCoreDebug) << "result:" << result.toString();
|
||||
|
||||
if (event) {
|
||||
qCDebug(OkularCoreDebug) << "Event Result:" << event->name() << event->type() << "value:" << event->value();
|
||||
}
|
||||
}
|
||||
}
|
36
core/script/executor_js_p.h
Normal file
36
core/script/executor_js_p.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OKULAR_SCRIPT_EXECUTOR_JS_P_H
|
||||
#define OKULAR_SCRIPT_EXECUTOR_JS_P_H
|
||||
|
||||
class QString;
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class DocumentPrivate;
|
||||
class ExecutorJSPrivate;
|
||||
class Event;
|
||||
|
||||
class ExecutorJS
|
||||
{
|
||||
public:
|
||||
explicit ExecutorJS(DocumentPrivate *doc);
|
||||
~ExecutorJS();
|
||||
|
||||
ExecutorJS(const ExecutorJS &) = delete;
|
||||
ExecutorJS &operator=(const ExecutorJS &) = delete;
|
||||
|
||||
void execute(const QString &script, Event *event);
|
||||
|
||||
private:
|
||||
friend class ExecutorJSPrivate;
|
||||
ExecutorJSPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "executor_kjs_p.h"
|
||||
|
||||
#include <kjs/kjsarguments.h>
|
||||
#include <kjs/kjsinterpreter.h>
|
||||
#include <kjs/kjsobject.h>
|
||||
#include <kjs/kjsprototype.h>
|
||||
#include <kjs_version.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "../debug_p.h"
|
||||
#include "../document_p.h"
|
||||
|
||||
#include "config-okular.h"
|
||||
#include "event_p.h"
|
||||
#include "kjs_app_p.h"
|
||||
#include "kjs_console_p.h"
|
||||
#include "kjs_data_p.h"
|
||||
#include "kjs_display_p.h"
|
||||
#include "kjs_document_p.h"
|
||||
#include "kjs_event_p.h"
|
||||
#include "kjs_field_p.h"
|
||||
#include "kjs_fullscreen_p.h"
|
||||
#include "kjs_ocg_p.h"
|
||||
#include "kjs_spell_p.h"
|
||||
#include "kjs_util_p.h"
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
class Okular::ExecutorKJSPrivate
|
||||
{
|
||||
public:
|
||||
explicit ExecutorKJSPrivate(DocumentPrivate *doc)
|
||||
: m_doc(doc)
|
||||
{
|
||||
initTypes();
|
||||
}
|
||||
~ExecutorKJSPrivate()
|
||||
{
|
||||
delete m_interpreter;
|
||||
}
|
||||
|
||||
void initTypes();
|
||||
|
||||
DocumentPrivate *m_doc;
|
||||
KJSInterpreter *m_interpreter;
|
||||
KJSGlobalObject m_docObject;
|
||||
};
|
||||
|
||||
void ExecutorKJSPrivate::initTypes()
|
||||
{
|
||||
m_docObject = JSDocument::wrapDocument(m_doc);
|
||||
m_interpreter = new KJSInterpreter(m_docObject);
|
||||
|
||||
#if KJS_VERSION > QT_VERSION_CHECK(5, 71, 0)
|
||||
m_interpreter->setTimeoutTime(2000); // max 2 secs allowed
|
||||
#endif
|
||||
KJSContext *ctx = m_interpreter->globalContext();
|
||||
|
||||
JSApp::initType(ctx);
|
||||
JSFullscreen::initType(ctx);
|
||||
JSConsole::initType(ctx);
|
||||
JSData::initType(ctx);
|
||||
JSDisplay::initType(ctx);
|
||||
JSDocument::initType(ctx);
|
||||
JSEvent::initType(ctx);
|
||||
JSField::initType(ctx);
|
||||
JSOCG::initType(ctx);
|
||||
JSSpell::initType(ctx);
|
||||
JSUtil::initType(ctx);
|
||||
|
||||
m_docObject.setProperty(ctx, QStringLiteral("app"), JSApp::object(ctx, m_doc));
|
||||
m_docObject.setProperty(ctx, QStringLiteral("console"), JSConsole::object(ctx));
|
||||
m_docObject.setProperty(ctx, QStringLiteral("Doc"), m_docObject);
|
||||
m_docObject.setProperty(ctx, QStringLiteral("display"), JSDisplay::object(ctx));
|
||||
m_docObject.setProperty(ctx, QStringLiteral("OCG"), JSOCG::object(ctx));
|
||||
m_docObject.setProperty(ctx, QStringLiteral("spell"), JSSpell::object(ctx));
|
||||
m_docObject.setProperty(ctx, QStringLiteral("util"), JSUtil::object(ctx));
|
||||
}
|
||||
|
||||
ExecutorKJS::ExecutorKJS(DocumentPrivate *doc)
|
||||
: d(new ExecutorKJSPrivate(doc))
|
||||
{
|
||||
}
|
||||
|
||||
ExecutorKJS::~ExecutorKJS()
|
||||
{
|
||||
JSField::clearCachedFields();
|
||||
JSApp::clearCachedFields();
|
||||
JSOCG::clearCachedFields();
|
||||
delete d;
|
||||
}
|
||||
|
||||
void ExecutorKJS::execute(const QString &script, Event *event)
|
||||
{
|
||||
KJSContext *ctx = d->m_interpreter->globalContext();
|
||||
|
||||
d->m_docObject.setProperty(ctx, QStringLiteral("event"), event ? JSEvent::wrapEvent(ctx, event) : KJSUndefined());
|
||||
|
||||
#if KJS_VERSION > QT_VERSION_CHECK(5, 71, 0)
|
||||
d->m_interpreter->startTimeoutCheck();
|
||||
#endif
|
||||
KJSResult result = d->m_interpreter->evaluate(QStringLiteral("okular.js"), 1, script, &d->m_docObject);
|
||||
#if KJS_VERSION > QT_VERSION_CHECK(5, 71, 0)
|
||||
d->m_interpreter->stopTimeoutCheck();
|
||||
#endif
|
||||
|
||||
if (result.isException() || ctx->hasException()) {
|
||||
qCDebug(OkularCoreDebug) << "JS exception" << result.errorMessage();
|
||||
} else {
|
||||
qCDebug(OkularCoreDebug) << "result:" << result.value().toString(ctx);
|
||||
|
||||
if (event) {
|
||||
qCDebug(OkularCoreDebug) << "Event Result:" << event->name() << event->type() << "value:" << event->value();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OKULAR_SCRIPT_EXECUTOR_KJS_P_H
|
||||
#define OKULAR_SCRIPT_EXECUTOR_KJS_P_H
|
||||
|
||||
class QString;
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class DocumentPrivate;
|
||||
class ExecutorKJSPrivate;
|
||||
class Event;
|
||||
|
||||
class ExecutorKJS
|
||||
{
|
||||
public:
|
||||
explicit ExecutorKJS(DocumentPrivate *doc);
|
||||
~ExecutorKJS();
|
||||
|
||||
ExecutorKJS(const ExecutorKJS &) = delete;
|
||||
ExecutorKJS &operator=(const ExecutorKJS &) = delete;
|
||||
|
||||
void execute(const QString &script, Event *event);
|
||||
|
||||
private:
|
||||
friend class ExecutorKJSPrivate;
|
||||
ExecutorKJSPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
408
core/script/js_app.cpp
Normal file
408
core/script/js_app.cpp
Normal file
|
@ -0,0 +1,408 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "js_app_p.h"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include <QLocale>
|
||||
#include <QTimer>
|
||||
|
||||
#include <KLocalizedString>
|
||||
#include <QCheckBox>
|
||||
#include <QJSEngine>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "../document_p.h"
|
||||
#include "../scripter.h"
|
||||
#include "config-okular.h"
|
||||
#include "js_fullscreen_p.h"
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
#define OKULAR_TIMERID QStringLiteral("okular_timerID")
|
||||
|
||||
typedef QHash<int, QTimer *> TimerCache;
|
||||
Q_GLOBAL_STATIC(TimerCache, g_timerCache)
|
||||
|
||||
// the acrobat version we fake
|
||||
static const double fake_acroversion = 8.00;
|
||||
|
||||
// The property used to hold the value to return from app.popUpMenuEx
|
||||
static const char *kResultProperty = "result";
|
||||
|
||||
static const struct FakePluginInfo {
|
||||
const char *name;
|
||||
bool certified;
|
||||
bool loaded;
|
||||
const char *path;
|
||||
} s_fake_plugins[] = {{"Annots", true, true, ""}, {"EFS", true, true, ""}, {"EScript", true, true, ""}, {"Forms", true, true, ""}, {"ReadOutLoud", true, true, ""}, {"WebLink", true, true, ""}};
|
||||
static const int s_num_fake_plugins = sizeof(s_fake_plugins) / sizeof(s_fake_plugins[0]);
|
||||
|
||||
int JSApp::formsVersion() const
|
||||
{
|
||||
// faking a bit...
|
||||
return fake_acroversion;
|
||||
}
|
||||
|
||||
QString JSApp::language() const
|
||||
{
|
||||
QLocale locale;
|
||||
QString lang = QLocale::languageToString(locale.language());
|
||||
QString country = QLocale::territoryToString(locale.territory());
|
||||
QString acroLang = QStringLiteral("ENU");
|
||||
if (lang == QLatin1String("da")) {
|
||||
acroLang = QStringLiteral("DAN"); // Danish
|
||||
} else if (lang == QLatin1String("de")) {
|
||||
acroLang = QStringLiteral("DEU"); // German
|
||||
} else if (lang == QLatin1String("en")) {
|
||||
acroLang = QStringLiteral("ENU"); // English
|
||||
} else if (lang == QLatin1String("es")) {
|
||||
acroLang = QStringLiteral("ESP"); // Spanish
|
||||
} else if (lang == QLatin1String("fr")) {
|
||||
acroLang = QStringLiteral("FRA"); // French
|
||||
} else if (lang == QLatin1String("it")) {
|
||||
acroLang = QStringLiteral("ITA"); // Italian
|
||||
} else if (lang == QLatin1String("ko")) {
|
||||
acroLang = QStringLiteral("KOR"); // Korean
|
||||
} else if (lang == QLatin1String("ja")) {
|
||||
acroLang = QStringLiteral("JPN"); // Japanese
|
||||
} else if (lang == QLatin1String("nl")) {
|
||||
acroLang = QStringLiteral("NLD"); // Dutch
|
||||
} else if (lang == QLatin1String("pt") && country == QLatin1String("BR")) {
|
||||
acroLang = QStringLiteral("PTB"); // Brazilian Portuguese
|
||||
} else if (lang == QLatin1String("fi")) {
|
||||
acroLang = QStringLiteral("SUO"); // Finnish
|
||||
} else if (lang == QLatin1String("sv")) {
|
||||
acroLang = QStringLiteral("SVE"); // Swedish
|
||||
} else if (lang == QLatin1String("zh") && country == QLatin1String("CN")) {
|
||||
acroLang = QStringLiteral("CHS"); // Chinese Simplified
|
||||
} else if (lang == QLatin1String("zh") && country == QLatin1String("TW")) {
|
||||
acroLang = QStringLiteral("CHT"); // Chinese Traditional
|
||||
}
|
||||
return acroLang;
|
||||
}
|
||||
|
||||
int JSApp::numPlugIns() const
|
||||
{
|
||||
return s_num_fake_plugins;
|
||||
}
|
||||
|
||||
QString JSApp::platform() const
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
return QString::fromLatin1("WIN");
|
||||
#elif defined(Q_OS_MAC)
|
||||
return QString::fromLatin1("MAC");
|
||||
#else
|
||||
return QStringLiteral("UNIX");
|
||||
#endif
|
||||
}
|
||||
|
||||
QJSValue JSApp::plugIns() const
|
||||
{
|
||||
QJSValue plugins = qjsEngine(this)->newArray(s_num_fake_plugins);
|
||||
for (int i = 0; i < s_num_fake_plugins; ++i) {
|
||||
const FakePluginInfo &info = s_fake_plugins[i];
|
||||
QJSValue plugin = qjsEngine(this)->newObject();
|
||||
plugin.setProperty(QStringLiteral("certified"), info.certified);
|
||||
plugin.setProperty(QStringLiteral("loaded"), info.loaded);
|
||||
plugin.setProperty(QStringLiteral("name"), info.name);
|
||||
plugin.setProperty(QStringLiteral("path"), info.path);
|
||||
plugin.setProperty(QStringLiteral("version"), fake_acroversion);
|
||||
plugins.setProperty(i, plugin);
|
||||
}
|
||||
return plugins;
|
||||
}
|
||||
|
||||
QStringList JSApp::printColorProfiles() const
|
||||
{
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QStringList JSApp::printerNames() const
|
||||
{
|
||||
return QStringList();
|
||||
}
|
||||
|
||||
QString JSApp::viewerType() const
|
||||
{
|
||||
// faking a bit...
|
||||
return QStringLiteral("Reader");
|
||||
}
|
||||
|
||||
QString JSApp::viewerVariation() const
|
||||
{
|
||||
// faking a bit...
|
||||
return QStringLiteral("Reader");
|
||||
}
|
||||
|
||||
int JSApp::viewerVersion() const
|
||||
{
|
||||
// faking a bit...
|
||||
return fake_acroversion;
|
||||
}
|
||||
|
||||
/*
|
||||
Alert function defined in the reference, it shows a Dialog Box with options.
|
||||
app.alert()
|
||||
*/
|
||||
int JSApp::alert(const QJSValue &arguments)
|
||||
{
|
||||
const auto cMsg = arguments.property(QStringLiteral("cMsg")).toString();
|
||||
const auto nIcon = arguments.property(QStringLiteral("nIcon")).toInt();
|
||||
const auto nType = arguments.property(QStringLiteral("nType")).toInt();
|
||||
const auto cTitle = arguments.property(QStringLiteral("cTitle")).toString();
|
||||
const auto oCheckbox = arguments.property(QStringLiteral("oCheckbox"));
|
||||
return alert(cMsg, nIcon, nType, cTitle, QJSValue(), oCheckbox);
|
||||
}
|
||||
|
||||
int JSApp::alert(const QString &cMsg, int nIcon, int nType, const QString &cTitle, [[maybe_unused]] const QJSValue &oDoc, const QJSValue &oCheckbox)
|
||||
{
|
||||
QMessageBox::Icon icon = QMessageBox::Critical;
|
||||
switch (nIcon) {
|
||||
case 0:
|
||||
icon = QMessageBox::Critical;
|
||||
break;
|
||||
case 1:
|
||||
icon = QMessageBox::Warning;
|
||||
break;
|
||||
case 2:
|
||||
icon = QMessageBox::Question;
|
||||
break;
|
||||
case 3:
|
||||
icon = QMessageBox::Information;
|
||||
break;
|
||||
}
|
||||
|
||||
const QString title = !cTitle.isEmpty() ? cTitle : QStringLiteral("Okular");
|
||||
QMessageBox box(icon, title, cMsg);
|
||||
|
||||
QMessageBox::StandardButtons buttons = QMessageBox::Ok;
|
||||
switch (nType) {
|
||||
case 0:
|
||||
buttons = QMessageBox::Ok;
|
||||
break;
|
||||
case 1:
|
||||
buttons = QMessageBox::Ok | QMessageBox::Cancel;
|
||||
break;
|
||||
case 2:
|
||||
buttons = QMessageBox::Yes | QMessageBox::No;
|
||||
break;
|
||||
case 3:
|
||||
buttons = QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel;
|
||||
break;
|
||||
}
|
||||
box.setStandardButtons(buttons);
|
||||
|
||||
QCheckBox *checkBox = nullptr;
|
||||
if (oCheckbox.isObject()) {
|
||||
const auto oMsg = oCheckbox.property(QStringLiteral("cMsg"));
|
||||
QString msg = i18n("Do not show this message again");
|
||||
|
||||
if (oMsg.isString()) {
|
||||
msg = oMsg.toString();
|
||||
}
|
||||
|
||||
bool bInitialValue = false;
|
||||
const auto value = oCheckbox.property(QStringLiteral("bInitialValue"));
|
||||
if (value.isBool()) {
|
||||
bInitialValue = value.toBool();
|
||||
}
|
||||
checkBox = new QCheckBox(msg);
|
||||
checkBox->setChecked(bInitialValue);
|
||||
box.setCheckBox(checkBox);
|
||||
}
|
||||
|
||||
// halt timeout until the user has responded
|
||||
QMetaObject::invokeMethod(m_watchdogTimer, qOverload<>(&QTimer::stop));
|
||||
|
||||
int button = box.exec();
|
||||
|
||||
// restart max allowed time
|
||||
QMetaObject::invokeMethod(m_watchdogTimer, qOverload<>(&QTimer::start));
|
||||
|
||||
int ret = 0;
|
||||
|
||||
switch (button) {
|
||||
case QMessageBox::Ok:
|
||||
ret = 1;
|
||||
break;
|
||||
case QMessageBox::Cancel:
|
||||
ret = 2;
|
||||
break;
|
||||
case QMessageBox::No:
|
||||
ret = 3;
|
||||
break;
|
||||
case QMessageBox::Yes:
|
||||
ret = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
if (checkBox) {
|
||||
QJSValue(oCheckbox).setProperty(QStringLiteral("bAfterValue"), checkBox->isChecked());
|
||||
}
|
||||
|
||||
delete checkBox;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void JSApp::beep([[maybe_unused]] int nType)
|
||||
{
|
||||
QApplication::beep();
|
||||
}
|
||||
|
||||
QJSValue JSApp::getNthPlugInName(int nIndex) const
|
||||
{
|
||||
if (nIndex < 0 || nIndex >= s_num_fake_plugins) {
|
||||
return qjsEngine(this)->newErrorObject(QJSValue::TypeError, QStringLiteral("PlugIn index out of bounds"));
|
||||
}
|
||||
|
||||
const FakePluginInfo &info = s_fake_plugins[nIndex];
|
||||
return info.name;
|
||||
}
|
||||
|
||||
void JSApp::goBack()
|
||||
{
|
||||
if (!m_doc->m_parent->historyAtBegin()) {
|
||||
m_doc->m_parent->setPrevViewport();
|
||||
}
|
||||
}
|
||||
|
||||
void JSApp::goForward()
|
||||
{
|
||||
if (!m_doc->m_parent->historyAtEnd()) {
|
||||
m_doc->m_parent->setNextViewport();
|
||||
}
|
||||
}
|
||||
|
||||
// app.setInterval()
|
||||
QJSValue JSApp::setInterval(const QString &cExpr, int nMilliseconds)
|
||||
{
|
||||
QTimer *timer = new QTimer();
|
||||
|
||||
QObject::connect(timer, &QTimer::timeout, m_doc->m_parent, [=]() { m_doc->executeScript(cExpr); });
|
||||
|
||||
timer->start(nMilliseconds);
|
||||
|
||||
return JSApp::wrapTimer(timer);
|
||||
}
|
||||
|
||||
// app.clearInterval()
|
||||
void JSApp::clearInterval(const QJSValue &oInterval)
|
||||
{
|
||||
const int timerId = oInterval.property(OKULAR_TIMERID).toInt();
|
||||
QTimer *timer = g_timerCache->value(timerId);
|
||||
if (timer != nullptr) {
|
||||
timer->stop();
|
||||
g_timerCache->remove(timerId);
|
||||
delete timer;
|
||||
}
|
||||
}
|
||||
|
||||
// app.setTimeOut()
|
||||
QJSValue JSApp::setTimeOut(const QString &cExpr, int nMilliseconds)
|
||||
{
|
||||
QTimer *timer = new QTimer();
|
||||
timer->setSingleShot(true);
|
||||
|
||||
QObject::connect(timer, &QTimer::timeout, m_doc->m_parent, [=]() { m_doc->executeScript(cExpr); });
|
||||
|
||||
timer->start(nMilliseconds);
|
||||
|
||||
return JSApp::wrapTimer(timer);
|
||||
}
|
||||
|
||||
// app.clearTimeOut()
|
||||
void JSApp::clearTimeOut(const QJSValue &oTime)
|
||||
{
|
||||
const int timerId = oTime.property(OKULAR_TIMERID).toInt();
|
||||
QTimer *timer = g_timerCache->value(timerId);
|
||||
|
||||
if (timer != nullptr) {
|
||||
timer->stop();
|
||||
g_timerCache->remove(timerId);
|
||||
delete timer;
|
||||
}
|
||||
}
|
||||
|
||||
// app.popUpMenuEx()
|
||||
|
||||
bool JSApp::createPopUpMenuTree(int depth, QMenu *rootMenu, const QJSValue &arguments)
|
||||
{
|
||||
const int nArgs = arguments.property(QStringLiteral("length")).toInt();
|
||||
|
||||
// If no menu to add or if we got too deep in recursion
|
||||
if (nArgs == 0 || depth > 20) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nArgs; ++i) {
|
||||
const QJSValue item = arguments.property(i);
|
||||
const QString cName = item.property(QStringLiteral("cName")).toString();
|
||||
const QJSValue cResultProperty = item.property(QStringLiteral("cResult"));
|
||||
const QJSValue oSubMenu = item.property(QStringLiteral("oSubMenu"));
|
||||
|
||||
if (oSubMenu.isArray()) {
|
||||
QMenu *subMenu = rootMenu->addMenu(cName);
|
||||
createPopUpMenuTree(depth + 1, subMenu, oSubMenu);
|
||||
} else {
|
||||
QAction *a = rootMenu->addAction(cName);
|
||||
if (cResultProperty.isUndefined()) {
|
||||
a->setProperty(kResultProperty, cName);
|
||||
} else {
|
||||
a->setProperty(kResultProperty, cResultProperty.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QJSValue JSApp::okular_popUpMenuEx(const QJSValue &arguments)
|
||||
{
|
||||
QMenu m;
|
||||
|
||||
// Object name is used for tests.
|
||||
m.setObjectName(QStringLiteral("popUpMenuEx"));
|
||||
|
||||
if (!createPopUpMenuTree(0, &m, arguments)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
QAction *result = m.exec(QCursor::pos());
|
||||
return result ? result->property(kResultProperty).toString() : QString();
|
||||
}
|
||||
|
||||
JSApp::JSApp(DocumentPrivate *doc, QTimer *watchdogTimer, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_doc(doc)
|
||||
, m_watchdogTimer(watchdogTimer)
|
||||
{
|
||||
}
|
||||
|
||||
JSApp::~JSApp() = default;
|
||||
|
||||
QJSValue JSApp::wrapTimer(QTimer *timer) const
|
||||
{
|
||||
QJSValue timerObject = qjsEngine(this)->newObject();
|
||||
timerObject.setProperty(OKULAR_TIMERID, timer->timerId());
|
||||
|
||||
g_timerCache->insert(timer->timerId(), timer);
|
||||
|
||||
return timerObject;
|
||||
}
|
||||
|
||||
void JSApp::clearCachedFields()
|
||||
{
|
||||
if (g_timerCache) {
|
||||
qDeleteAll(g_timerCache->begin(), g_timerCache->end());
|
||||
g_timerCache->clear();
|
||||
}
|
||||
}
|
74
core/script/js_app_p.h
Normal file
74
core/script/js_app_p.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OKULAR_SCRIPT_JS_APP_P_H
|
||||
#define OKULAR_SCRIPT_JS_APP_P_H
|
||||
|
||||
#include <QJSValue>
|
||||
#include <QObject>
|
||||
#include <QPoint>
|
||||
|
||||
class QMenu;
|
||||
class QTimer;
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class DocumentPrivate;
|
||||
|
||||
class JSApp : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int formsVersion READ formsVersion CONSTANT)
|
||||
Q_PROPERTY(QString language READ language CONSTANT)
|
||||
Q_PROPERTY(int numPlugIns READ numPlugIns CONSTANT)
|
||||
Q_PROPERTY(QString platform READ platform CONSTANT)
|
||||
Q_PROPERTY(QJSValue plugIns READ plugIns CONSTANT)
|
||||
Q_PROPERTY(QStringList printColorProfiles READ printColorProfiles CONSTANT)
|
||||
Q_PROPERTY(QStringList printerNames READ printerNames CONSTANT)
|
||||
Q_PROPERTY(QString viewerType READ viewerType CONSTANT)
|
||||
Q_PROPERTY(QString viewerVariation READ viewerVariation CONSTANT)
|
||||
Q_PROPERTY(int viewerVersion READ viewerVersion CONSTANT)
|
||||
|
||||
public:
|
||||
explicit JSApp(DocumentPrivate *doc, QTimer *watchdogTimer, QObject *parent = nullptr);
|
||||
~JSApp() override;
|
||||
static void clearCachedFields();
|
||||
|
||||
int formsVersion() const;
|
||||
QString language() const;
|
||||
int numPlugIns() const;
|
||||
QString platform() const;
|
||||
QJSValue plugIns() const;
|
||||
QStringList printColorProfiles() const;
|
||||
QStringList printerNames() const;
|
||||
QString viewerType() const;
|
||||
QString viewerVariation() const;
|
||||
int viewerVersion() const;
|
||||
|
||||
Q_INVOKABLE int alert(const QJSValue &arguments);
|
||||
Q_INVOKABLE int alert(const QString &cMsg, int nIcon = 0, int nType = 0, const QString &cTitle = {}, const QJSValue &oDoc = {}, const QJSValue &oCheckbox = {});
|
||||
Q_INVOKABLE void beep(int nType = 4);
|
||||
Q_INVOKABLE QJSValue getNthPlugInName(int nIndex) const;
|
||||
Q_INVOKABLE void goBack();
|
||||
Q_INVOKABLE void goForward();
|
||||
Q_INVOKABLE QJSValue setInterval(const QString &cExpr, int nMilliseconds);
|
||||
Q_INVOKABLE void clearInterval(const QJSValue &oInterval);
|
||||
Q_INVOKABLE QJSValue setTimeOut(const QString &cExpr, int nMilliseconds);
|
||||
Q_INVOKABLE void clearTimeOut(const QJSValue &oTime);
|
||||
Q_INVOKABLE QJSValue okular_popUpMenuEx(const QJSValue &arguments);
|
||||
|
||||
private:
|
||||
QJSValue wrapTimer(QTimer *timer) const;
|
||||
static bool createPopUpMenuTree(int depth, QMenu *rootMenu, const QJSValue &arguments);
|
||||
|
||||
DocumentPrivate *m_doc = nullptr;
|
||||
QTimer *m_watchdogTimer = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
82
core/script/js_console.cpp
Normal file
82
core/script/js_console.cpp
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "js_console_p.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "../debug_p.h"
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
#ifdef OKULAR_JS_CONSOLE
|
||||
|
||||
#include <QLayout>
|
||||
#include <QPlainTextEdit>
|
||||
|
||||
#include <KDialog>
|
||||
#include <KStandardGuiItem>
|
||||
|
||||
K_GLOBAL_STATIC(KDialog, g_jsConsoleWindow)
|
||||
static QPlainTextEdit *g_jsConsoleLog = 0;
|
||||
|
||||
static void createConsoleWindow()
|
||||
{
|
||||
if (g_jsConsoleWindow.exists())
|
||||
return;
|
||||
|
||||
g_jsConsoleWindow->setButtons(KDialog::Close | KDialog::User1);
|
||||
g_jsConsoleWindow->setButtonGuiItem(KDialog::User1, KStandardGuiItem::clear());
|
||||
|
||||
QVBoxLayout *mainLay = new QVBoxLayout(g_jsConsoleWindow->mainWidget());
|
||||
mainLay->setContentsMargins(0, 0, 0, 0);
|
||||
g_jsConsoleLog = new QPlainTextEdit(g_jsConsoleWindow->mainWidget());
|
||||
g_jsConsoleLog->setReadOnly(true);
|
||||
mainLay->addWidget(g_jsConsoleLog);
|
||||
|
||||
QObject::connect(g_jsConsoleWindow, SIGNAL(closeClicked()), g_jsConsoleWindow, SLOT(close()));
|
||||
QObject::connect(g_jsConsoleWindow, SIGNAL(user1Clicked()), g_jsConsoleLog, SLOT(clear()));
|
||||
}
|
||||
#endif
|
||||
|
||||
void JSConsole::show()
|
||||
{
|
||||
#ifdef OKULAR_JS_CONSOLE
|
||||
createConsoleWindow();
|
||||
g_jsConsoleWindow->show();
|
||||
#endif
|
||||
}
|
||||
|
||||
void JSConsole::hide()
|
||||
{
|
||||
#ifdef OKULAR_JS_CONSOLE
|
||||
if (!g_jsConsoleWindow.exists())
|
||||
return;
|
||||
|
||||
g_jsConsoleWindow->hide();
|
||||
#endif
|
||||
}
|
||||
|
||||
void JSConsole::clear()
|
||||
{
|
||||
#ifdef OKULAR_JS_CONSOLE
|
||||
if (!g_jsConsoleWindow.exists())
|
||||
return;
|
||||
|
||||
g_jsConsoleLog->clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
void JSConsole::println(const QString &cMessage)
|
||||
{
|
||||
#ifdef OKULAR_JS_CONSOLE
|
||||
showConsole();
|
||||
g_jsConsoleLog->appendPlainText(cMessage);
|
||||
#else
|
||||
Q_UNUSED(cMessage);
|
||||
#endif
|
||||
}
|
27
core/script/js_console_p.h
Normal file
27
core/script/js_console_p.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OKULAR_SCRIPT_JS_CONSOLE_P_H
|
||||
#define OKULAR_SCRIPT_JS_CONSOLE_P_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class JSConsole : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Q_INVOKABLE void clear();
|
||||
Q_INVOKABLE void hide();
|
||||
Q_INVOKABLE void println(const QString &cMessage);
|
||||
Q_INVOKABLE void show();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
58
core/script/js_data.cpp
Normal file
58
core/script/js_data.cpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "js_data_p.h"
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
#include "../document.h"
|
||||
#include "js_display_p.h"
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
QDateTime JSData::creationDate() const
|
||||
{
|
||||
return m_file->creationDate();
|
||||
}
|
||||
|
||||
QString JSData::description() const
|
||||
{
|
||||
return m_file->description();
|
||||
}
|
||||
|
||||
QString JSData::MIMEType() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
}
|
||||
|
||||
QDateTime JSData::modDate() const
|
||||
{
|
||||
return m_file->modificationDate();
|
||||
}
|
||||
|
||||
QString JSData::name() const
|
||||
{
|
||||
return m_file->name();
|
||||
}
|
||||
|
||||
QString JSData::path() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
}
|
||||
|
||||
int JSData::size() const
|
||||
{
|
||||
return m_file->size();
|
||||
}
|
||||
|
||||
JSData::JSData(EmbeddedFile *f, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_file(f)
|
||||
{
|
||||
}
|
||||
|
||||
JSData::~JSData() = default;
|
46
core/script/js_data_p.h
Normal file
46
core/script/js_data_p.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OKULAR_SCRIPT_JS_DATA_P_H
|
||||
#define OKULAR_SCRIPT_JS_DATA_P_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class EmbeddedFile;
|
||||
|
||||
class JSData : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QDateTime creationDate READ creationDate CONSTANT)
|
||||
Q_PROPERTY(QString description READ description CONSTANT)
|
||||
Q_PROPERTY(QString MIMEType READ MIMEType CONSTANT)
|
||||
Q_PROPERTY(QDateTime modDate READ modDate CONSTANT)
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
Q_PROPERTY(QString path READ path CONSTANT)
|
||||
Q_PROPERTY(int size READ size CONSTANT)
|
||||
|
||||
public:
|
||||
explicit JSData(EmbeddedFile *f, QObject *parent = nullptr);
|
||||
~JSData() override;
|
||||
|
||||
QDateTime creationDate() const;
|
||||
QString description() const;
|
||||
QString MIMEType() const;
|
||||
QDateTime modDate() const;
|
||||
QString name() const;
|
||||
QString path() const;
|
||||
int size() const;
|
||||
|
||||
private:
|
||||
EmbeddedFile *m_file = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
36
core/script/js_display.cpp
Normal file
36
core/script/js_display.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2019 João Netto <joaonetto901@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "../form.h"
|
||||
#include "js_display_p.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
// display.hidden
|
||||
int JSDisplay::hidden() const
|
||||
{
|
||||
return FormDisplay::FormHidden;
|
||||
}
|
||||
|
||||
// display.visible
|
||||
int JSDisplay::visible() const
|
||||
{
|
||||
return FormDisplay::FormVisible;
|
||||
}
|
||||
|
||||
// display.noView
|
||||
int JSDisplay::noView() const
|
||||
{
|
||||
return FormDisplay::FormNoView;
|
||||
}
|
||||
|
||||
// display.noPrint
|
||||
int JSDisplay::noPrint() const
|
||||
{
|
||||
return FormDisplay::FormNoPrint;
|
||||
}
|
35
core/script/js_display_p.h
Normal file
35
core/script/js_display_p.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2019 João Netto <joaonetto901@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OKULAR_SCRIPT_JS_DISPLAY_P_H
|
||||
#define OKULAR_SCRIPT_JS_DISPLAY_P_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
/**
|
||||
* The display types of the field.
|
||||
*/
|
||||
enum FormDisplay { FormVisible, FormHidden, FormNoPrint, FormNoView };
|
||||
|
||||
class JSDisplay : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int hidden READ hidden CONSTANT)
|
||||
Q_PROPERTY(int visible READ visible CONSTANT)
|
||||
Q_PROPERTY(int noView READ noView CONSTANT)
|
||||
Q_PROPERTY(int noPrint READ noPrint CONSTANT)
|
||||
public:
|
||||
int hidden() const;
|
||||
int visible() const;
|
||||
int noView() const;
|
||||
int noPrint() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
242
core/script/js_document.cpp
Normal file
242
core/script/js_document.cpp
Normal file
|
@ -0,0 +1,242 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "js_document_p.h"
|
||||
|
||||
#include <qwidget.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QJSEngine>
|
||||
#include <assert.h>
|
||||
|
||||
#include "../document_p.h"
|
||||
#include "../form.h"
|
||||
#include "../page.h"
|
||||
#include "js_data_p.h"
|
||||
#include "js_field_p.h"
|
||||
#include "js_ocg_p.h"
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
// Document.numPages
|
||||
int JSDocument::numPages() const
|
||||
{
|
||||
return m_doc->m_pagesVector.count();
|
||||
}
|
||||
|
||||
// Document.pageNum (getter)
|
||||
int JSDocument::pageNum() const
|
||||
{
|
||||
return m_doc->m_parent->currentPage();
|
||||
}
|
||||
|
||||
// Document.pageNum (setter)
|
||||
void JSDocument::setPageNum(int page)
|
||||
{
|
||||
if (page == (int)m_doc->m_parent->currentPage()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_doc->m_parent->setViewportPage(page);
|
||||
}
|
||||
|
||||
// Document.documentFileName
|
||||
QString JSDocument::documentFileName() const
|
||||
{
|
||||
return m_doc->m_url.fileName();
|
||||
}
|
||||
|
||||
// Document.filesize
|
||||
int JSDocument::filesize() const
|
||||
{
|
||||
return m_doc->m_docSize;
|
||||
}
|
||||
|
||||
// Document.path
|
||||
QString JSDocument::path() const
|
||||
{
|
||||
return m_doc->m_url.toDisplayString(QUrl::PreferLocalFile);
|
||||
}
|
||||
|
||||
// Document.URL
|
||||
QString JSDocument::URL() const
|
||||
{
|
||||
return m_doc->m_url.toDisplayString();
|
||||
}
|
||||
|
||||
// Document.permStatusReady
|
||||
bool JSDocument::permStatusReady() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Document.dataObjects
|
||||
QJSValue JSDocument::dataObjects() const
|
||||
{
|
||||
const QList<EmbeddedFile *> *files = m_doc->m_generator->embeddedFiles();
|
||||
|
||||
QJSValue dataObjects = qjsEngine(this)->newArray(files ? files->count() : 0);
|
||||
if (files) {
|
||||
QList<EmbeddedFile *>::ConstIterator it = files->begin(), itEnd = files->end();
|
||||
for (int i = 0; it != itEnd; ++it, ++i) {
|
||||
QJSValue newdata = qjsEngine(this)->newQObject(new JSData(*it));
|
||||
dataObjects.setProperty(i, newdata);
|
||||
}
|
||||
}
|
||||
return dataObjects;
|
||||
}
|
||||
|
||||
// Document.external
|
||||
bool JSDocument::external() const
|
||||
{
|
||||
QWidget *widget = m_doc->m_widget;
|
||||
|
||||
const bool isShell = (widget && widget->parentWidget() && widget->parentWidget()->objectName().startsWith(QLatin1String("okular::Shell")));
|
||||
return !isShell;
|
||||
}
|
||||
|
||||
// Document.numFields
|
||||
int JSDocument::numFields() const
|
||||
{
|
||||
unsigned int numFields = 0;
|
||||
|
||||
for (const Page *pIt : std::as_const(m_doc->m_pagesVector)) {
|
||||
numFields += pIt->formFields().size();
|
||||
}
|
||||
|
||||
return numFields;
|
||||
}
|
||||
|
||||
QJSValue JSDocument::info() const
|
||||
{
|
||||
QJSValue obj = qjsEngine(this)->newObject();
|
||||
QSet<DocumentInfo::Key> keys;
|
||||
keys << DocumentInfo::Title << DocumentInfo::Author << DocumentInfo::Subject << DocumentInfo::Keywords << DocumentInfo::Creator << DocumentInfo::Producer;
|
||||
const DocumentInfo docinfo = m_doc->m_parent->documentInfo(keys);
|
||||
#define KEY_GET(key, property) \
|
||||
do { \
|
||||
const QString data = docinfo.get(key); \
|
||||
if (!data.isEmpty()) { \
|
||||
obj.setProperty(QStringLiteral(property), data); \
|
||||
obj.setProperty(QStringLiteral(property).toLower(), data); \
|
||||
} \
|
||||
} while (0);
|
||||
KEY_GET(DocumentInfo::Title, "Title");
|
||||
KEY_GET(DocumentInfo::Author, "Author");
|
||||
KEY_GET(DocumentInfo::Subject, "Subject");
|
||||
KEY_GET(DocumentInfo::Keywords, "Keywords");
|
||||
KEY_GET(DocumentInfo::Creator, "Creator");
|
||||
KEY_GET(DocumentInfo::Producer, "Producer");
|
||||
#undef KEY_GET
|
||||
return obj;
|
||||
}
|
||||
|
||||
#define DOCINFO_GET_METHOD(key, name) \
|
||||
QString JSDocument::name() const \
|
||||
{ \
|
||||
const DocumentInfo docinfo = m_doc->m_parent->documentInfo(QSet<DocumentInfo::Key>() << key); \
|
||||
return docinfo.get(key); \
|
||||
}
|
||||
|
||||
DOCINFO_GET_METHOD(DocumentInfo::Author, author)
|
||||
DOCINFO_GET_METHOD(DocumentInfo::Creator, creator)
|
||||
DOCINFO_GET_METHOD(DocumentInfo::Keywords, keywords)
|
||||
DOCINFO_GET_METHOD(DocumentInfo::Producer, producer)
|
||||
DOCINFO_GET_METHOD(DocumentInfo::Title, title)
|
||||
DOCINFO_GET_METHOD(DocumentInfo::Subject, subject)
|
||||
|
||||
#undef DOCINFO_GET_METHOD
|
||||
|
||||
// Document.getField()
|
||||
QJSValue JSDocument::getField(const QString &cName) const
|
||||
{
|
||||
QVector<Page *>::const_iterator pIt = m_doc->m_pagesVector.constBegin(), pEnd = m_doc->m_pagesVector.constEnd();
|
||||
for (; pIt != pEnd; ++pIt) {
|
||||
const QList<Okular::FormField *> pageFields = (*pIt)->formFields();
|
||||
for (FormField *form : pageFields) {
|
||||
if (form->fullyQualifiedName() == cName) {
|
||||
return JSField::wrapField(qjsEngine(this), form, *pIt);
|
||||
}
|
||||
}
|
||||
}
|
||||
return QJSValue(QJSValue::UndefinedValue);
|
||||
}
|
||||
|
||||
// Document.getPageLabel()
|
||||
QString JSDocument::getPageLabel(int nPage) const
|
||||
{
|
||||
Page *p = m_doc->m_pagesVector.value(nPage);
|
||||
return p ? p->label() : QString();
|
||||
}
|
||||
|
||||
// Document.getPageRotation()
|
||||
int JSDocument::getPageRotation(int nPage) const
|
||||
{
|
||||
Page *p = m_doc->m_pagesVector.value(nPage);
|
||||
return p ? p->orientation() * 90 : 0;
|
||||
}
|
||||
|
||||
// Document.gotoNamedDest()
|
||||
void JSDocument::gotoNamedDest(const QString &cName) const
|
||||
{
|
||||
DocumentViewport viewport(m_doc->m_generator->metaData(QStringLiteral("NamedViewport"), cName).toString());
|
||||
if (viewport.isValid()) {
|
||||
m_doc->m_parent->setViewport(viewport);
|
||||
}
|
||||
}
|
||||
|
||||
// Document.syncAnnotScan()
|
||||
void JSDocument::syncAnnotScan() const
|
||||
{
|
||||
}
|
||||
|
||||
// Document.getNthFieldName
|
||||
QJSValue JSDocument::getNthFieldName(int nIndex) const
|
||||
{
|
||||
for (const Page *pIt : std::as_const(m_doc->m_pagesVector)) {
|
||||
const QList<Okular::FormField *> pageFields = pIt->formFields();
|
||||
|
||||
if (nIndex < pageFields.size()) {
|
||||
const Okular::FormField *form = pageFields[nIndex];
|
||||
|
||||
return form->fullyQualifiedName();
|
||||
}
|
||||
|
||||
nIndex -= pageFields.size();
|
||||
}
|
||||
|
||||
return QJSValue(QJSValue::UndefinedValue);
|
||||
}
|
||||
|
||||
QJSValue JSDocument::getOCGs([[maybe_unused]] int nPage) const
|
||||
{
|
||||
QAbstractItemModel *model = m_doc->m_parent->layersModel();
|
||||
|
||||
QJSValue array = qjsEngine(this)->newArray(model->rowCount());
|
||||
|
||||
for (int i = 0; i < model->rowCount(); ++i) {
|
||||
for (int j = 0; j < model->columnCount(); ++j) {
|
||||
const QModelIndex index = model->index(i, j);
|
||||
|
||||
QJSValue item = qjsEngine(this)->newQObject(new JSOCG(model, i, j));
|
||||
item.setProperty(QStringLiteral("name"), model->data(index, Qt::DisplayRole).toString());
|
||||
item.setProperty(QStringLiteral("initState"), model->data(index, Qt::CheckStateRole).toBool());
|
||||
|
||||
array.setProperty(i, item);
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
JSDocument::JSDocument(DocumentPrivate *doc, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_doc(doc)
|
||||
{
|
||||
}
|
||||
|
||||
JSDocument::~JSDocument() = default;
|
79
core/script/js_document_p.h
Normal file
79
core/script/js_document_p.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OKULAR_SCRIPT_JS_DOCUMENT_P_H
|
||||
#define OKULAR_SCRIPT_JS_DOCUMENT_P_H
|
||||
|
||||
#include <QJSValue>
|
||||
#include <QObject>
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class DocumentPrivate;
|
||||
|
||||
class JSDocument : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int numPages READ numPages CONSTANT)
|
||||
Q_PROPERTY(int pageNum READ pageNum WRITE setPageNum) // clazy:exclude=qproperty-without-notify
|
||||
Q_PROPERTY(QString documentFileName READ documentFileName CONSTANT)
|
||||
Q_PROPERTY(int filesize READ filesize CONSTANT)
|
||||
Q_PROPERTY(QString path READ path CONSTANT)
|
||||
Q_PROPERTY(QString URL READ URL CONSTANT)
|
||||
Q_PROPERTY(bool permStatusReady READ permStatusReady CONSTANT)
|
||||
Q_PROPERTY(QJSValue dataObjects READ dataObjects CONSTANT)
|
||||
Q_PROPERTY(bool external READ external CONSTANT)
|
||||
Q_PROPERTY(int numFields READ numFields CONSTANT)
|
||||
|
||||
// info properties
|
||||
Q_PROPERTY(QJSValue info READ info CONSTANT)
|
||||
Q_PROPERTY(QString author READ author CONSTANT)
|
||||
Q_PROPERTY(QString creator READ creator CONSTANT)
|
||||
Q_PROPERTY(QString keywords READ keywords CONSTANT)
|
||||
Q_PROPERTY(QString producer READ producer CONSTANT)
|
||||
Q_PROPERTY(QString title READ title CONSTANT)
|
||||
Q_PROPERTY(QString subject READ subject CONSTANT)
|
||||
|
||||
public:
|
||||
explicit JSDocument(DocumentPrivate *doc, QObject *parent = nullptr);
|
||||
~JSDocument() override;
|
||||
|
||||
int numPages() const;
|
||||
int pageNum() const;
|
||||
void setPageNum(int pageNum);
|
||||
QString documentFileName() const;
|
||||
int filesize() const;
|
||||
QString path() const;
|
||||
QString URL() const;
|
||||
bool permStatusReady() const;
|
||||
QJSValue dataObjects() const;
|
||||
bool external() const;
|
||||
int numFields() const;
|
||||
|
||||
QJSValue info() const;
|
||||
QString author() const;
|
||||
QString creator() const;
|
||||
QString keywords() const;
|
||||
QString producer() const;
|
||||
QString title() const;
|
||||
QString subject() const;
|
||||
|
||||
Q_INVOKABLE QJSValue getField(const QString &cName) const;
|
||||
Q_INVOKABLE QString getPageLabel(int nPage) const;
|
||||
Q_INVOKABLE int getPageRotation(int nPage) const;
|
||||
Q_INVOKABLE void gotoNamedDest(const QString &cName) const;
|
||||
Q_INVOKABLE void syncAnnotScan() const;
|
||||
Q_INVOKABLE QJSValue getNthFieldName(int nIndex) const;
|
||||
Q_INVOKABLE QJSValue getOCGs(int nPage = -1) const;
|
||||
|
||||
private:
|
||||
DocumentPrivate *m_doc = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
122
core/script/js_event.cpp
Normal file
122
core/script/js_event.cpp
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2018 Intevation GmbH <intevation@intevation.de>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "js_event_p.h"
|
||||
|
||||
#include "event_p.h"
|
||||
#include "js_field_p.h"
|
||||
|
||||
#include <QJSEngine>
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
// Event.name
|
||||
QString JSEvent::name() const
|
||||
{
|
||||
return m_event->name();
|
||||
}
|
||||
|
||||
// Event.type
|
||||
QString JSEvent::type() const
|
||||
{
|
||||
return m_event->type();
|
||||
}
|
||||
|
||||
// Event.targetName (getter)
|
||||
QString JSEvent::targetName() const
|
||||
{
|
||||
return m_event->targetName();
|
||||
}
|
||||
|
||||
// Event.targetName (setter)
|
||||
void JSEvent::setTargetName(const QString &targetName)
|
||||
{
|
||||
m_event->setTargetName(targetName);
|
||||
}
|
||||
|
||||
// Event.shift
|
||||
bool JSEvent::shift() const
|
||||
{
|
||||
return m_event->shiftModifier();
|
||||
}
|
||||
|
||||
// Event.source
|
||||
QJSValue JSEvent::source() const
|
||||
{
|
||||
if (m_event->eventType() == Event::FieldCalculate) {
|
||||
FormField *src = m_event->source();
|
||||
if (src) {
|
||||
return JSField::wrapField(qjsEngine(this), src, m_event->sourcePage());
|
||||
}
|
||||
}
|
||||
return QJSValue(QJSValue::UndefinedValue);
|
||||
}
|
||||
|
||||
// Event.target
|
||||
QJSValue JSEvent::target() const
|
||||
{
|
||||
switch (m_event->eventType()) {
|
||||
case Event::FieldCalculate:
|
||||
case Event::FieldFormat:
|
||||
case Event::FieldKeystroke:
|
||||
case Event::FieldFocus:
|
||||
case Event::FieldValidate:
|
||||
case Event::FieldMouseUp: {
|
||||
FormField *target = static_cast<FormField *>(m_event->target());
|
||||
if (target) {
|
||||
return JSField::wrapField(qjsEngine(this), target, m_event->targetPage());
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
}
|
||||
}
|
||||
return QJSValue(QJSValue::UndefinedValue);
|
||||
}
|
||||
|
||||
// Event.value (getter)
|
||||
QJSValue JSEvent::value() const
|
||||
{
|
||||
return m_event->value().toString();
|
||||
}
|
||||
|
||||
// Event.value (setter)
|
||||
void JSEvent::setValue(const QJSValue &value)
|
||||
{
|
||||
m_event->setValue(QVariant(value.toString()));
|
||||
}
|
||||
|
||||
// Event.rc (getter)
|
||||
bool JSEvent::returnCode() const
|
||||
{
|
||||
return m_event->returnCode();
|
||||
}
|
||||
|
||||
// Event.rc (setter)
|
||||
void JSEvent::setReturnCode(bool rc)
|
||||
{
|
||||
m_event->setReturnCode(rc);
|
||||
}
|
||||
|
||||
// Event.willCommit (getter)
|
||||
bool JSEvent::willCommit() const
|
||||
{
|
||||
return m_event->willCommit();
|
||||
}
|
||||
|
||||
// Event.change (getter)
|
||||
QString JSEvent::change() const
|
||||
{
|
||||
return m_event->change();
|
||||
}
|
||||
|
||||
JSEvent::JSEvent(Event *event, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_event(event)
|
||||
{
|
||||
}
|
||||
|
||||
JSEvent::~JSEvent() = default;
|
55
core/script/js_event_p.h
Normal file
55
core/script/js_event_p.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2018 Intevation GmbH <intevation@intevation.de>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OKULAR_SCRIPT_JS_EVENT_P_H
|
||||
#define OKULAR_SCRIPT_JS_EVENT_P_H
|
||||
|
||||
#include <QJSValue>
|
||||
#include <QObject>
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class Event;
|
||||
|
||||
class JSEvent : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
Q_PROPERTY(QString type READ type CONSTANT)
|
||||
Q_PROPERTY(QString targetName READ targetName WRITE setTargetName) // clazy:exclude=qproperty-without-notify
|
||||
Q_PROPERTY(bool shift READ shift CONSTANT)
|
||||
Q_PROPERTY(QJSValue source READ source CONSTANT)
|
||||
Q_PROPERTY(QJSValue target READ target CONSTANT)
|
||||
Q_PROPERTY(bool willCommit READ willCommit CONSTANT)
|
||||
Q_PROPERTY(QJSValue value READ value WRITE setValue) // clazy:exclude=qproperty-without-notify
|
||||
Q_PROPERTY(bool rc READ returnCode WRITE setReturnCode) // clazy:exclude=qproperty-without-notify
|
||||
Q_PROPERTY(QString change READ change CONSTANT)
|
||||
|
||||
public:
|
||||
explicit JSEvent(Event *event, QObject *parent = nullptr);
|
||||
~JSEvent() override;
|
||||
|
||||
QString name() const;
|
||||
QString type() const;
|
||||
QString targetName() const;
|
||||
void setTargetName(const QString &targetName);
|
||||
bool shift() const;
|
||||
QJSValue source() const;
|
||||
QJSValue target() const;
|
||||
bool willCommit() const;
|
||||
QJSValue value() const;
|
||||
void setValue(const QJSValue &value);
|
||||
bool returnCode() const;
|
||||
void setReturnCode(bool rc);
|
||||
QString change() const;
|
||||
|
||||
private:
|
||||
Event *m_event = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
304
core/script/js_field.cpp
Normal file
304
core/script/js_field.cpp
Normal file
|
@ -0,0 +1,304 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "js_field_p.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QHash>
|
||||
#include <QJSEngine>
|
||||
#include <QTimer>
|
||||
|
||||
#include "../debug_p.h"
|
||||
#include "../document_p.h"
|
||||
#include "../form.h"
|
||||
#include "../page.h"
|
||||
#include "../page_p.h"
|
||||
#include "js_display_p.h"
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
#define OKULAR_NAME QStringLiteral("okular_name")
|
||||
|
||||
typedef QHash<FormField *, Page *> FormCache;
|
||||
Q_GLOBAL_STATIC(FormCache, g_fieldCache)
|
||||
typedef QHash<QString, FormField *> ButtonCache;
|
||||
Q_GLOBAL_STATIC(ButtonCache, g_buttonCache)
|
||||
|
||||
// Helper for modified fields
|
||||
static void updateField(FormField *field)
|
||||
{
|
||||
Page *page = g_fieldCache->value(field);
|
||||
if (page) {
|
||||
Document *doc = PagePrivate::get(page)->m_doc->m_parent;
|
||||
const int pageNumber = page->number();
|
||||
QTimer::singleShot(0, doc, [doc, pageNumber] { doc->refreshPixmaps(pageNumber); });
|
||||
Q_EMIT doc->refreshFormWidget(field);
|
||||
} else {
|
||||
qWarning() << "Could not get page of field" << field;
|
||||
}
|
||||
}
|
||||
|
||||
// Field.doc
|
||||
QJSValue JSField::doc() const
|
||||
{
|
||||
return qjsEngine(this)->globalObject();
|
||||
}
|
||||
|
||||
// Field.name
|
||||
QString JSField::name() const
|
||||
{
|
||||
return m_field->fullyQualifiedName();
|
||||
}
|
||||
|
||||
// Field.readonly (getter)
|
||||
bool JSField::readonly() const
|
||||
{
|
||||
return m_field->isReadOnly();
|
||||
}
|
||||
|
||||
// Field.readonly (setter)
|
||||
void JSField::setReadonly(bool readonly)
|
||||
{
|
||||
m_field->setReadOnly(readonly);
|
||||
|
||||
updateField(m_field);
|
||||
}
|
||||
|
||||
static QString fieldGetTypeHelper(const FormField *field)
|
||||
{
|
||||
switch (field->type()) {
|
||||
case FormField::FormButton: {
|
||||
const FormFieldButton *button = static_cast<const FormFieldButton *>(field);
|
||||
switch (button->buttonType()) {
|
||||
case FormFieldButton::Push:
|
||||
return QStringLiteral("button");
|
||||
case FormFieldButton::CheckBox:
|
||||
return QStringLiteral("checkbox");
|
||||
case FormFieldButton::Radio:
|
||||
return QStringLiteral("radiobutton");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FormField::FormText:
|
||||
return QStringLiteral("text");
|
||||
case FormField::FormChoice: {
|
||||
const FormFieldChoice *choice = static_cast<const FormFieldChoice *>(field);
|
||||
switch (choice->choiceType()) {
|
||||
case FormFieldChoice::ComboBox:
|
||||
return QStringLiteral("combobox");
|
||||
case FormFieldChoice::ListBox:
|
||||
return QStringLiteral("listbox");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FormField::FormSignature:
|
||||
return QStringLiteral("signature");
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
// Field.type
|
||||
QString JSField::type() const
|
||||
{
|
||||
return fieldGetTypeHelper(m_field);
|
||||
}
|
||||
|
||||
QJSValue JSField::fieldGetValueCore(bool asString) const
|
||||
{
|
||||
QJSValue result(QJSValue::UndefinedValue);
|
||||
|
||||
switch (m_field->type()) {
|
||||
case FormField::FormButton: {
|
||||
const FormFieldButton *button = static_cast<const FormFieldButton *>(m_field);
|
||||
if (button->state()) {
|
||||
result = QStringLiteral("Yes");
|
||||
} else {
|
||||
result = QStringLiteral("Off");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FormField::FormText: {
|
||||
const FormFieldText *text = static_cast<const FormFieldText *>(m_field);
|
||||
const QLocale locale;
|
||||
bool ok;
|
||||
const double textAsNumber = locale.toDouble(text->text(), &ok);
|
||||
if (ok && !asString) {
|
||||
result = textAsNumber;
|
||||
} else {
|
||||
result = text->text();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FormField::FormChoice: {
|
||||
const FormFieldChoice *choice = static_cast<const FormFieldChoice *>(m_field);
|
||||
const QList<int> currentChoices = choice->currentChoices();
|
||||
if (currentChoices.count() == 1) {
|
||||
result = choice->exportValueForChoice(choice->choices().at(currentChoices[0]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FormField::FormSignature: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
qCDebug(OkularCoreDebug) << "fieldGetValueCore:"
|
||||
<< " Field: " << m_field->fullyQualifiedName() << " Type: " << fieldGetTypeHelper(m_field) << " Value: " << result.toString() << (result.isString() ? "(as string)" : "");
|
||||
return result;
|
||||
}
|
||||
// Field.value (getter)
|
||||
QJSValue JSField::value() const
|
||||
{
|
||||
return fieldGetValueCore(/*asString*/ false);
|
||||
}
|
||||
|
||||
// Field.value (setter)
|
||||
void JSField::setValue(const QJSValue &value)
|
||||
{
|
||||
qCDebug(OkularCoreDebug) << "fieldSetValue: Field: " << m_field->fullyQualifiedName() << " Type: " << fieldGetTypeHelper(m_field) << " Value: " << value.toString();
|
||||
switch (m_field->type()) {
|
||||
case FormField::FormButton: {
|
||||
FormFieldButton *button = static_cast<FormFieldButton *>(m_field);
|
||||
const QString text = value.toString();
|
||||
if (text == QStringLiteral("Yes")) {
|
||||
button->setState(true);
|
||||
updateField(m_field);
|
||||
} else if (text == QStringLiteral("Off")) {
|
||||
button->setState(false);
|
||||
updateField(m_field);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FormField::FormText: {
|
||||
FormFieldText *textField = static_cast<FormFieldText *>(m_field);
|
||||
const QString text = value.toString();
|
||||
if (text != textField->text()) {
|
||||
textField->setText(text);
|
||||
updateField(m_field);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FormField::FormChoice: {
|
||||
FormFieldChoice *choice = static_cast<FormFieldChoice *>(m_field);
|
||||
Q_UNUSED(choice); // ###
|
||||
break;
|
||||
}
|
||||
case FormField::FormSignature: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Field.valueAsString (getter)
|
||||
QJSValue JSField::valueAsString() const
|
||||
{
|
||||
return fieldGetValueCore(/*asString*/ true);
|
||||
}
|
||||
|
||||
// Field.hidden (getter)
|
||||
bool JSField::hidden() const
|
||||
{
|
||||
return !m_field->isVisible();
|
||||
}
|
||||
|
||||
// Field.hidden (setter)
|
||||
void JSField::setHidden(bool hidden)
|
||||
{
|
||||
m_field->setVisible(!hidden);
|
||||
|
||||
updateField(m_field);
|
||||
}
|
||||
|
||||
// Field.display (getter)
|
||||
int JSField::display() const
|
||||
{
|
||||
bool visible = m_field->isVisible();
|
||||
if (visible) {
|
||||
return m_field->isPrintable() ? FormDisplay::FormVisible : FormDisplay::FormNoPrint;
|
||||
}
|
||||
return m_field->isPrintable() ? FormDisplay::FormNoView : FormDisplay::FormHidden;
|
||||
}
|
||||
|
||||
// Field.display (setter)
|
||||
void JSField::setDisplay(int display)
|
||||
{
|
||||
switch (display) {
|
||||
case FormDisplay::FormVisible:
|
||||
m_field->setVisible(true);
|
||||
m_field->setPrintable(true);
|
||||
break;
|
||||
case FormDisplay::FormHidden:
|
||||
m_field->setVisible(false);
|
||||
m_field->setPrintable(false);
|
||||
break;
|
||||
case FormDisplay::FormNoPrint:
|
||||
m_field->setVisible(true);
|
||||
m_field->setPrintable(false);
|
||||
break;
|
||||
case FormDisplay::FormNoView:
|
||||
m_field->setVisible(false);
|
||||
m_field->setPrintable(true);
|
||||
break;
|
||||
}
|
||||
updateField(m_field);
|
||||
}
|
||||
|
||||
// Instead of getting the Icon, we pick the field.
|
||||
QJSValue JSField::buttonGetIcon([[maybe_unused]] int nFace) const
|
||||
{
|
||||
QJSValue fieldObject = qjsEngine(this)->newObject();
|
||||
fieldObject.setProperty(OKULAR_NAME, m_field->fullyQualifiedName());
|
||||
g_buttonCache->insert(m_field->fullyQualifiedName(), m_field);
|
||||
|
||||
return fieldObject;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now we send to the button what Icon should be drawn on it
|
||||
*/
|
||||
void JSField::buttonSetIcon(const QJSValue &oIcon, [[maybe_unused]] int nFace)
|
||||
{
|
||||
const QString fieldName = oIcon.property(OKULAR_NAME).toString();
|
||||
|
||||
if (m_field->type() == Okular::FormField::FormButton) {
|
||||
FormFieldButton *button = static_cast<FormFieldButton *>(m_field);
|
||||
const auto formField = g_buttonCache->value(fieldName);
|
||||
if (formField) {
|
||||
button->setIcon(formField);
|
||||
}
|
||||
}
|
||||
|
||||
updateField(m_field);
|
||||
}
|
||||
|
||||
JSField::JSField(FormField *field, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_field(field)
|
||||
{
|
||||
}
|
||||
|
||||
JSField::~JSField() = default;
|
||||
|
||||
QJSValue JSField::wrapField(QJSEngine *engine, FormField *field, Page *page)
|
||||
{
|
||||
// ### cache unique wrapper
|
||||
QJSValue f = engine->newQObject(new JSField(field));
|
||||
f.setProperty(QStringLiteral("page"), page->number());
|
||||
g_fieldCache->insert(field, page);
|
||||
return f;
|
||||
}
|
||||
|
||||
void JSField::clearCachedFields()
|
||||
{
|
||||
if (g_fieldCache.exists()) {
|
||||
g_fieldCache->clear();
|
||||
}
|
||||
|
||||
if (g_buttonCache.exists()) {
|
||||
g_buttonCache->clear();
|
||||
}
|
||||
}
|
62
core/script/js_field_p.h
Normal file
62
core/script/js_field_p.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OKULAR_SCRIPT_JS_FIELD_P_H
|
||||
#define OKULAR_SCRIPT_JS_FIELD_P_H
|
||||
|
||||
#include <QJSValue>
|
||||
#include <QObject>
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class FormField;
|
||||
class Page;
|
||||
|
||||
class JSField : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QJSValue doc READ doc CONSTANT)
|
||||
Q_PROPERTY(QString name READ name CONSTANT)
|
||||
Q_PROPERTY(bool readonly READ readonly WRITE setReadonly) // clazy:exclude=qproperty-without-notify
|
||||
Q_PROPERTY(QString type READ type CONSTANT)
|
||||
Q_PROPERTY(QJSValue value READ value WRITE setValue) // clazy:exclude=qproperty-without-notify
|
||||
Q_PROPERTY(QJSValue valueAsString READ valueAsString) // clazy:exclude=qproperty-without-notify
|
||||
Q_PROPERTY(bool hidden READ hidden WRITE setHidden) // clazy:exclude=qproperty-without-notify
|
||||
Q_PROPERTY(int display READ display WRITE setDisplay) // clazy:exclude=qproperty-without-notify
|
||||
|
||||
public:
|
||||
explicit JSField(FormField *field, QObject *parent = nullptr);
|
||||
~JSField() override;
|
||||
|
||||
static QJSValue wrapField(QJSEngine *engine, FormField *field, Page *page);
|
||||
static void clearCachedFields();
|
||||
|
||||
QJSValue doc() const;
|
||||
QString name() const;
|
||||
bool readonly() const;
|
||||
void setReadonly(bool readonly);
|
||||
int display() const;
|
||||
void setDisplay(int display);
|
||||
QString type() const;
|
||||
QJSValue value() const;
|
||||
void setValue(const QJSValue &value);
|
||||
QJSValue valueAsString() const;
|
||||
bool hidden() const;
|
||||
void setHidden(bool hidden);
|
||||
|
||||
Q_INVOKABLE QJSValue buttonGetIcon(int nFace = 0) const;
|
||||
Q_INVOKABLE void buttonSetIcon(const QJSValue &oIcon, int nFace = 0);
|
||||
|
||||
private:
|
||||
QJSValue fieldGetValueCore(bool asString) const;
|
||||
|
||||
FormField *m_field = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
42
core/script/js_fullscreen.cpp
Normal file
42
core/script/js_fullscreen.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "js_fullscreen_p.h"
|
||||
|
||||
#include "settings_core.h"
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
bool JSFullscreen::loop() const
|
||||
{
|
||||
return SettingsCore::slidesLoop();
|
||||
}
|
||||
|
||||
void JSFullscreen::setLoop(bool loop)
|
||||
{
|
||||
SettingsCore::setSlidesLoop(loop);
|
||||
}
|
||||
|
||||
bool JSFullscreen::useTimer() const
|
||||
{
|
||||
return SettingsCore::slidesAdvance();
|
||||
}
|
||||
|
||||
void JSFullscreen::setUseTimer(bool use)
|
||||
{
|
||||
SettingsCore::setSlidesAdvance(use);
|
||||
}
|
||||
|
||||
int JSFullscreen::timeDelay() const
|
||||
{
|
||||
return SettingsCore::slidesAdvanceTime();
|
||||
}
|
||||
|
||||
void JSFullscreen::setTimeDelay(int time)
|
||||
{
|
||||
SettingsCore::setSlidesAdvanceTime(time);
|
||||
}
|
33
core/script/js_fullscreen_p.h
Normal file
33
core/script/js_fullscreen_p.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OKULAR_SCRIPT_JS_FULLSCREEN_P_H
|
||||
#define OKULAR_SCRIPT_JS_FULLSCREEN_P_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class JSFullscreen : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool loop READ loop WRITE setLoop) // clazy:exclude=qproperty-without-notify
|
||||
Q_PROPERTY(bool useTimer READ useTimer WRITE setUseTimer) // clazy:exclude=qproperty-without-notify
|
||||
Q_PROPERTY(int timeDelay READ timeDelay WRITE setTimeDelay) // clazy:exclude=qproperty-without-notify
|
||||
|
||||
public:
|
||||
bool loop() const;
|
||||
void setLoop(bool loop);
|
||||
bool useTimer() const;
|
||||
void setUseTimer(bool use);
|
||||
int timeDelay() const;
|
||||
void setTimeDelay(int time);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
39
core/script/js_ocg.cpp
Normal file
39
core/script/js_ocg.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2019 João Netto <joaonetto901@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "js_ocg_p.h"
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
// OCG.state (getter)
|
||||
bool JSOCG::state() const
|
||||
{
|
||||
const QModelIndex index = m_model->index(m_i, m_j);
|
||||
|
||||
return m_model->data(index, Qt::CheckStateRole).toBool();
|
||||
}
|
||||
|
||||
// OCG.state (setter)
|
||||
void JSOCG::setState(bool state)
|
||||
{
|
||||
const QModelIndex index = m_model->index(m_i, m_j);
|
||||
|
||||
m_model->setData(index, QVariant(state ? Qt::Checked : Qt::Unchecked), Qt::CheckStateRole);
|
||||
}
|
||||
|
||||
JSOCG::JSOCG(QAbstractItemModel *model, int i, int j, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_model(model)
|
||||
, m_i(i)
|
||||
, m_j(j)
|
||||
{
|
||||
}
|
||||
|
||||
JSOCG::~JSOCG() = default;
|
36
core/script/js_ocg_p.h
Normal file
36
core/script/js_ocg_p.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2019 João Netto <joaonetto901@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OKULAR_SCRIPT_JS_OCG_P_H
|
||||
#define OKULAR_SCRIPT_JS_OCG_P_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QAbstractItemModel;
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class JSOCG : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool state READ state WRITE setState) // clazy:exclude=qproperty-without-notify
|
||||
|
||||
public:
|
||||
explicit JSOCG(QAbstractItemModel *model, int i, int j, QObject *parent = nullptr);
|
||||
~JSOCG() override;
|
||||
|
||||
bool state() const;
|
||||
void setState(bool state);
|
||||
|
||||
private:
|
||||
QAbstractItemModel *m_model = nullptr;
|
||||
int m_i;
|
||||
int m_j;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
15
core/script/js_spell.cpp
Normal file
15
core/script/js_spell.cpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "js_spell_p.h"
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
bool JSSpell::available() const
|
||||
{
|
||||
return false;
|
||||
}
|
|
@ -5,19 +5,19 @@
|
|||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OKULAR_SCRIPT_KJS_CONSOLE_P_H
|
||||
#define OKULAR_SCRIPT_KJS_CONSOLE_P_H
|
||||
#ifndef OKULAR_SCRIPT_JS_SPELL_P_H
|
||||
#define OKULAR_SCRIPT_JS_SPELL_P_H
|
||||
|
||||
class KJSContext;
|
||||
class KJSObject;
|
||||
#include <QObject>
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class JSConsole
|
||||
class JSSpell : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool available READ available CONSTANT)
|
||||
public:
|
||||
static void initType(KJSContext *ctx);
|
||||
static KJSObject object(KJSContext *ctx);
|
||||
bool available() const;
|
||||
};
|
||||
|
||||
}
|
133
core/script/js_util.cpp
Normal file
133
core/script/js_util.cpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "js_util_p.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QJSEngine>
|
||||
#include <QLocale>
|
||||
#include <QRegularExpression>
|
||||
#include <QUrl>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
QJSValue JSUtil::crackURL(const QString &cURL) const
|
||||
{
|
||||
QUrl url(QUrl::fromLocalFile(cURL));
|
||||
if (!url.isValid()) {
|
||||
return qjsEngine(this)->newErrorObject(QJSValue::URIError, QStringLiteral("Invalid URL"));
|
||||
}
|
||||
if (url.scheme() != QLatin1String("file") || url.scheme() != QLatin1String("http") || url.scheme() != QLatin1String("https")) {
|
||||
return qjsEngine(this)->newErrorObject(QJSValue::URIError, QStringLiteral("Protocol not valid: '") + url.scheme() + QLatin1Char('\''));
|
||||
}
|
||||
|
||||
QJSValue obj;
|
||||
obj.setProperty(QStringLiteral("cScheme"), url.scheme());
|
||||
if (!url.userName().isEmpty()) {
|
||||
obj.setProperty(QStringLiteral("cUser"), url.userName());
|
||||
}
|
||||
if (!url.password().isEmpty()) {
|
||||
obj.setProperty(QStringLiteral("cPassword"), url.password());
|
||||
}
|
||||
obj.setProperty(QStringLiteral("cHost"), url.host());
|
||||
obj.setProperty(QStringLiteral("nPort"), url.port(80));
|
||||
// TODO cPath (Optional) The path portion of the URL.
|
||||
// TODO cParameters (Optional) The parameter string portion of the URL.
|
||||
if (url.hasFragment()) {
|
||||
obj.setProperty(QStringLiteral("cFragments"), url.fragment(QUrl::FullyDecoded));
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
QJSValue JSUtil::printd(const QJSValue &oFormat, const QDateTime &oDate) const
|
||||
{
|
||||
QString format;
|
||||
QLocale defaultLocale;
|
||||
|
||||
if (oFormat.isNumber()) {
|
||||
int formatType = oFormat.toInt();
|
||||
switch (formatType) {
|
||||
case 0:
|
||||
format = QStringLiteral("D:yyyyMMddHHmmss");
|
||||
break;
|
||||
case 1:
|
||||
format = QStringLiteral("yyyy.MM.dd HH:mm:ss");
|
||||
break;
|
||||
case 2:
|
||||
format = defaultLocale.dateTimeFormat(QLocale::ShortFormat);
|
||||
if (!format.contains(QStringLiteral("ss"))) {
|
||||
format.insert(format.indexOf(QStringLiteral("mm")) + 2, QStringLiteral(":ss"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
format = oFormat.toString().replace(QLatin1String("tt"), QLatin1String("ap"));
|
||||
format.replace(QLatin1Char('t'), QLatin1Char('a'));
|
||||
for (QChar &formatChar : format) {
|
||||
if (formatChar == QLatin1Char('M')) {
|
||||
formatChar = QLatin1Char('m');
|
||||
} else if (formatChar == QLatin1Char('m')) {
|
||||
formatChar = QLatin1Char('M');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return defaultLocale.toString(oDate, format);
|
||||
}
|
||||
|
||||
/** Converts a Number to a String using l10n
|
||||
*
|
||||
* String numberToString( Number number, String format = 'g', int precision = 6,
|
||||
* String LocaleName = system )
|
||||
*/
|
||||
QString JSUtil::numberToString(double number, const QString &fmt, int precision, const QString &localeName) const
|
||||
{
|
||||
if (std::isnan(number)) {
|
||||
return QStringLiteral("NaN");
|
||||
}
|
||||
|
||||
QChar format = QLatin1Char('g');
|
||||
if (!fmt.isEmpty()) {
|
||||
format = fmt[0];
|
||||
}
|
||||
|
||||
QLocale locale;
|
||||
if (!localeName.isEmpty()) {
|
||||
locale = QLocale(localeName);
|
||||
}
|
||||
|
||||
return locale.toString(number, format.toLatin1(), precision);
|
||||
}
|
||||
|
||||
/** Converts a String to a Number trying with the current locale first and
|
||||
* if that fails trying with the reverse locale for the decimal separator
|
||||
*
|
||||
* Number stringToNumber( String number ) */
|
||||
double JSUtil::stringToNumber(const QString &number) const
|
||||
{
|
||||
if (number.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const QLocale locale;
|
||||
bool ok;
|
||||
double converted = locale.toDouble(number, &ok);
|
||||
|
||||
if (!ok) {
|
||||
const QLocale locale2(locale.decimalPoint() == QLatin1Char('.') ? QStringLiteral("de") : QStringLiteral("en"));
|
||||
converted = locale2.toDouble(number, &ok);
|
||||
if (!ok) {
|
||||
return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
return converted;
|
||||
}
|
28
core/script/js_util_p.h
Normal file
28
core/script/js_util_p.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OKULAR_SCRIPT_JS_UTIL_P_H
|
||||
#define OKULAR_SCRIPT_JS_UTIL_P_H
|
||||
|
||||
#include <QJSValue>
|
||||
#include <QObject>
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class JSUtil : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Q_INVOKABLE QJSValue crackURL(const QString &cURL) const;
|
||||
Q_INVOKABLE QJSValue printd(const QJSValue &oFormat, const QDateTime &oDate) const;
|
||||
Q_INVOKABLE double stringToNumber(const QString &number) const;
|
||||
Q_INVOKABLE QString numberToString(double number, const QString &fmt = QStringLiteral("g"), int precision = 6, const QString &localeName = {}) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,439 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "kjs_app_p.h"
|
||||
|
||||
#include <kjs/kjsarguments.h>
|
||||
#include <kjs/kjsinterpreter.h>
|
||||
#include <kjs/kjsobject.h>
|
||||
#include <kjs/kjsprototype.h>
|
||||
#include <kjs_version.h>
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include <QLocale>
|
||||
#include <QTimer>
|
||||
|
||||
#include <KLocalizedString>
|
||||
#include <QCheckBox>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "../document_p.h"
|
||||
#include "../scripter.h"
|
||||
#include "config-okular.h"
|
||||
#include "kjs_fullscreen_p.h"
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
#define OKULAR_TIMERID QStringLiteral("okular_timerID")
|
||||
|
||||
static KJSPrototype *g_appProto;
|
||||
typedef QHash<int, QTimer *> TimerCache;
|
||||
Q_GLOBAL_STATIC(TimerCache, g_timerCache)
|
||||
|
||||
// the acrobat version we fake
|
||||
static const double fake_acroversion = 8.00;
|
||||
|
||||
static const struct FakePluginInfo {
|
||||
const char *name;
|
||||
bool certified;
|
||||
bool loaded;
|
||||
const char *path;
|
||||
} s_fake_plugins[] = {{"Annots", true, true, ""}, {"EFS", true, true, ""}, {"EScript", true, true, ""}, {"Forms", true, true, ""}, {"ReadOutLoud", true, true, ""}, {"WebLink", true, true, ""}};
|
||||
static const int s_num_fake_plugins = sizeof(s_fake_plugins) / sizeof(s_fake_plugins[0]);
|
||||
|
||||
static KJSObject appGetFormsVersion(KJSContext *, void *)
|
||||
{
|
||||
// faking a bit...
|
||||
return KJSNumber(fake_acroversion);
|
||||
}
|
||||
|
||||
static KJSObject appGetLanguage(KJSContext *, void *)
|
||||
{
|
||||
QLocale locale;
|
||||
QString lang = QLocale::languageToString(locale.language());
|
||||
QString country = QLocale::countryToString(locale.country());
|
||||
QString acroLang = QStringLiteral("ENU");
|
||||
if (lang == QLatin1String("da")) {
|
||||
acroLang = QStringLiteral("DAN"); // Danish
|
||||
} else if (lang == QLatin1String("de")) {
|
||||
acroLang = QStringLiteral("DEU"); // German
|
||||
} else if (lang == QLatin1String("en")) {
|
||||
acroLang = QStringLiteral("ENU"); // English
|
||||
} else if (lang == QLatin1String("es")) {
|
||||
acroLang = QStringLiteral("ESP"); // Spanish
|
||||
} else if (lang == QLatin1String("fr")) {
|
||||
acroLang = QStringLiteral("FRA"); // French
|
||||
} else if (lang == QLatin1String("it")) {
|
||||
acroLang = QStringLiteral("ITA"); // Italian
|
||||
} else if (lang == QLatin1String("ko")) {
|
||||
acroLang = QStringLiteral("KOR"); // Korean
|
||||
} else if (lang == QLatin1String("ja")) {
|
||||
acroLang = QStringLiteral("JPN"); // Japanese
|
||||
} else if (lang == QLatin1String("nl")) {
|
||||
acroLang = QStringLiteral("NLD"); // Dutch
|
||||
} else if (lang == QLatin1String("pt") && country == QLatin1String("BR")) {
|
||||
acroLang = QStringLiteral("PTB"); // Brazilian Portuguese
|
||||
} else if (lang == QLatin1String("fi")) {
|
||||
acroLang = QStringLiteral("SUO"); // Finnish
|
||||
} else if (lang == QLatin1String("sv")) {
|
||||
acroLang = QStringLiteral("SVE"); // Swedish
|
||||
} else if (lang == QLatin1String("zh") && country == QLatin1String("CN")) {
|
||||
acroLang = QStringLiteral("CHS"); // Chinese Simplified
|
||||
} else if (lang == QLatin1String("zh") && country == QLatin1String("TW")) {
|
||||
acroLang = QStringLiteral("CHT"); // Chinese Traditional
|
||||
}
|
||||
return KJSString(acroLang);
|
||||
}
|
||||
|
||||
static KJSObject appGetNumPlugins(KJSContext *, void *)
|
||||
{
|
||||
return KJSNumber(s_num_fake_plugins);
|
||||
}
|
||||
|
||||
static KJSObject appGetPlatform(KJSContext *, void *)
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
return KJSString(QString::fromLatin1("WIN"));
|
||||
#elif defined(Q_OS_MAC)
|
||||
return KJSString(QString::fromLatin1("MAC"));
|
||||
#else
|
||||
return KJSString(QStringLiteral("UNIX"));
|
||||
#endif
|
||||
}
|
||||
|
||||
static KJSObject appGetPlugIns(KJSContext *context, void *)
|
||||
{
|
||||
KJSArray plugins(context, s_num_fake_plugins);
|
||||
for (int i = 0; i < s_num_fake_plugins; ++i) {
|
||||
const FakePluginInfo &info = s_fake_plugins[i];
|
||||
KJSObject plugin;
|
||||
plugin.setProperty(context, QStringLiteral("certified"), info.certified);
|
||||
plugin.setProperty(context, QStringLiteral("loaded"), info.loaded);
|
||||
plugin.setProperty(context, QStringLiteral("name"), info.name);
|
||||
plugin.setProperty(context, QStringLiteral("path"), info.path);
|
||||
plugin.setProperty(context, QStringLiteral("version"), fake_acroversion);
|
||||
plugins.setProperty(context, QString::number(i), plugin);
|
||||
}
|
||||
return plugins;
|
||||
}
|
||||
|
||||
static KJSObject appGetPrintColorProfiles(KJSContext *context, void *)
|
||||
{
|
||||
return KJSArray(context, 0);
|
||||
}
|
||||
|
||||
static KJSObject appGetPrinterNames(KJSContext *context, void *)
|
||||
{
|
||||
return KJSArray(context, 0);
|
||||
}
|
||||
|
||||
static KJSObject appGetViewerType(KJSContext *, void *)
|
||||
{
|
||||
// faking a bit...
|
||||
return KJSString(QStringLiteral("Reader"));
|
||||
}
|
||||
|
||||
static KJSObject appGetViewerVariation(KJSContext *, void *)
|
||||
{
|
||||
// faking a bit...
|
||||
return KJSString(QStringLiteral("Reader"));
|
||||
}
|
||||
|
||||
static KJSObject appGetViewerVersion(KJSContext *, void *)
|
||||
{
|
||||
// faking a bit...
|
||||
return KJSNumber(fake_acroversion);
|
||||
}
|
||||
|
||||
/*
|
||||
Alert function defined in the reference, it shows a Dialog Box with options.
|
||||
app.alert()
|
||||
*/
|
||||
static KJSObject appAlert(KJSContext *context, void *, const KJSArguments &arguments)
|
||||
{
|
||||
if (arguments.count() < 1) {
|
||||
return context->throwException(i18n("Missing alert type"));
|
||||
}
|
||||
KJSObject cMsg, nIcon, nType, cTitle, oCheckbox;
|
||||
|
||||
if (arguments.at(0).isObject()) {
|
||||
KJSObject obj = arguments.at(0);
|
||||
cMsg = obj.property(context, QStringLiteral("cMsg"));
|
||||
nIcon = obj.property(context, QStringLiteral("nIcon"));
|
||||
nType = obj.property(context, QStringLiteral("nType"));
|
||||
cTitle = obj.property(context, QStringLiteral("cTitle"));
|
||||
oCheckbox = obj.property(context, QStringLiteral("oCheckbox"));
|
||||
} else {
|
||||
cMsg = arguments.at(0);
|
||||
nIcon = arguments.at(1);
|
||||
nType = arguments.at(2);
|
||||
cTitle = arguments.at(3);
|
||||
oCheckbox = arguments.at(5);
|
||||
}
|
||||
|
||||
QMessageBox::Icon icon = QMessageBox::Critical;
|
||||
if (nIcon.isNumber()) {
|
||||
switch (nIcon.toInt32(context)) {
|
||||
case 0:
|
||||
icon = QMessageBox::Critical;
|
||||
break;
|
||||
case 1:
|
||||
icon = QMessageBox::Warning;
|
||||
break;
|
||||
case 2:
|
||||
icon = QMessageBox::Question;
|
||||
break;
|
||||
case 3:
|
||||
icon = QMessageBox::Information;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const QString title = cTitle.isString() ? cTitle.toString(context) : QStringLiteral("Okular");
|
||||
QMessageBox box(icon, title, cMsg.toString(context));
|
||||
|
||||
QMessageBox::StandardButtons buttons = QMessageBox::Ok;
|
||||
if (nType.isNumber()) {
|
||||
switch (nType.toInt32(context)) {
|
||||
case 0:
|
||||
buttons = QMessageBox::Ok;
|
||||
break;
|
||||
case 1:
|
||||
buttons = QMessageBox::Ok | QMessageBox::Cancel;
|
||||
break;
|
||||
case 2:
|
||||
buttons = QMessageBox::Yes | QMessageBox::No;
|
||||
break;
|
||||
case 3:
|
||||
buttons = QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel;
|
||||
break;
|
||||
}
|
||||
}
|
||||
box.setStandardButtons(buttons);
|
||||
|
||||
QCheckBox *checkBox = nullptr;
|
||||
if (oCheckbox.isObject()) {
|
||||
KJSObject oMsg = oCheckbox.property(context, QStringLiteral("cMsg"));
|
||||
QString msg = i18n("Do not show this message again");
|
||||
|
||||
if (oMsg.isString()) {
|
||||
msg = oMsg.toString(context);
|
||||
}
|
||||
|
||||
bool bInitialValue = false;
|
||||
KJSObject value = oCheckbox.property(context, QStringLiteral("bInitialValue"));
|
||||
if (value.isBoolean()) {
|
||||
bInitialValue = value.toBoolean(context);
|
||||
}
|
||||
checkBox = new QCheckBox(msg);
|
||||
checkBox->setChecked(bInitialValue);
|
||||
box.setCheckBox(checkBox);
|
||||
}
|
||||
|
||||
#if KJS_VERSION > QT_VERSION_CHECK(5, 71, 0)
|
||||
// halt timeout until the user has responded
|
||||
context->interpreter().stopTimeoutCheck();
|
||||
#endif
|
||||
|
||||
int button = box.exec();
|
||||
|
||||
#if KJS_VERSION > QT_VERSION_CHECK(5, 71, 0)
|
||||
// restart max allowed time
|
||||
context->interpreter().startTimeoutCheck();
|
||||
#endif
|
||||
|
||||
int ret;
|
||||
|
||||
switch (button) {
|
||||
case QMessageBox::Ok:
|
||||
ret = 1;
|
||||
break;
|
||||
case QMessageBox::Cancel:
|
||||
ret = 2;
|
||||
break;
|
||||
case QMessageBox::No:
|
||||
ret = 3;
|
||||
break;
|
||||
case QMessageBox::Yes:
|
||||
ret = 4;
|
||||
break;
|
||||
}
|
||||
|
||||
if (checkBox) {
|
||||
oCheckbox.setProperty(context, QStringLiteral("bAfterValue"), checkBox->isChecked());
|
||||
}
|
||||
|
||||
delete checkBox;
|
||||
|
||||
return KJSNumber(ret);
|
||||
}
|
||||
|
||||
static KJSObject appBeep(KJSContext *context, void *, const KJSArguments &arguments)
|
||||
{
|
||||
if (arguments.count() < 1) {
|
||||
return context->throwException(QStringLiteral("Missing beep type"));
|
||||
}
|
||||
QApplication::beep();
|
||||
return KJSUndefined();
|
||||
}
|
||||
|
||||
static KJSObject appGetNthPlugInName(KJSContext *context, void *, const KJSArguments &arguments)
|
||||
{
|
||||
if (arguments.count() < 1) {
|
||||
return context->throwException(QStringLiteral("Missing plugin index"));
|
||||
}
|
||||
const int nIndex = arguments.at(0).toInt32(context);
|
||||
|
||||
if (nIndex < 0 || nIndex >= s_num_fake_plugins) {
|
||||
return context->throwException(QStringLiteral("PlugIn index out of bounds"));
|
||||
}
|
||||
|
||||
const FakePluginInfo &info = s_fake_plugins[nIndex];
|
||||
return KJSString(info.name);
|
||||
}
|
||||
|
||||
static KJSObject appGoBack(KJSContext *, void *object, const KJSArguments &)
|
||||
{
|
||||
const DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
|
||||
if (doc->m_parent->historyAtBegin()) {
|
||||
return KJSUndefined();
|
||||
}
|
||||
|
||||
doc->m_parent->setPrevViewport();
|
||||
return KJSUndefined();
|
||||
}
|
||||
|
||||
static KJSObject appGoForward(KJSContext *, void *object, const KJSArguments &)
|
||||
{
|
||||
const DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
|
||||
if (doc->m_parent->historyAtEnd()) {
|
||||
return KJSUndefined();
|
||||
}
|
||||
|
||||
doc->m_parent->setNextViewport();
|
||||
return KJSUndefined();
|
||||
}
|
||||
|
||||
// app.setInterval()
|
||||
static KJSObject appSetInterval(KJSContext *ctx, void *object, const KJSArguments &arguments)
|
||||
{
|
||||
DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
|
||||
const QString function = arguments.at(0).toString(ctx) + QLatin1Char(';');
|
||||
const int interval = arguments.at(1).toInt32(ctx);
|
||||
|
||||
QTimer *timer = new QTimer();
|
||||
|
||||
QObject::connect(timer, &QTimer::timeout, doc->m_parent, [=]() { doc->executeScript(function); });
|
||||
|
||||
timer->start(interval);
|
||||
|
||||
return JSApp::wrapTimer(ctx, timer);
|
||||
}
|
||||
|
||||
// app.clearInterval()
|
||||
static KJSObject appClearInterval(KJSContext *ctx, void *, const KJSArguments &arguments)
|
||||
{
|
||||
KJSObject timerObject = arguments.at(0);
|
||||
const int timerId = timerObject.property(ctx, OKULAR_TIMERID).toInt32(ctx);
|
||||
QTimer *timer = g_timerCache->value(timerId);
|
||||
if (timer != nullptr) {
|
||||
timer->stop();
|
||||
g_timerCache->remove(timerId);
|
||||
delete timer;
|
||||
}
|
||||
|
||||
return KJSUndefined();
|
||||
}
|
||||
|
||||
// app.setTimeOut()
|
||||
static KJSObject appSetTimeOut(KJSContext *ctx, void *object, const KJSArguments &arguments)
|
||||
{
|
||||
DocumentPrivate *doc = reinterpret_cast<DocumentPrivate *>(object);
|
||||
const QString function = arguments.at(0).toString(ctx) + QLatin1Char(';');
|
||||
const int interval = arguments.at(1).toInt32(ctx);
|
||||
|
||||
QTimer *timer = new QTimer();
|
||||
timer->setSingleShot(true);
|
||||
|
||||
QObject::connect(timer, &QTimer::timeout, doc->m_parent, [=]() { doc->executeScript(function); });
|
||||
|
||||
timer->start(interval);
|
||||
|
||||
return JSApp::wrapTimer(ctx, timer);
|
||||
}
|
||||
|
||||
// app.clearTimeOut()
|
||||
static KJSObject appClearTimeOut(KJSContext *ctx, void *, const KJSArguments &arguments)
|
||||
{
|
||||
KJSObject timerObject = arguments.at(0);
|
||||
const int timerId = timerObject.property(ctx, OKULAR_TIMERID).toInt32(ctx);
|
||||
QTimer *timer = g_timerCache->value(timerId);
|
||||
|
||||
if (timer != nullptr) {
|
||||
timer->stop();
|
||||
g_timerCache->remove(timerId);
|
||||
delete timer;
|
||||
}
|
||||
|
||||
return KJSUndefined();
|
||||
}
|
||||
|
||||
void JSApp::initType(KJSContext *ctx)
|
||||
{
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
g_appProto = new KJSPrototype();
|
||||
|
||||
g_appProto->defineProperty(ctx, QStringLiteral("formsVersion"), appGetFormsVersion);
|
||||
g_appProto->defineProperty(ctx, QStringLiteral("language"), appGetLanguage);
|
||||
g_appProto->defineProperty(ctx, QStringLiteral("numPlugIns"), appGetNumPlugins);
|
||||
g_appProto->defineProperty(ctx, QStringLiteral("platform"), appGetPlatform);
|
||||
g_appProto->defineProperty(ctx, QStringLiteral("plugIns"), appGetPlugIns);
|
||||
g_appProto->defineProperty(ctx, QStringLiteral("printColorProfiles"), appGetPrintColorProfiles);
|
||||
g_appProto->defineProperty(ctx, QStringLiteral("printerNames"), appGetPrinterNames);
|
||||
g_appProto->defineProperty(ctx, QStringLiteral("viewerType"), appGetViewerType);
|
||||
g_appProto->defineProperty(ctx, QStringLiteral("viewerVariation"), appGetViewerVariation);
|
||||
g_appProto->defineProperty(ctx, QStringLiteral("viewerVersion"), appGetViewerVersion);
|
||||
|
||||
g_appProto->defineFunction(ctx, QStringLiteral("alert"), appAlert);
|
||||
g_appProto->defineFunction(ctx, QStringLiteral("beep"), appBeep);
|
||||
g_appProto->defineFunction(ctx, QStringLiteral("getNthPlugInName"), appGetNthPlugInName);
|
||||
g_appProto->defineFunction(ctx, QStringLiteral("goBack"), appGoBack);
|
||||
g_appProto->defineFunction(ctx, QStringLiteral("goForward"), appGoForward);
|
||||
g_appProto->defineFunction(ctx, QStringLiteral("setInterval"), appSetInterval);
|
||||
g_appProto->defineFunction(ctx, QStringLiteral("clearInterval"), appClearInterval);
|
||||
g_appProto->defineFunction(ctx, QStringLiteral("setTimeOut"), appSetTimeOut);
|
||||
g_appProto->defineFunction(ctx, QStringLiteral("clearTimeOut"), appClearTimeOut);
|
||||
}
|
||||
|
||||
KJSObject JSApp::object(KJSContext *ctx, DocumentPrivate *doc)
|
||||
{
|
||||
return g_appProto->constructObject(ctx, doc);
|
||||
}
|
||||
|
||||
KJSObject JSApp::wrapTimer(KJSContext *ctx, QTimer *timer)
|
||||
{
|
||||
KJSObject timerObject = g_appProto->constructObject(ctx, timer);
|
||||
timerObject.setProperty(ctx, OKULAR_TIMERID, timer->timerId());
|
||||
|
||||
g_timerCache->insert(timer->timerId(), timer);
|
||||
|
||||
return timerObject;
|
||||
}
|
||||
|
||||
void JSApp::clearCachedFields()
|
||||
{
|
||||
if (g_timerCache) {
|
||||
qDeleteAll(g_timerCache->begin(), g_timerCache->end());
|
||||
g_timerCache->clear();
|
||||
}
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OKULAR_SCRIPT_KJS_APP_P_H
|
||||
#define OKULAR_SCRIPT_KJS_APP_P_H
|
||||
|
||||
class KJSContext;
|
||||
class KJSObject;
|
||||
class QTimer;
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class DocumentPrivate;
|
||||
|
||||
class JSApp
|
||||
{
|
||||
public:
|
||||
static void initType(KJSContext *ctx);
|
||||
static KJSObject object(KJSContext *ctx, DocumentPrivate *doc);
|
||||
static KJSObject wrapTimer(KJSContext *ctx, QTimer *timer);
|
||||
static void clearCachedFields();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "kjs_console_p.h"
|
||||
|
||||
#include <kjs/kjsarguments.h>
|
||||
#include <kjs/kjsobject.h>
|
||||
#include <kjs/kjsprototype.h>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "../debug_p.h"
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
static KJSPrototype *g_consoleProto;
|
||||
|
||||
#ifdef OKULAR_JS_CONSOLE
|
||||
|
||||
#include <QLayout>
|
||||
#include <QPlainTextEdit>
|
||||
|
||||
#include <KDialog>
|
||||
#include <KStandardGuiItem>
|
||||
|
||||
K_GLOBAL_STATIC(KDialog, g_jsConsoleWindow)
|
||||
static QPlainTextEdit *g_jsConsoleLog = 0;
|
||||
|
||||
static void createConsoleWindow()
|
||||
{
|
||||
if (g_jsConsoleWindow.exists())
|
||||
return;
|
||||
|
||||
g_jsConsoleWindow->setButtons(KDialog::Close | KDialog::User1);
|
||||
g_jsConsoleWindow->setButtonGuiItem(KDialog::User1, KStandardGuiItem::clear());
|
||||
|
||||
QVBoxLayout *mainLay = new QVBoxLayout(g_jsConsoleWindow->mainWidget());
|
||||
mainLay->setContentsMargins(0, 0, 0, 0);
|
||||
g_jsConsoleLog = new QPlainTextEdit(g_jsConsoleWindow->mainWidget());
|
||||
g_jsConsoleLog->setReadOnly(true);
|
||||
mainLay->addWidget(g_jsConsoleLog);
|
||||
|
||||
QObject::connect(g_jsConsoleWindow, SIGNAL(closeClicked()), g_jsConsoleWindow, SLOT(close()));
|
||||
QObject::connect(g_jsConsoleWindow, SIGNAL(user1Clicked()), g_jsConsoleLog, SLOT(clear()));
|
||||
}
|
||||
|
||||
static void showConsole()
|
||||
{
|
||||
createConsoleWindow();
|
||||
g_jsConsoleWindow->show();
|
||||
}
|
||||
|
||||
static void hideConsole()
|
||||
{
|
||||
if (!g_jsConsoleWindow.exists())
|
||||
return;
|
||||
|
||||
g_jsConsoleWindow->hide();
|
||||
}
|
||||
|
||||
static void clearConsole()
|
||||
{
|
||||
if (!g_jsConsoleWindow.exists())
|
||||
return;
|
||||
|
||||
g_jsConsoleLog->clear();
|
||||
}
|
||||
|
||||
static void outputToConsole(const QString &message)
|
||||
{
|
||||
showConsole();
|
||||
g_jsConsoleLog->appendPlainText(message);
|
||||
}
|
||||
|
||||
#else /* OKULAR_JS_CONSOLE */
|
||||
|
||||
static void showConsole()
|
||||
{
|
||||
}
|
||||
|
||||
static void hideConsole()
|
||||
{
|
||||
}
|
||||
|
||||
static void clearConsole()
|
||||
{
|
||||
}
|
||||
|
||||
static void outputToConsole(const QString &cMessage)
|
||||
{
|
||||
qCDebug(OkularCoreDebug) << "CONSOLE:" << cMessage;
|
||||
}
|
||||
|
||||
#endif /* OKULAR_JS_CONSOLE */
|
||||
|
||||
static KJSObject consoleClear(KJSContext *, void *, const KJSArguments &)
|
||||
{
|
||||
clearConsole();
|
||||
return KJSUndefined();
|
||||
}
|
||||
|
||||
static KJSObject consoleHide(KJSContext *, void *, const KJSArguments &)
|
||||
{
|
||||
hideConsole();
|
||||
return KJSUndefined();
|
||||
}
|
||||
|
||||
static KJSObject consolePrintln(KJSContext *ctx, void *, const KJSArguments &arguments)
|
||||
{
|
||||
QString cMessage = arguments.at(0).toString(ctx);
|
||||
outputToConsole(cMessage);
|
||||
|
||||
return KJSUndefined();
|
||||
}
|
||||
|
||||
static KJSObject consoleShow(KJSContext *, void *, const KJSArguments &)
|
||||
{
|
||||
showConsole();
|
||||
return KJSUndefined();
|
||||
}
|
||||
|
||||
void JSConsole::initType(KJSContext *ctx)
|
||||
{
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
g_consoleProto = new KJSPrototype();
|
||||
|
||||
g_consoleProto->defineFunction(ctx, QStringLiteral("clear"), consoleClear);
|
||||
g_consoleProto->defineFunction(ctx, QStringLiteral("hide"), consoleHide);
|
||||
g_consoleProto->defineFunction(ctx, QStringLiteral("println"), consolePrintln);
|
||||
g_consoleProto->defineFunction(ctx, QStringLiteral("hide"), consoleShow);
|
||||
}
|
||||
|
||||
KJSObject JSConsole::object(KJSContext *ctx)
|
||||
{
|
||||
return g_consoleProto->constructObject(ctx, nullptr);
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "kjs_data_p.h"
|
||||
|
||||
#include <kjs/kjsobject.h>
|
||||
#include <kjs/kjsprototype.h>
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
#include "../document.h"
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
static KJSPrototype *g_dataProto;
|
||||
|
||||
static KJSObject dataGetCreationDate(KJSContext *ctx, void *object)
|
||||
{
|
||||
const EmbeddedFile *file = reinterpret_cast<EmbeddedFile *>(object);
|
||||
|
||||
return KJSDate(ctx, file->creationDate());
|
||||
}
|
||||
|
||||
static KJSObject dataGetDescription(KJSContext *, void *object)
|
||||
{
|
||||
const EmbeddedFile *file = reinterpret_cast<EmbeddedFile *>(object);
|
||||
|
||||
return KJSString(file->description());
|
||||
}
|
||||
|
||||
static KJSObject dataGetMIMEType(KJSContext *, void *)
|
||||
{
|
||||
return KJSString("");
|
||||
}
|
||||
|
||||
static KJSObject dataGetModDate(KJSContext *ctx, void *object)
|
||||
{
|
||||
const EmbeddedFile *file = reinterpret_cast<EmbeddedFile *>(object);
|
||||
|
||||
return KJSDate(ctx, file->modificationDate());
|
||||
}
|
||||
|
||||
static KJSObject dataGetName(KJSContext *, void *object)
|
||||
{
|
||||
const EmbeddedFile *file = reinterpret_cast<EmbeddedFile *>(object);
|
||||
|
||||
return KJSString(file->name());
|
||||
}
|
||||
|
||||
static KJSObject dataGetPath(KJSContext *, void *)
|
||||
{
|
||||
return KJSString("");
|
||||
}
|
||||
|
||||
static KJSObject dataGetSize(KJSContext *, void *object)
|
||||
{
|
||||
const EmbeddedFile *file = reinterpret_cast<EmbeddedFile *>(object);
|
||||
return KJSNumber(file->size());
|
||||
}
|
||||
|
||||
void JSData::initType(KJSContext *ctx)
|
||||
{
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
if (!g_dataProto) {
|
||||
g_dataProto = new KJSPrototype();
|
||||
}
|
||||
|
||||
g_dataProto->defineProperty(ctx, QStringLiteral("creationDate"), dataGetCreationDate);
|
||||
g_dataProto->defineProperty(ctx, QStringLiteral("description"), dataGetDescription);
|
||||
g_dataProto->defineProperty(ctx, QStringLiteral("MIMEType"), dataGetMIMEType);
|
||||
g_dataProto->defineProperty(ctx, QStringLiteral("modDate"), dataGetModDate);
|
||||
g_dataProto->defineProperty(ctx, QStringLiteral("name"), dataGetName);
|
||||
g_dataProto->defineProperty(ctx, QStringLiteral("path"), dataGetPath);
|
||||
g_dataProto->defineProperty(ctx, QStringLiteral("size"), dataGetSize);
|
||||
}
|
||||
|
||||
KJSObject JSData::wrapFile(KJSContext *ctx, EmbeddedFile *f)
|
||||
{
|
||||
return g_dataProto->constructObject(ctx, f);
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org>
|
||||
SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OKULAR_SCRIPT_KJS_DATA_P_H
|
||||
#define OKULAR_SCRIPT_KJS_DATA_P_H
|
||||
|
||||
class KJSContext;
|
||||
class KJSObject;
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
class EmbeddedFile;
|
||||
|
||||
class JSData
|
||||
{
|
||||
public:
|
||||
static void initType(KJSContext *ctx);
|
||||
static KJSObject wrapFile(KJSContext *ctx, EmbeddedFile *f);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2019 João Netto <joaonetto901@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "../form.h"
|
||||
#include "kjs_display_p.h"
|
||||
|
||||
#include <kjs/kjsobject.h>
|
||||
#include <kjs/kjsprototype.h>
|
||||
|
||||
#include <QString>
|
||||
|
||||
using namespace Okular;
|
||||
|
||||
static KJSPrototype *g_displayProto;
|
||||
|
||||
// display.hidden
|
||||
static KJSObject displayGetHidden(KJSContext *, void *)
|
||||
{
|
||||
return KJSNumber(FormDisplay::FormHidden);
|
||||
}
|
||||
|
||||
// display.visible
|
||||
static KJSObject displayGetVisible(KJSContext *, void *)
|
||||
{
|
||||
return KJSNumber(FormDisplay::FormVisible);
|
||||
}
|
||||
|
||||
// display.noView
|
||||
static KJSObject displayGetNoView(KJSContext *, void *)
|
||||
{
|
||||
return KJSNumber(FormDisplay::FormNoView);
|
||||
}
|
||||
|
||||
// display.noPrint
|
||||
static KJSObject displayGetNoPrint(KJSContext *, void *)
|
||||
{
|
||||
return KJSNumber(FormDisplay::FormNoPrint);
|
||||
}
|
||||
|
||||
void JSDisplay::initType(KJSContext *ctx)
|
||||
{
|
||||
static bool initialized = false;
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
initialized = true;
|
||||
|
||||
g_displayProto = new KJSPrototype();
|
||||
|
||||
g_displayProto->defineProperty(ctx, QStringLiteral("hidden"), displayGetHidden);
|
||||
g_displayProto->defineProperty(ctx, QStringLiteral("visible"), displayGetVisible);
|
||||
g_displayProto->defineProperty(ctx, QStringLiteral("noView"), displayGetNoView);
|
||||
g_displayProto->defineProperty(ctx, QStringLiteral("noPrint"), displayGetNoPrint);
|
||||
}
|
||||
|
||||
KJSObject JSDisplay::object(KJSContext *ctx)
|
||||
{
|
||||
return g_displayProto->constructObject(ctx, nullptr);
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2019 João Netto <joaonetto901@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef OKULAR_SCRIPT_KJS_DISPLAY_P_H
|
||||
#define OKULAR_SCRIPT_KJS_DISPLAY_P_H
|
||||
|
||||
class KJSContext;
|
||||
class KJSObject;
|
||||
|
||||
namespace Okular
|
||||
{
|
||||
/**
|
||||
* The display types of the field.
|
||||
*/
|
||||
enum FormDisplay { FormVisible, FormHidden, FormNoPrint, FormNoView };
|
||||
|
||||
class JSDisplay
|
||||
{
|
||||
public:
|
||||
static void initType(KJSContext *ctx);
|
||||
static KJSObject object(KJSContext *ctx);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue