Compare commits
195 Commits
Author | SHA1 | Date |
---|---|---|
Jakub Melka | c9b262fc36 | |
Jakub Melka | 29f59be3b6 | |
Jakub Melka | 793cf59c72 | |
Jakub Melka | 1e52c0c063 | |
Jakub Melka | 8b832ccab9 | |
Jakub Melka | bf4b0552dc | |
Jakub Melka | b4e742f564 | |
Jakub Melka | 35242f845e | |
Jakub Melka | ccd69e1ac4 | |
Jakub Melka | c11708d367 | |
Jakub Melka | f2ea50ae6e | |
Jakub Melka | a72f2f7bac | |
Jakub Melka | 032e564fd8 | |
Jakub Melka | 28807b4f12 | |
Jakub Melka | a70f45c8a9 | |
Jakub Melka | 344c341f65 | |
Jakub Melka | d6f334c242 | |
Jakub Melka | bdf7a957d5 | |
Jakub Melka | 5f0ae6ae5f | |
Jakub Melka | 6c5b8b08a5 | |
Jakub Melka | 1c3eca3971 | |
Jakub Melka | 03cbde9690 | |
Jakub Melka | 89cfd1dd1f | |
Jakub Melka | e8d72878a5 | |
Jakub Melka | 2e38e41ce9 | |
Jakub Melka | 6a477bdf04 | |
Jakub Melka | 54d093ab8c | |
Jakub Melka | 5eb5069173 | |
Jakub Melka | 7ad04b55ee | |
Jakub Melka | f80b7b059e | |
Jakub Melka | d1d0fe30d6 | |
Jakub Melka | f3e1a94e1c | |
Jakub Melka | d314683d38 | |
Jakub Melka | 87cedf01dc | |
Jakub Melka | 1bf7b724a1 | |
Jakub Melka | 8406fd0c47 | |
Jakub Melka | 0629a719bd | |
Jakub Melka | e45924a4cc | |
Jakub Melka | fc60e94156 | |
Jakub Melka | 0f8e2b7012 | |
Jakub Melka | afeaf88151 | |
Jakub Melka | c0eaeddcd9 | |
Jakub Melka | 2019816995 | |
Jakub Melka | 2aea7ed606 | |
Jakub Melka | cb98f3bcb2 | |
Jakub Melka | 64fae4feba | |
Jakub Melka | 56095ab350 | |
Jakub Melka | 41b89c2988 | |
Jakub Melka | a6d201e3a5 | |
Jakub Melka | 04c7855d7e | |
Jakub Melka | 86a32de1d1 | |
Jakub Melka | b8ff31c5e5 | |
Jakub Melka | a27d8be0e0 | |
Jakub Melka | 1bf4e90b8c | |
Nyall Dawson | 4f1fca4b70 | |
Nyall Dawson | 52ce99d466 | |
Nyall Dawson | eefde4edee | |
Nyall Dawson | 61f489dd70 | |
Nyall Dawson | 7ab77c582b | |
Nyall Dawson | 577866aa2f | |
Nyall Dawson | bbecbf6311 | |
Nyall Dawson | 6354e4cad1 | |
Nyall Dawson | 3846c5187e | |
Nyall Dawson | 8c40e49801 | |
Nyall Dawson | 2ed31dcd2c | |
Jakub Melka | 221587c751 | |
Jakub Melka | 3cabc6b792 | |
Jakub Melka | b2b033b5d3 | |
Jakub Melka | 9bbf4539d1 | |
Jakub Melka | 843c025010 | |
Jakub Melka | ca698156cd | |
Jakub Melka | 298060a61f | |
Jakub Melka | b62e96e2d0 | |
Jakub Melka | 62abee0e97 | |
Jakub Melka | 1a66b804a2 | |
Jakub Melka | 8338d7d85d | |
Jakub Melka | acafeb0144 | |
Jakub Melka | 0ddeda8036 | |
Jakub Melka | 1fded3d6b7 | |
Jakub Melka | 333ccb1bfb | |
Jakub Melka | e4875c4050 | |
Jakub Melka | 905a9e4a8b | |
Jakub Melka | d6e5dd2b15 | |
Jakub Melka | 3ccbef6dc8 | |
Jakub Melka | 37654945d2 | |
Jakub Melka | d5e390e75c | |
Jakub Melka | 7cb6b5bb3a | |
Jakub Melka | a085a54b00 | |
Jakub Melka | c6d8b8b783 | |
Jakub Melka | 0f47f1a6d0 | |
Jakub Melka | 5ba4cef2f7 | |
Jakub Melka | 89ea815696 | |
Jakub Melka | 53849f51e1 | |
Jakub Melka | 9de8dbfad2 | |
Jakub Melka | 94b392c108 | |
Jakub Melka | e082f072f7 | |
Jakub Melka | d974912b05 | |
Jakub Melka | 56f5c4abcf | |
Jakub Melka | 17f94a102c | |
Jakub Melka | b3580560a4 | |
Jakub Melka | 9f624e5569 | |
Jakub Melka | e5e25a71a3 | |
Jakub Melka | c79a029c2f | |
Nyall Dawson | c17165b088 | |
Jakub Melka | 4a679efe25 | |
Jakub Melka | d07263c3f1 | |
Jakub Melka | 5d001ede45 | |
Jakub Melka | 1ed7a12357 | |
Jakub Melka | e87b14dc3a | |
Jakub Melka | e9ca3a4a82 | |
Jakub Melka | 7a5f37e38f | |
Jakub Melka | c1c59139b5 | |
Jakub Melka | 27cccbedcb | |
Jakub Melka | 15e7b93393 | |
Jakub Melka | 3645bfe07b | |
Jakub Melka | 2ad471ee9a | |
Jakub Melka | 657afadd46 | |
Jakub Melka | 8759578142 | |
Jakub Melka | 6721490ee6 | |
Jakub Melka | e6d95d3936 | |
Jakub Melka | d80351b2a6 | |
Jakub Melka | 38988babc5 | |
Jakub Melka | 14ae5e9a85 | |
Jakub Melka | 038101d765 | |
Jakub Melka | 8e6e83cc66 | |
Jakub Melka | feade42fe8 | |
Jakub Melka | 277b40acc9 | |
Jakub Melka | 2c0b462075 | |
Jakub Melka | 4340b3dbaa | |
Jakub Melka | 0b579c828f | |
Jakub Melka | ee42c63f80 | |
Jakub Melka | 4b76eb989d | |
Jakub Melka | 3e9d7a39ff | |
Jakub Melka | 5f7b54dff5 | |
Jakub Melka | 1dcb42ebef | |
Jakub Melka | 19a26c2a74 | |
Jakub Melka | 176369e8dd | |
Jakub Melka | 1aa3ffe695 | |
Jakub Melka | 31e34d8e32 | |
Jakub Melka | d50ecdbb28 | |
Jakub Melka | 5a6f448467 | |
Jakub Melka | 147a1ea586 | |
Jakub Melka | 8db0ae80c3 | |
Jakub Melka | 3004618992 | |
Jakub Melka | 642e6a9bb7 | |
Jakub Melka | cdbbe5e121 | |
Jakub Melka | 0e1959b3aa | |
Jakub Melka | b4d123baac | |
Jakub Melka | edd100d3b8 | |
Jakub Melka | bc8be2198b | |
Jakub Melka | c01a1da4ec | |
Jakub Melka | 6221c533a2 | |
Jakub Melka | 1a10401b91 | |
Jakub Melka | 2d1e1dc479 | |
Jakub Melka | 288eead65e | |
Jakub Melka | a892c192fc | |
Jakub Melka | 1c5c7da5ba | |
Jakub Melka | f5cb2a17af | |
Jakub Melka | 5f678bc308 | |
Jakub Melka | ff6dd4b249 | |
Jakub Melka | 851374dc73 | |
Jakub Melka | 5746412e31 | |
Jakub Melka | e476c4ea11 | |
Jakub Melka | ed79aa0334 | |
Jakub Melka | 65fd88aa71 | |
Jakub Melka | 6f6ddaab04 | |
Jakub Melka | 2408c61b5f | |
Jakub Melka | 4ffd4a0639 | |
Jakub Melka | e9a87553af | |
Jakub Melka | 47f0bffeca | |
Jakub Melka | 805c967b70 | |
Jakub Melka | c5ddb521ed | |
Jakub Melka | cf7d65dc82 | |
Jakub Melka | fc44dfa4bc | |
Jakub Melka | 908fb47af1 | |
Jakub Melka | 881364f0a0 | |
Jakub Melka | 6fe978f031 | |
Jakub Melka | 2584227373 | |
Jakub Melka | 1631268d08 | |
Jakub Melka | 9a951431c4 | |
Jakub Melka | 3a50c16c07 | |
Jakub Melka | 3d32db2046 | |
Jakub Melka | edc86a84fa | |
Jakub Melka | 10f24c2dff | |
Jakub Melka | c57f28a3b5 | |
Jakub Melka | 52f6a3ce8a | |
Jakub Melka | 93496339d4 | |
Jakub Melka | 73024fbe99 | |
Jakub Melka | bf53e7419b | |
Jakub Melka | be0d02bb5c | |
Jakub Melka | bf4ed862e5 | |
Jakub Melka | a29a35e029 | |
Jakub Melka | c2c03a358f | |
Jakub Melka | 9b33b3a4a5 | |
Jakub Melka | 07c2a476a0 |
|
@ -0,0 +1 @@
|
|||
github: JakubMelka
|
|
@ -0,0 +1,105 @@
|
|||
name: LinuxInstall
|
||||
|
||||
on:
|
||||
create:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build_ubuntu:
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libxcb-cursor0
|
||||
sudo apt-get install -y libspeechd2
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: pdf4qt
|
||||
|
||||
- name: Set up GCC
|
||||
uses: egor-tensin/setup-gcc@v1
|
||||
with:
|
||||
version: 11
|
||||
platform: x64
|
||||
|
||||
- name: 'VCPKG: Set up VCPKG'
|
||||
run: |
|
||||
git clone --depth=1 https://github.com/microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
|
||||
- name: 'VCPKG: Cache vcpkg dependencies'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./vcpkg/downloads
|
||||
./vcpkg/packages
|
||||
key: ${{ runner.os }}-vcpkg-v2-${{ hashFiles('**/vcpkg.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-vcpkg-v2-
|
||||
|
||||
- name: 'VCPKG: Install project dependencies'
|
||||
run: |
|
||||
./vcpkg install tbb openssl lcms zlib openjpeg freetype ijg-libjpeg libpng blend2d
|
||||
working-directory: vcpkg
|
||||
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
version: '6.6.0'
|
||||
host: 'linux'
|
||||
target: 'desktop'
|
||||
dir: '${{ github.workspace }}/qt/'
|
||||
install-deps: 'true'
|
||||
modules: 'qtspeech qtmultimedia'
|
||||
cache: 'true'
|
||||
cache-key-prefix: ${{ runner.os }}-qt-660
|
||||
|
||||
- name: Build project
|
||||
working-directory: pdf4qt
|
||||
run: |
|
||||
cmake -B build -S . -DPDF4QT_INSTALL_QT_DEPENDENCIES=0 -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release -DVCPKG_OVERLAY_PORTS=vcpkg/overlays -DPDF4QT_INSTALL_TO_USR=ON
|
||||
cmake --build build -j6
|
||||
cmake --install build
|
||||
cp -rp build/install build/install_appimage
|
||||
|
||||
- name: 'Linux Deploy Qt'
|
||||
working-directory: pdf4qt/build
|
||||
run: |
|
||||
wget -O deploy.AppImage https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage
|
||||
chmod +x deploy.AppImage
|
||||
./deploy.AppImage install/usr/share/applications/io.github.JakubMelka.Pdf4qt.desktop -executable-dir=install/usr/bin -extra-plugins=iconengines,imageformats,texttospeech
|
||||
|
||||
- name: Make DEB package
|
||||
working-directory: pdf4qt/build
|
||||
run: |
|
||||
sh make-package.sh
|
||||
|
||||
- name: Upload DEB package
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ubuntu-deb-package
|
||||
path: ./pdf4qt/build/*.deb
|
||||
retention-days: 30
|
||||
|
||||
- name: 'Make AppImage'
|
||||
working-directory: pdf4qt/build
|
||||
run: |
|
||||
cp install_appimage/usr/share/icons/hicolor/scalable/apps/io.github.JakubMelka.Pdf4qt.svg install_appimage/io.github.JakubMelka.Pdf4qt.svg
|
||||
./deploy.AppImage install_appimage/usr/share/applications/io.github.JakubMelka.Pdf4qt.desktop -appimage -executable-dir=install_appimage/usr/bin -always-overwrite -extra-plugins=iconengines,imageformats,texttospeech
|
||||
|
||||
- name: Upload AppImage package
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ubuntu-appimage
|
||||
path: ./pdf4qt/build/*.AppImage
|
||||
retention-days: 30
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build_ubuntu:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: pdf4qt
|
||||
|
||||
- name: 'VCPKG: Set up VCPKG'
|
||||
run: |
|
||||
git clone --depth=1 https://github.com/microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
|
||||
- name: 'VCPKG: Cache vcpkg dependencies'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./vcpkg/downloads
|
||||
./vcpkg/packages
|
||||
key: ${{ runner.os }}-vcpkg-v2-${{ hashFiles('**/vcpkg.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-vcpkg-v2-
|
||||
|
||||
- name: 'VCPKG: Install project dependencies'
|
||||
run: |
|
||||
./vcpkg install tbb openssl lcms zlib openjpeg freetype ijg-libjpeg libpng blend2d
|
||||
working-directory: vcpkg
|
||||
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
version: '6.6.0'
|
||||
host: 'linux'
|
||||
target: 'desktop'
|
||||
dir: '${{ github.workspace }}/qt/'
|
||||
install-deps: 'true'
|
||||
modules: 'qtspeech qtmultimedia'
|
||||
cache: 'true'
|
||||
cache-key-prefix: ${{ runner.os }}-qt-660
|
||||
|
||||
- name: Build project
|
||||
working-directory: pdf4qt
|
||||
run: |
|
||||
cmake -B build -S . -DPDF4QT_INSTALL_QT_DEPENDENCIES=0 -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build -j6
|
||||
cmake --install build
|
||||
|
||||
- name: Make DEB package
|
||||
working-directory: pdf4qt/build
|
||||
run: |
|
||||
sh make-package.sh
|
||||
|
||||
- name: Upload DEB package
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ubuntu-deb-package
|
||||
path: ./pdf4qt/build/*.deb
|
||||
retention-days: 30
|
||||
|
||||
build_windows:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: pdf4qt
|
||||
|
||||
- name: 'VCPKG: Set up VCPKG'
|
||||
run: |
|
||||
git clone --depth=1 https://github.com/microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
.\bootstrap-vcpkg.bat -disableMetrics
|
||||
.\vcpkg integrate install
|
||||
set VCPKG_ROOT=${env:GITHUB_WORKSPACE}\vcpkg\
|
||||
set "VCPKG_BINARY_SOURCES=clear;files,${env:GITHUB_WORKSPACE}\vcpkg\archives,readwrite"
|
||||
|
||||
- name: 'VCPKG: Cache vcpkg dependencies'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./vcpkg/downloads
|
||||
./vcpkg/packages
|
||||
./vcpkg/installed
|
||||
./vcpkg/archives
|
||||
key: ${{ runner.os }}-vcpkg-${{ hashFiles('**/vcpkg.json') }}
|
||||
|
||||
|
||||
- name: 'VCPKG: Install project dependencies'
|
||||
run: |
|
||||
.\vcpkg install tbb openssl lcms zlib openjpeg freetype ijg-libjpeg libpng blend2d --triplet x64-windows
|
||||
working-directory: vcpkg
|
||||
|
||||
- name: Install Qt
|
||||
uses: jurplel/install-qt-action@v3
|
||||
with:
|
||||
version: '6.6.0'
|
||||
host: 'windows'
|
||||
target: 'desktop'
|
||||
dir: '${{ github.workspace }}/qt/'
|
||||
install-deps: 'true'
|
||||
modules: 'qtspeech qtmultimedia'
|
||||
cache: 'true'
|
||||
cache-key-prefix: ${{ runner.os }}-qt-660
|
||||
|
||||
- name: Build project
|
||||
working-directory: pdf4qt
|
||||
shell: pwsh
|
||||
run: |
|
||||
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DPDF4QT_INSTALL_QT_DEPENDENCIES=ON -DPDF4QT_INSTALL_DEPENDENCIES=ON -DCMAKE_TOOLCHAIN_FILE="${env:GITHUB_WORKSPACE}\vcpkg\scripts\buildsystems\vcpkg.cmake" -DPDF4QT_QT_ROOT="${env:Qt6_DIR}" -DPDF4QT_INSTALL_MSVC_REDISTRIBUTABLE=ON -DPDF4QT_INSTALL_PREPARE_WIX_INSTALLER=ON -DPDF4QT_INSTALL_TO_USR=ON
|
||||
cmake --build build --config Release -j6
|
||||
cmake --install build
|
||||
|
||||
- name: Upload Windows package
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: 'pdf4qt-${{ runner.os }}.zip'
|
||||
path: .\pdf4qt\build\install\usr\bin
|
||||
retention-days: 30
|
|
@ -0,0 +1,2 @@
|
|||
ignore:
|
||||
- "LICENSE.rtf"
|
127
CMakeLists.txt
|
@ -1,4 +1,4 @@
|
|||
# Copyright (C) 2022 Jakub Melka
|
||||
# Copyright (C) 2023 Jakub Melka
|
||||
#
|
||||
# This file is part of PDF4QT.
|
||||
#
|
||||
|
@ -17,7 +17,8 @@
|
|||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
set(PDF4QT_VERSION 1.3.5)
|
||||
set(PDF4QT_VERSION 1.3.7)
|
||||
message(STATUS "Build type - CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
project(PDF4QT VERSION ${PDF4QT_VERSION} LANGUAGES CXX)
|
||||
|
||||
|
@ -32,6 +33,8 @@ if(WIN32 AND MSVC)
|
|||
option(PDF4QT_INSTALL_PREPARE_WIX_INSTALLER "Prepare Wix installer for Windows" ON)
|
||||
endif()
|
||||
|
||||
option(PDF4QT_BUILD_ONLY_CORE_LIBRARY "Build only core library" OFF)
|
||||
|
||||
set(PDF4QT_QT_ROOT "" CACHE PATH "Qt root directory")
|
||||
|
||||
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
|
@ -43,16 +46,22 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Svg Xml PrintSupport TextToSpeech OpenGL OpenGLWidgets Multimedia Network Test)
|
||||
if(PDF4QT_BUILD_ONLY_CORE_LIBRARY)
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Svg Xml)
|
||||
else()
|
||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Svg Xml PrintSupport TextToSpeech Test)
|
||||
endif()
|
||||
|
||||
qt_standard_project_setup()
|
||||
|
||||
find_package(OpenSSL REQUIRED)
|
||||
find_package(lcms REQUIRED)
|
||||
find_package(ZLIB REQUIRED)
|
||||
find_package(freetype CONFIG REQUIRED)
|
||||
find_package(Freetype REQUIRED)
|
||||
find_package(OpenJPEG CONFIG REQUIRED)
|
||||
find_package(JPEG REQUIRED)
|
||||
find_package(PNG REQUIRED)
|
||||
find_package(blend2d CONFIG REQUIRED)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
@ -80,33 +89,87 @@ if (LINUX_GCC)
|
|||
find_package(TBB REQUIRED)
|
||||
endif()
|
||||
|
||||
add_subdirectory(Pdf4QtLib)
|
||||
add_subdirectory(CodeGenerator)
|
||||
add_subdirectory(JBIG2_Viewer)
|
||||
add_subdirectory(PdfExampleGenerator)
|
||||
add_subdirectory(PdfTool)
|
||||
add_subdirectory(UnitTests)
|
||||
add_subdirectory(Pdf4QtViewer)
|
||||
add_subdirectory(Pdf4QtViewerPlugins)
|
||||
add_subdirectory(Pdf4QtViewerProfi)
|
||||
add_subdirectory(Pdf4QtViewerLite)
|
||||
add_subdirectory(Pdf4QtDocPageOrganizer)
|
||||
add_subdirectory(Pdf4QtDocDiff)
|
||||
add_subdirectory(WixInstaller)
|
||||
option(PDF4QT_INSTALL_TO_USR "Install to usr directory" ON)
|
||||
|
||||
if(PDF4QT_LINUX)
|
||||
set(PDF4QT_INSTALL_LIB_DIR_IMPL lib)
|
||||
set(PDF4QT_INSTALL_BIN_DIR_IMPL bin)
|
||||
|
||||
# Check if VCPKG_OVERLAY_PORTS is set as an environment variable or a CMake argument
|
||||
if(NOT DEFINED ENV{VCPKG_OVERLAY_PORTS} AND NOT DEFINED VCPKG_OVERLAY_PORTS)
|
||||
message(WARNING "The VCPKG_OVERLAY_PORTS variable is not set! Application can crash in Open/Save dialog due to incompatible LIBPNG.")
|
||||
else()
|
||||
set(VCPKG_OVERLAY_PORTS_VALUE "$ENV{VCPKG_OVERLAY_PORTS}")
|
||||
if(DEFINED VCPKG_OVERLAY_PORTS)
|
||||
set(VCPKG_OVERLAY_PORTS_VALUE "${VCPKG_OVERLAY_PORTS}")
|
||||
endif()
|
||||
message(STATUS "The VCPKG_OVERLAY_PORTS variable is set to: ${VCPKG_OVERLAY_PORTS_VALUE}")
|
||||
endif()
|
||||
|
||||
else()
|
||||
set(PDF4QT_INSTALL_LIB_DIR_IMPL bin)
|
||||
set(PDF4QT_INSTALL_BIN_DIR_IMPL bin)
|
||||
endif()
|
||||
|
||||
if(PDF4QT_INSTALL_TO_USR)
|
||||
set(PDF4QT_INSTALL_LIB_DIR usr/${PDF4QT_INSTALL_LIB_DIR_IMPL})
|
||||
set(PDF4QT_INSTALL_BIN_DIR usr/${PDF4QT_INSTALL_BIN_DIR_IMPL})
|
||||
set(PDF4QT_INSTALL_SHARE_DIR usr/share)
|
||||
else()
|
||||
set(PDF4QT_INSTALL_LIB_DIR ${PDF4QT_INSTALL_LIB_DIR_IMPL})
|
||||
set(PDF4QT_INSTALL_BIN_DIR ${PDF4QT_INSTALL_BIN_DIR_IMPL})
|
||||
set(PDF4QT_INSTALL_SHARE_DIR share)
|
||||
endif()
|
||||
|
||||
add_subdirectory(Pdf4QtLibCore)
|
||||
|
||||
if(NOT PDF4QT_BUILD_ONLY_CORE_LIBRARY)
|
||||
add_subdirectory(Pdf4QtLibWidgets)
|
||||
add_subdirectory(CodeGenerator)
|
||||
add_subdirectory(JBIG2_Viewer)
|
||||
add_subdirectory(PdfExampleGenerator)
|
||||
add_subdirectory(PdfTool)
|
||||
add_subdirectory(UnitTests)
|
||||
add_subdirectory(Pdf4QtLibGui)
|
||||
add_subdirectory(Pdf4QtEditorPlugins)
|
||||
add_subdirectory(Pdf4QtEditor)
|
||||
add_subdirectory(Pdf4QtViewer)
|
||||
add_subdirectory(Pdf4QtPageMaster)
|
||||
add_subdirectory(Pdf4QtDiff)
|
||||
add_subdirectory(Pdf4QtLaunchPad)
|
||||
add_subdirectory(WixInstaller)
|
||||
endif()
|
||||
|
||||
message("CMAKE_PREFIX_PATH = " ${CMAKE_PREFIX_PATH})
|
||||
message("CMAKE_TOOLCHAIN_FILE = " ${CMAKE_TOOLCHAIN_FILE})
|
||||
|
||||
install(FILES Desktop/io.github.JakubMelka.Pdf4qt.Pdf4QtDocDiff.desktop Desktop/io.github.JakubMelka.Pdf4qt.Pdf4QtDocPageOrganizer.desktop Desktop/io.github.JakubMelka.Pdf4qt.Pdf4QtViewerLite.desktop Desktop/io.github.JakubMelka.Pdf4qt.desktop DESTINATION share/applications)
|
||||
install(FILES Desktop/io.github.JakubMelka.Pdf4qt.Pdf4QtDocDiff.svg Desktop/io.github.JakubMelka.Pdf4qt.Pdf4QtDocPageOrganizer.svg Desktop/io.github.JakubMelka.Pdf4qt.Pdf4QtViewerLite.svg Desktop/io.github.JakubMelka.Pdf4qt.svg DESTINATION share/icons/hicolor/scalable/apps)
|
||||
install(FILES Desktop/io.github.JakubMelka.Pdf4qt.appdata.xml DESTINATION share/metainfo)
|
||||
install(FILES Desktop/128x128/io.github.JakubMelka.Pdf4qt.Pdf4QtDocDiff.png Desktop/128x128/io.github.JakubMelka.Pdf4qt.Pdf4QtDocPageOrganizer.png Desktop/128x128/io.github.JakubMelka.Pdf4qt.Pdf4QtViewerLite.png Desktop/128x128/io.github.JakubMelka.Pdf4qt.png DESTINATION share/icons/hicolor/128x128/apps)
|
||||
if(NOT PDF4QT_BUILD_ONLY_CORE_LIBRARY)
|
||||
install(FILES Desktop/io.github.JakubMelka.Pdf4qt.Pdf4QtDiff.desktop
|
||||
Desktop/io.github.JakubMelka.Pdf4qt.Pdf4QtPageMaster.desktop
|
||||
Desktop/io.github.JakubMelka.Pdf4qt.Pdf4QtViewer.desktop
|
||||
Desktop/io.github.JakubMelka.Pdf4qt.Pdf4QtEditor.desktop
|
||||
Desktop/io.github.JakubMelka.Pdf4qt.desktop
|
||||
DESTINATION ${PDF4QT_INSTALL_SHARE_DIR}/applications)
|
||||
install(FILES Desktop/io.github.JakubMelka.Pdf4qt.Pdf4QtDiff.svg
|
||||
Desktop/io.github.JakubMelka.Pdf4qt.Pdf4QtPageMaster.svg
|
||||
Desktop/io.github.JakubMelka.Pdf4qt.Pdf4QtViewer.svg
|
||||
Desktop/io.github.JakubMelka.Pdf4qt.Pdf4QtEditor.svg
|
||||
Desktop/io.github.JakubMelka.Pdf4qt.svg
|
||||
DESTINATION ${PDF4QT_INSTALL_SHARE_DIR}/icons/hicolor/scalable/apps)
|
||||
install(FILES Desktop/io.github.JakubMelka.Pdf4qt.appdata.xml DESTINATION ${PDF4QT_INSTALL_SHARE_DIR}/metainfo)
|
||||
install(FILES Desktop/128x128/io.github.JakubMelka.Pdf4qt.Pdf4QtDiff.png
|
||||
Desktop/128x128/io.github.JakubMelka.Pdf4qt.Pdf4QtPageMaster.png
|
||||
Desktop/128x128/io.github.JakubMelka.Pdf4qt.Pdf4QtViewer.png
|
||||
Desktop/128x128/io.github.JakubMelka.Pdf4qt.Pdf4QtEditor.png
|
||||
Desktop/128x128/io.github.JakubMelka.Pdf4qt.png
|
||||
DESTINATION ${PDF4QT_INSTALL_SHARE_DIR}/icons/hicolor/128x128/apps)
|
||||
|
||||
configure_file(make-package.sh.in make-package.sh)
|
||||
configure_file(make-package.sh.in make-package.sh)
|
||||
endif()
|
||||
|
||||
if(PDF4QT_INSTALL_DEPENDENCIES)
|
||||
if(PDF4QT_INSTALL_DEPENDENCIES AND NOT PDF4QT_BUILD_ONLY_CORE_LIBRARY)
|
||||
install(DIRECTORY ${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/bin/
|
||||
TYPE BIN
|
||||
RUNTIME DESTINATION ${PDF4QT_INSTALL_LIB_DIR}/
|
||||
FILES_MATCHING
|
||||
PATTERN "*.dll"
|
||||
PATTERN "*.so"
|
||||
|
@ -119,14 +182,14 @@ if(PDF4QT_INSTALL_DEPENDENCIES)
|
|||
|
||||
if(PDF4QT_INSTALL_QT_DEPENDENCIES)
|
||||
install(DIRECTORY ${PDF4QT_QT_ROOT}/bin/
|
||||
RUNTIME DESTINATION bin/
|
||||
RUNTIME DESTINATION ${PDF4QT_INSTALL_LIB_DIR}/
|
||||
FILES_MATCHING
|
||||
REGEX "(Qt6Core|Qt6Gui|Qt6PrintSupport|Qt6Svg|Qt6TextToSpeech|Qt6Widgets|Qt6Xml|Qt6OpenGL|Qt6OpenGLWidgets|Qt6Multimedia|Qt6Network)\\..*"
|
||||
REGEX "(Qt6Core|Qt6Gui|Qt6PrintSupport|Qt6Svg|Qt6TextToSpeech|Qt6Widgets|Qt6Xml|Qt6Multimedia|Qt6Network)\\..*"
|
||||
PATTERN "Debug" EXCLUDE
|
||||
)
|
||||
|
||||
install(DIRECTORY ${PDF4QT_QT_ROOT}/plugins/platforms/
|
||||
RUNTIME DESTINATION bin/platforms/
|
||||
RUNTIME DESTINATION ${PDF4QT_INSTALL_LIB_DIR}/platforms/
|
||||
FILES_MATCHING
|
||||
PATTERN "qwindows.dll"
|
||||
PATTERN "*.so"
|
||||
|
@ -134,13 +197,13 @@ if(PDF4QT_INSTALL_DEPENDENCIES)
|
|||
)
|
||||
|
||||
install(DIRECTORY ${PDF4QT_QT_ROOT}/plugins/iconengines/
|
||||
RUNTIME DESTINATION bin/iconengines/
|
||||
RUNTIME DESTINATION ${PDF4QT_INSTALL_LIB_DIR}/iconengines/
|
||||
FILES_MATCHING
|
||||
REGEX "qsvgicon\\..*"
|
||||
)
|
||||
|
||||
install(DIRECTORY ${PDF4QT_QT_ROOT}/plugins/imageformats/
|
||||
RUNTIME DESTINATION bin/imageformats/
|
||||
RUNTIME DESTINATION ${PDF4QT_INSTALL_LIB_DIR}/imageformats/
|
||||
FILES_MATCHING
|
||||
PATTERN "*.dll"
|
||||
PATTERN "*.so"
|
||||
|
@ -149,7 +212,7 @@ if(PDF4QT_INSTALL_DEPENDENCIES)
|
|||
)
|
||||
|
||||
install(DIRECTORY ${PDF4QT_QT_ROOT}/plugins/styles/
|
||||
RUNTIME DESTINATION bin/styles/
|
||||
RUNTIME DESTINATION ${PDF4QT_INSTALL_LIB_DIR}/styles/
|
||||
FILES_MATCHING
|
||||
PATTERN "*.dll"
|
||||
PATTERN "*.so"
|
||||
|
@ -158,7 +221,7 @@ if(PDF4QT_INSTALL_DEPENDENCIES)
|
|||
)
|
||||
|
||||
install(DIRECTORY ${PDF4QT_QT_ROOT}/plugins/texttospeech/
|
||||
RUNTIME DESTINATION bin/texttospeech/
|
||||
RUNTIME DESTINATION ${PDF4QT_INSTALL_LIB_DIR}/texttospeech/
|
||||
FILES_MATCHING
|
||||
PATTERN "*.dll"
|
||||
PATTERN "*.so"
|
||||
|
@ -172,7 +235,7 @@ if(PDF4QT_INSTALL_DEPENDENCIES)
|
|||
message(STATUS "MSVC Redistributable Package Path = ${MSVC_REDISTRIBUTABLES_PATH}")
|
||||
|
||||
install(DIRECTORY ${MSVC_REDISTRIBUTABLES_PATH}/
|
||||
RUNTIME DESTINATION bin/
|
||||
RUNTIME DESTINATION ${PDF4QT_INSTALL_LIB_DIR}/
|
||||
FILES_MATCHING
|
||||
PATTERN "*.dll"
|
||||
)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Copyright (C) 2022 Jakub Melka
|
||||
# Copyright (C) 2022-2023 Jakub Melka
|
||||
#
|
||||
# This file is part of PDF4QT.
|
||||
#
|
||||
|
@ -17,14 +17,18 @@
|
|||
|
||||
add_executable(CodeGenerator
|
||||
codegenerator.cpp
|
||||
codegenerator.h
|
||||
main.cpp
|
||||
generatormainwindow.cpp
|
||||
generatormainwindow.ui
|
||||
generatormainwindow.h
|
||||
generatormainwindow.ui
|
||||
)
|
||||
|
||||
target_link_libraries(CodeGenerator PRIVATE Pdf4QtLib Qt6::Core Qt6::Widgets Qt6::Gui Qt6::Xml)
|
||||
target_link_libraries(CodeGenerator PRIVATE Pdf4QtLibCore Qt6::Core Qt6::Widgets Qt6::Gui Qt6::Xml)
|
||||
|
||||
set_target_properties(CodeGenerator PROPERTIES
|
||||
WIN32_EXECUTABLE ON
|
||||
MACOSX_BUNDLE ON
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PDF4QT_INSTALL_LIB_DIR}
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PDF4QT_INSTALL_BIN_DIR}
|
||||
)
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
qSetGlobalQHashSeed(0);
|
||||
QHashSeed::globalSeed().setDeterministicGlobalSeed();
|
||||
|
||||
QApplication a(argc, argv);
|
||||
GeneratorMainWindow w;
|
||||
w.show();
|
||||
|
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 3.4 KiB |
|
@ -0,0 +1,10 @@
|
|||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Name=PDF4QT Diff
|
||||
Comment=Compare PDF documents
|
||||
Exec=Pdf4QtDiff
|
||||
Icon=io.github.JakubMelka.Pdf4qt.Pdf4QtDiff
|
||||
Terminal=false
|
||||
Categories=Office;
|
||||
MimeType=application/pdf;
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
@ -1,10 +0,0 @@
|
|||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Name=PDF4QT DocDiff
|
||||
Comment=Compare PDF documents
|
||||
Exec=Pdf4QtDocDiff
|
||||
Icon=io.github.JakubMelka.Pdf4qt.Pdf4QtDocDiff.svg
|
||||
Terminal=false
|
||||
Categories=Office
|
||||
MimeType=application/pdf
|
|
@ -1,10 +0,0 @@
|
|||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Name=PDF4QT DocPage Organizer
|
||||
Comment=Organize, merge, split, and duplicate pages in PDF files
|
||||
Exec=Pdf4QtDocPageOrganizer
|
||||
Icon=io.github.JakubMelka.Pdf4qt.Pdf4QtDocPageOrganizer.svg
|
||||
Terminal=false
|
||||
Categories=Office
|
||||
MimeType=application/pdf
|
|
@ -0,0 +1,10 @@
|
|||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Name=PDF4QT Editor
|
||||
Comment=Edit and modify PDF files
|
||||
Exec=Pdf4QtEditor
|
||||
Icon=io.github.JakubMelka.Pdf4qt.Pdf4QtEditor.svg
|
||||
Terminal=false
|
||||
Categories=Office;
|
||||
MimeType=application/pdf;
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
@ -0,0 +1,10 @@
|
|||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Name=PDF4QT PageMaster
|
||||
Comment=Organize, merge, split, and duplicate pages in PDF files
|
||||
Exec=Pdf4QtPageMaster
|
||||
Icon=io.github.JakubMelka.Pdf4qt.Pdf4QtPageMaster
|
||||
Terminal=false
|
||||
Categories=Office;
|
||||
MimeType=application/pdf;
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
@ -0,0 +1,10 @@
|
|||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Name=PDF4QT Viewer
|
||||
Comment=View and navigate PDF documents
|
||||
Exec=Pdf4QtViewer
|
||||
Icon=io.github.JakubMelka.Pdf4qt.Pdf4QtViewer
|
||||
Terminal=false
|
||||
Categories=Office;
|
||||
MimeType=application/pdf;
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
@ -1,10 +0,0 @@
|
|||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Name=PDF4QT Viewer Lite
|
||||
Comment=View and navigate PDF documents
|
||||
Exec=Pdf4QtViewerLite
|
||||
Icon=io.github.JakubMelka.Pdf4qt.Pdf4QtViewerLite.svg
|
||||
Terminal=false
|
||||
Categories=Office
|
||||
MimeType=application/pdf
|
|
@ -23,6 +23,8 @@
|
|||
<content_rating type="oars-1.1"/>
|
||||
<launchable type="desktop-id">io.github.JakubMelka.Pdf4qt.desktop</launchable>
|
||||
<releases>
|
||||
<release version="1.3.7" date="2024-01-10"/>
|
||||
<release version="1.3.6" date="2023-11-24"/>
|
||||
<release version="1.3.5" date="2023-09-08"/>
|
||||
<release version="1.3.4" date="2023-08-03"/>
|
||||
<release version="1.3.3" date="2023-04-22"/>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
[Desktop Entry]
|
||||
Version=1.0
|
||||
Type=Application
|
||||
Name=PDF4QT Viewer Profi
|
||||
Comment=Edit and modify PDF files
|
||||
Exec=Pdf4QtViewerProfi
|
||||
Icon=io.github.JakubMelka.Pdf4qt.svg
|
||||
Name=PDF4QT LaunchPad
|
||||
Comment=Launch PDF applications
|
||||
Exec=Pdf4QtLaunchPad
|
||||
Icon=io.github.JakubMelka.Pdf4qt
|
||||
Terminal=false
|
||||
Categories=Office
|
||||
MimeType=application/pdf
|
||||
Categories=Office;
|
||||
MimeType=application/pdf;
|
||||
|
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 7.0 KiB |
|
@ -1,4 +1,4 @@
|
|||
# Copyright (C) 2022 Jakub Melka
|
||||
# Copyright (C) 2022-2023 Jakub Melka
|
||||
#
|
||||
# This file is part of PDF4QT.
|
||||
#
|
||||
|
@ -18,12 +18,15 @@
|
|||
add_executable(JBIG2_VIEWER
|
||||
mainwindow.ui
|
||||
mainwindow.cpp
|
||||
mainwindow.h
|
||||
main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(JBIG2_VIEWER PRIVATE Pdf4QtLib Qt6::Core Qt6::Widgets Qt6::Gui)
|
||||
target_link_libraries(JBIG2_VIEWER PRIVATE Pdf4QtLibCore Qt6::Core Qt6::Widgets Qt6::Gui)
|
||||
|
||||
set_target_properties(JBIG2_VIEWER PROPERTIES
|
||||
WIN32_EXECUTABLE ON
|
||||
MACOSX_BUNDLE ON
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PDF4QT_INSTALL_LIB_DIR}
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PDF4QT_INSTALL_BIN_DIR}
|
||||
)
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
# Copyright (C) 2022-2024 Jakub Melka
|
||||
#
|
||||
# This file is part of PDF4QT.
|
||||
#
|
||||
# PDF4QT is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# with the written consent of the copyright owner, any later version.
|
||||
#
|
||||
# PDF4QT is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
add_executable(Pdf4QtDiff
|
||||
aboutdialog.cpp
|
||||
aboutdialog.h
|
||||
differencesdockwidget.cpp
|
||||
differencesdockwidget.h
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
mainwindow.h
|
||||
settingsdockwidget.cpp
|
||||
settingsdockwidget.h
|
||||
utils.cpp
|
||||
utils.h
|
||||
aboutdialog.ui
|
||||
differencesdockwidget.ui
|
||||
mainwindow.ui
|
||||
settingsdockwidget.ui
|
||||
resources.qrc
|
||||
icon.rc
|
||||
app.qrc
|
||||
settings.h
|
||||
)
|
||||
|
||||
target_link_libraries(Pdf4QtDiff PRIVATE Pdf4QtLibCore Pdf4QtLibWidgets Qt6::Core Qt6::Gui Qt6::Widgets)
|
||||
|
||||
set_target_properties(Pdf4QtDiff PROPERTIES
|
||||
WIN32_EXECUTABLE ON
|
||||
MACOSX_BUNDLE ON
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PDF4QT_INSTALL_LIB_DIR}
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${PDF4QT_INSTALL_BIN_DIR}
|
||||
)
|
||||
|
||||
install(TARGETS Pdf4QtDiff RUNTIME DESTINATION ${PDF4QT_INSTALL_BIN_DIR} LIBRARY DESTINATION ${PDF4QT_INSTALL_LIB_DIR})
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "aboutdialog.h"
|
||||
#include "ui_aboutdialog.h"
|
||||
|
||||
#include "pdfutils.h"
|
||||
#include "pdfwidgetutils.h"
|
||||
|
||||
namespace pdfdiff
|
||||
{
|
||||
|
||||
PDFAboutDialog::PDFAboutDialog(QWidget* parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::PDFAboutDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QString html = ui->copyrightLabel->text();
|
||||
html.replace("PdfForQtViewer", QString("%1 %2").arg(QApplication::applicationDisplayName(), QApplication::applicationVersion()));
|
||||
ui->copyrightLabel->setText(html);
|
||||
|
||||
std::vector<pdf::PDFDependentLibraryInfo> infos = pdf::PDFDependentLibraryInfo::getLibraryInfo();
|
||||
|
||||
ui->tableWidget->setColumnCount(4);
|
||||
ui->tableWidget->setRowCount(static_cast<int>(infos.size()));
|
||||
ui->tableWidget->setHorizontalHeaderLabels(QStringList() << tr("Library") << tr("Version") << tr("License") << tr("URL"));
|
||||
ui->tableWidget->setEditTriggers(QTableWidget::NoEditTriggers);
|
||||
ui->tableWidget->setSelectionMode(QTableView::SingleSelection);
|
||||
ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
|
||||
for (int i = 0; i < infos.size(); ++i)
|
||||
{
|
||||
const pdf::PDFDependentLibraryInfo& info = infos[i];
|
||||
ui->tableWidget->setItem(i, 0, new QTableWidgetItem(info.library));
|
||||
ui->tableWidget->setItem(i, 1, new QTableWidgetItem(info.version));
|
||||
ui->tableWidget->setItem(i, 2, new QTableWidgetItem(info.license));
|
||||
ui->tableWidget->setItem(i, 3, new QTableWidgetItem(info.url));
|
||||
}
|
||||
|
||||
pdf::PDFWidgetUtils::scaleWidget(this, QSize(750, 600));
|
||||
pdf::PDFWidgetUtils::style(this);
|
||||
}
|
||||
|
||||
PDFAboutDialog::~PDFAboutDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
} // namespace pdfdiff
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFDIFF_PDFABOUTDIALOG_H
|
||||
#define PDFDIFF_PDFABOUTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class PDFAboutDialog;
|
||||
}
|
||||
|
||||
namespace pdfdiff
|
||||
{
|
||||
|
||||
class PDFAboutDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PDFAboutDialog(QWidget* parent);
|
||||
virtual ~PDFAboutDialog() override;
|
||||
|
||||
private:
|
||||
Ui::PDFAboutDialog* ui;
|
||||
};
|
||||
|
||||
} // namespace pdfdiff
|
||||
|
||||
#endif // PDFDIFF_PDFABOUTDIALOG_H
|
|
@ -0,0 +1,272 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PDFAboutDialog</class>
|
||||
<widget class="QDialog" name="PDFAboutDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>900</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>900</width>
|
||||
<height>600</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>About</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="copyrightLabel">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-weight:600;">PdfForQtViewer</span></p><p>Copyright 2018-2024 Jakub Melka. All rights reserved.</p><p>THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="textEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
hr { height: 1px; border-width: 0; }
|
||||
li.unchecked::marker { content: "\2610"; }
|
||||
li.checked::marker { content: "\2612"; }
|
||||
</style></head><body style=" font-family:'Segoe UI'; font-size:9pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> GNU LESSER GENERAL PUBLIC LICENSE</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> Version 3, 29 June 2007</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> Copyright (C) 2007 Free Software Foundation, Inc. &lt;https://fsf.org/&gt;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> Everyone is permitted to copy and distribute verbatim copies</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> of this license document, but changing it is not allowed.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> This version of the GNU Lesser General Public License incorporates</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">the terms and conditions of version 3 of the GNU General Public</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">License, supplemented by the additional permissions listed below.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> 0. Additional Definitions.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> As used herein, &quot;this License&quot; refers to version 3 of the GNU Lesser</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">General Public License, and the &quot;GNU GPL&quot; refers to version 3 of the GNU</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">General Public License.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> &quot;The Library&quot; refers to a covered work governed by this License,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">other than an Application or a Combined Work as defined below.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> An &quot;Application&quot; is any work that makes use of an interface provided</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">by the Library, but which is not otherwise based on the Library.</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">Defining a subclass of a class defined by the Library is deemed a mode</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">of using an interface provided by the Library.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> A &quot;Combined Work&quot; is a work produced by combining or linking an</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">Application with the Library. The particular version of the Library</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">with which the Combined Work was made is also called the &quot;Linked</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">Version&quot;.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> The &quot;Minimal Corresponding Source&quot; for a Combined Work means the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">Corresponding Source for the Combined Work, excluding any source code</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">for portions of the Combined Work that, considered in isolation, are</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">based on the Application, and not on the Linked Version.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> The &quot;Corresponding Application Code&quot; for a Combined Work means the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">object code and/or source code for the Application, including any data</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">and utility programs needed for reproducing the Combined Work from the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">Application, but excluding the System Libraries of the Combined Work.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> 1. Exception to Section 3 of the GNU GPL.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> You may convey a covered work under sections 3 and 4 of this License</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">without being bound by section 3 of the GNU GPL.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> 2. Conveying Modified Versions.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> If you modify a copy of the Library, and, in your modifications, a</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">facility refers to a function or data to be supplied by an Application</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">that uses the facility (other than as an argument passed when the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">facility is invoked), then you may convey a copy of the modified</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">version:</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> a) under this License, provided that you make a good faith effort to</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> ensure that, in the event an Application does not supply the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> function or data, the facility still operates, and performs</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> whatever part of its purpose remains meaningful, or</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> b) under the GNU GPL, with none of the additional permissions of</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> this License applicable to that copy.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> 3. Object Code Incorporating Material from Library Header Files.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> The object code form of an Application may incorporate material from</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">a header file that is part of the Library. You may convey such object</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">code under terms of your choice, provided that, if the incorporated</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">material is not limited to numerical parameters, data structure</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">layouts and accessors, or small macros, inline functions and templates</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">(ten or fewer lines in length), you do both of the following:</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> a) Give prominent notice with each copy of the object code that the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> Library is used in it and that the Library and its use are</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> covered by this License.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> b) Accompany the object code with a copy of the GNU GPL and this license</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> document.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> 4. Combined Works.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> You may convey a Combined Work under terms of your choice that,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">taken together, effectively do not restrict modification of the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">portions of the Library contained in the Combined Work and reverse</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">engineering for debugging such modifications, if you also do each of</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">the following:</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> a) Give prominent notice with each copy of the Combined Work that</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> the Library is used in it and that the Library and its use are</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> covered by this License.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> b) Accompany the Combined Work with a copy of the GNU GPL and this license</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> document.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> c) For a Combined Work that displays copyright notices during</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> execution, include the copyright notice for the Library among</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> these notices, as well as a reference directing the user to the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> copies of the GNU GPL and this license document.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> d) Do one of the following:</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> 0) Convey the Minimal Corresponding Source under the terms of this</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> License, and the Corresponding Application Code in a form</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> suitable for, and under terms that permit, the user to</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> recombine or relink the Application with a modified version of</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> the Linked Version to produce a modified Combined Work, in the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> manner specified by section 6 of the GNU GPL for conveying</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> Corresponding Source.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> 1) Use a suitable shared library mechanism for linking with the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> Library. A suitable mechanism is one that (a) uses at run time</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> a copy of the Library already present on the user's computer</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> system, and (b) will operate properly with a modified version</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> of the Library that is interface-compatible with the Linked</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> Version.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> e) Provide Installation Information, but only if you would otherwise</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> be required to provide such information under section 6 of the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> GNU GPL, and only to the extent that such information is</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> necessary to install and execute a modified version of the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> Combined Work produced by recombining or relinking the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> Application with a modified version of the Linked Version. (If</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> you use option 4d0, the Installation Information must accompany</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> the Minimal Corresponding Source and Corresponding Application</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> Code. If you use option 4d1, you must provide the Installation</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> Information in the manner specified by section 6 of the GNU GPL</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> for conveying Corresponding Source.)</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> 5. Combined Libraries.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> You may place library facilities that are a work based on the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">Library side by side in a single library together with other library</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">facilities that are not Applications and are not covered by this</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">License, and convey such a combined library under terms of your</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">choice, if you do both of the following:</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> a) Accompany the combined library with a copy of the same work based</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> on the Library, uncombined with any other library facilities,</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> conveyed under the terms of this License.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> b) Give prominent notice with the combined library that part of it</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> is a work based on the Library, and explaining where to find the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> accompanying uncombined form of the same work.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> 6. Revised Versions of the GNU Lesser General Public License.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> The Free Software Foundation may publish revised and/or new versions</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">of the GNU Lesser General Public License from time to time. Such new</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">versions will be similar in spirit to the present version, but may</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">differ in detail to address new problems or concerns.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> Each version is given a distinguishing version number. If the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">Library as you received it specifies that a certain numbered version</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">of the GNU Lesser General Public License &quot;or any later version&quot;</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">applies to it, you have the option of following the terms and</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">conditions either of that published version or of any later version</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">published by the Free Software Foundation. If the Library as you</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">received it does not specify a version number of the GNU Lesser</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">General Public License, you may choose any version of the GNU Lesser</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">General Public License ever published by the Free Software Foundation.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;"> If the Library as you received it specifies that a proxy can decide</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">whether future versions of the GNU Lesser General Public License shall</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">apply, that proxy's public statement of acceptance of any version is</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">permanent authorization for you to choose that version for the</span></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt;">Library.</span></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:7.875pt;"><br /></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="usedLibrariesLabel">
|
||||
<property name="text">
|
||||
<string>Used libraries</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="tableWidget"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>PDFAboutDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>PDFAboutDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
@ -0,0 +1,5 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>app-icon.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -0,0 +1,307 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "differencesdockwidget.h"
|
||||
#include "ui_differencesdockwidget.h"
|
||||
|
||||
#include "pdfdiff.h"
|
||||
#include "pdfwidgetutils.h"
|
||||
|
||||
#include <QPixmap>
|
||||
#include <QPainter>
|
||||
#include <QTreeWidgetItem>
|
||||
|
||||
namespace pdfdiff
|
||||
{
|
||||
|
||||
DifferenceItemDelegate::DifferenceItemDelegate(QObject* parent) :
|
||||
BaseClass(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DifferenceItemDelegate::paint(QPainter* painter,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const
|
||||
{
|
||||
BaseClass::paint(painter, option, index);
|
||||
}
|
||||
|
||||
QSize DifferenceItemDelegate::sizeHint(const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const
|
||||
{
|
||||
QStyleOptionViewItem adjustedOption = option;
|
||||
|
||||
if (!option.rect.isValid())
|
||||
{
|
||||
// Jakub Melka: Why this? We need to use text wrapping. Unfortunately,
|
||||
// standard delegate needs correct text rectangle (at least rectangle width),
|
||||
// for word wrap calculation. So we must manually calculate rectangle width.
|
||||
// Of course, we cant use visualRect of the tree widget, because of cyclical
|
||||
// dependence.
|
||||
|
||||
const QTreeWidget* treeWidget = qobject_cast<const QTreeWidget*>(option.widget);
|
||||
int xOffset = treeWidget->columnViewportPosition(index.column());
|
||||
int height = option.fontMetrics.lineSpacing();
|
||||
int yOffset = 0;
|
||||
int width = treeWidget->columnWidth(index.column());
|
||||
|
||||
int level = treeWidget->rootIsDecorated() ? 1 : 0;
|
||||
QModelIndex currentIndex = index.parent();
|
||||
while (currentIndex.isValid())
|
||||
{
|
||||
++level;
|
||||
currentIndex = currentIndex.parent();
|
||||
}
|
||||
|
||||
xOffset += level * treeWidget->indentation();
|
||||
adjustedOption.rect = QRect(xOffset, yOffset, width - xOffset, height);
|
||||
}
|
||||
|
||||
return BaseClass::sizeHint(adjustedOption, index);
|
||||
}
|
||||
|
||||
DifferencesDockWidget::DifferencesDockWidget(QWidget* parent,
|
||||
pdf::PDFDiffResult* unfilteredDiffResult,
|
||||
pdf::PDFDiffResult* diffResult,
|
||||
pdf::PDFDiffResultNavigator* diffNavigator,
|
||||
Settings* settings) :
|
||||
QDockWidget(parent),
|
||||
ui(new Ui::DifferencesDockWidget),
|
||||
m_unfilteredDiffResult(unfilteredDiffResult),
|
||||
m_diffResult(diffResult),
|
||||
m_diffNavigator(diffNavigator),
|
||||
m_settings(settings),
|
||||
m_disableChangeSelectedResultIndex(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->differencesTreeWidget->setItemDelegate(new DifferenceItemDelegate(this));
|
||||
ui->differencesTreeWidget->setIconSize(pdf::PDFWidgetUtils::scaleDPI(ui->differencesTreeWidget, QSize(16, 16)));
|
||||
connect(diffNavigator, &pdf::PDFDiffResultNavigator::selectionChanged, this, &DifferencesDockWidget::onSelectionChanged);
|
||||
connect(ui->differencesTreeWidget, &QTreeWidget::currentItemChanged, this, &DifferencesDockWidget::onCurrentItemChanged);
|
||||
|
||||
toggleViewAction()->setText(tr("Differen&ces"));
|
||||
|
||||
setMinimumWidth(pdf::PDFWidgetUtils::scaleDPI_x(this, 120));
|
||||
}
|
||||
|
||||
DifferencesDockWidget::~DifferencesDockWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QColor DifferencesDockWidget::getColorForIndex(size_t index) const
|
||||
{
|
||||
QColor color;
|
||||
|
||||
const size_t resultIndex = index;
|
||||
|
||||
if (m_diffResult->isReplaceDifference(resultIndex))
|
||||
{
|
||||
color = m_settings->colorReplaced;
|
||||
}
|
||||
else if (m_diffResult->isRemoveDifference(resultIndex))
|
||||
{
|
||||
color = m_settings->colorRemoved;
|
||||
}
|
||||
else if (m_diffResult->isAddDifference(resultIndex))
|
||||
{
|
||||
color = m_settings->colorAdded;
|
||||
}
|
||||
else if (m_diffResult->isPageMoveDifference(resultIndex))
|
||||
{
|
||||
color = m_settings->colorPageMove;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
QModelIndex DifferencesDockWidget::findResultIndex(size_t index) const
|
||||
{
|
||||
QAbstractItemModel* model = ui->differencesTreeWidget->model();
|
||||
const int count = ui->differencesTreeWidget->topLevelItemCount();
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
QModelIndex parentIndex = model->index(i, 0);
|
||||
if (parentIndex.isValid())
|
||||
{
|
||||
const int childCount = model->rowCount(parentIndex);
|
||||
for (int j = 0; j < childCount; ++j)
|
||||
{
|
||||
QModelIndex childIndex = model->index(j, 0, parentIndex);
|
||||
QVariant childUserData = childIndex.data(Qt::UserRole);
|
||||
if (childUserData.isValid())
|
||||
{
|
||||
if (childUserData.toULongLong() == index)
|
||||
{
|
||||
return childIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
void DifferencesDockWidget::update()
|
||||
{
|
||||
ui->differencesTreeWidget->clear();
|
||||
|
||||
QList<QTreeWidgetItem*> topItems;
|
||||
|
||||
QLocale locale;
|
||||
|
||||
if (m_diffResult && !m_diffResult->isSame())
|
||||
{
|
||||
std::map<QRgb, QIcon> icons;
|
||||
auto getIcon = [this, &icons](QColor color)
|
||||
{
|
||||
auto it = icons.find(color.rgb());
|
||||
if (it == icons.end())
|
||||
{
|
||||
QPixmap pixmap(ui->differencesTreeWidget->iconSize());
|
||||
pixmap.fill(Qt::transparent);
|
||||
|
||||
QPainter painter(&pixmap);
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setBrush(QBrush(color));
|
||||
painter.drawEllipse(0, 0, pixmap.width(), pixmap.height());
|
||||
painter.end();
|
||||
|
||||
QIcon icon(pixmap);
|
||||
it = icons.insert(std::make_pair(color.rgb(), std::move(icon))).first;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
};
|
||||
|
||||
const size_t differenceCount = m_diffResult->getDifferencesCount();
|
||||
const size_t unfilteredDifferenceCount = m_unfilteredDiffResult->getDifferencesCount();
|
||||
const size_t hiddenDifferences = unfilteredDifferenceCount - differenceCount;
|
||||
|
||||
if (hiddenDifferences > 0)
|
||||
{
|
||||
ui->infoTextLabel->setText(tr("%1 Differences (+%2 hidden)").arg(differenceCount).arg(hiddenDifferences));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->infoTextLabel->setText(tr("%1 Differences").arg(differenceCount));
|
||||
}
|
||||
|
||||
pdf::PDFInteger lastLeftPageIndex = -1;
|
||||
pdf::PDFInteger lastRightPageIndex = -1;
|
||||
|
||||
for (size_t i = 0; i < differenceCount; ++i)
|
||||
{
|
||||
pdf::PDFInteger pageIndexLeft = m_diffResult->getLeftPage(i);
|
||||
pdf::PDFInteger pageIndexRight = m_diffResult->getRightPage(i);
|
||||
|
||||
if (lastLeftPageIndex != pageIndexLeft ||
|
||||
lastRightPageIndex != pageIndexRight ||
|
||||
topItems.empty())
|
||||
{
|
||||
// Create new top level item
|
||||
QStringList captionParts;
|
||||
captionParts << QString("#%1:").arg(topItems.size() + 1);
|
||||
|
||||
if (pageIndexLeft == pageIndexRight)
|
||||
{
|
||||
captionParts << tr("Page %1").arg(locale.toString(pageIndexLeft + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pageIndexLeft != -1)
|
||||
{
|
||||
captionParts << tr("Left %1").arg(locale.toString(pageIndexLeft + 1));
|
||||
}
|
||||
|
||||
if (pageIndexRight != -1)
|
||||
{
|
||||
captionParts << tr("Right %1").arg(locale.toString(pageIndexRight + 1));
|
||||
}
|
||||
}
|
||||
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(QStringList() << captionParts.join(" "));
|
||||
topItems << item;
|
||||
|
||||
lastLeftPageIndex = pageIndexLeft;
|
||||
lastRightPageIndex = pageIndexRight;
|
||||
}
|
||||
|
||||
Q_ASSERT(!topItems.isEmpty());
|
||||
QTreeWidgetItem* parent = topItems.back();
|
||||
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(parent, QStringList() << m_diffResult->getMessage(i));
|
||||
item->setData(0, Qt::UserRole, QVariant(static_cast<qint64>(i)));
|
||||
|
||||
QColor color = getColorForIndex(i);
|
||||
|
||||
if (color.isValid())
|
||||
{
|
||||
item->setData(0, Qt::DecorationRole, getIcon(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->infoTextLabel->setText(tr("No Differences Found!"));
|
||||
}
|
||||
|
||||
ui->differencesTreeWidget->addTopLevelItems(topItems);
|
||||
ui->differencesTreeWidget->expandAll();
|
||||
}
|
||||
|
||||
void DifferencesDockWidget::onSelectionChanged(size_t currentIndex)
|
||||
{
|
||||
if (m_disableChangeSelectedResultIndex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pdf::PDFTemporaryValueChange guard(&m_disableChangeSelectedResultIndex, true);
|
||||
|
||||
QModelIndex index = findResultIndex(currentIndex);
|
||||
if (index.isValid())
|
||||
{
|
||||
ui->differencesTreeWidget->scrollTo(index);
|
||||
ui->differencesTreeWidget->setCurrentIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
void DifferencesDockWidget::onCurrentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous)
|
||||
{
|
||||
Q_UNUSED(previous);
|
||||
|
||||
if (m_disableChangeSelectedResultIndex || !current)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pdf::PDFTemporaryValueChange guard(&m_disableChangeSelectedResultIndex, true);
|
||||
QVariant childUserData = current->data(0, Qt::UserRole);
|
||||
|
||||
if (childUserData.isValid())
|
||||
{
|
||||
m_diffNavigator->select(childUserData.toULongLong());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pdfdiff
|
|
@ -0,0 +1,89 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFDIFF_DIFFERENCESDOCKWIDGET_H
|
||||
#define PDFDIFF_DIFFERENCESDOCKWIDGET_H
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QItemDelegate>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class DifferencesDockWidget;
|
||||
}
|
||||
|
||||
class QTreeWidgetItem;
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
class PDFDiffResult;
|
||||
class PDFDiffResultNavigator;
|
||||
}
|
||||
|
||||
namespace pdfdiff
|
||||
{
|
||||
|
||||
class DifferenceItemDelegate : public QItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
using BaseClass = QItemDelegate;
|
||||
|
||||
public:
|
||||
DifferenceItemDelegate(QObject* parent);
|
||||
|
||||
virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
};
|
||||
|
||||
class DifferencesDockWidget : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DifferencesDockWidget(QWidget* parent,
|
||||
pdf::PDFDiffResult* unfilteredDiffResult,
|
||||
pdf::PDFDiffResult* diffResult,
|
||||
pdf::PDFDiffResultNavigator* diffNavigator,
|
||||
Settings* settings);
|
||||
virtual ~DifferencesDockWidget() override;
|
||||
|
||||
void update();
|
||||
|
||||
private slots:
|
||||
void onSelectionChanged(size_t currentIndex);
|
||||
void onCurrentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous);
|
||||
|
||||
private:
|
||||
Ui::DifferencesDockWidget* ui;
|
||||
|
||||
QColor getColorForIndex(size_t index) const;
|
||||
QModelIndex findResultIndex(size_t index) const;
|
||||
|
||||
pdf::PDFDiffResult* m_unfilteredDiffResult;
|
||||
pdf::PDFDiffResult* m_diffResult;
|
||||
pdf::PDFDiffResultNavigator* m_diffNavigator;
|
||||
Settings* m_settings;
|
||||
bool m_disableChangeSelectedResultIndex;
|
||||
};
|
||||
|
||||
} // namespace pdfdiff
|
||||
|
||||
#endif // PDFDIFF_DIFFERENCESDOCKWIDGET_H
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "pdfconstants.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCommandLineParser>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents, true);
|
||||
QApplication application(argc, argv);
|
||||
|
||||
QCoreApplication::setOrganizationName("MelkaJ");
|
||||
QCoreApplication::setApplicationName("PDF4QT Diff");
|
||||
QCoreApplication::setApplicationVersion(pdf::PDF_LIBRARY_VERSION);
|
||||
QApplication::setApplicationDisplayName(QApplication::translate("Application", "PDF4QT Diff"));
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(QCoreApplication::applicationName());
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
parser.addPositionalArgument("file1", "The PDF file to be compared.");
|
||||
parser.addPositionalArgument("file2", "The PDF file to be compared.");
|
||||
parser.process(application);
|
||||
|
||||
QIcon appIcon(":/app-icon.svg");
|
||||
QApplication::setWindowIcon(appIcon);
|
||||
|
||||
pdfdiff::MainWindow mainWindow(nullptr);
|
||||
mainWindow.show();
|
||||
|
||||
return application.exec();
|
||||
}
|
|
@ -0,0 +1,899 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include "aboutdialog.h"
|
||||
#include "differencesdockwidget.h"
|
||||
#include "settingsdockwidget.h"
|
||||
|
||||
#include "pdfwidgetutils.h"
|
||||
#include "pdfdocumentreader.h"
|
||||
#include "pdfdrawspacecontroller.h"
|
||||
#include "pdfdocumentmanipulator.h"
|
||||
#include "pdfdocumentbuilder.h"
|
||||
#include "pdfdocumentwriter.h"
|
||||
#include "pdfwidgetutils.h"
|
||||
|
||||
#include <QToolBar>
|
||||
#include <QDesktopServices>
|
||||
#include <QMessageBox>
|
||||
#include <QInputDialog>
|
||||
#include <QFileDialog>
|
||||
#include <QVBoxLayout>
|
||||
#include <QActionGroup>
|
||||
#include <QScreen>
|
||||
#include <QSettings>
|
||||
|
||||
namespace pdfdiff
|
||||
{
|
||||
|
||||
MainWindow::MainWindow(QWidget* parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow),
|
||||
m_progress(new pdf::PDFProgress(this)),
|
||||
#ifdef WIN_TASKBAR_BUTTON
|
||||
m_taskbarButton(new QWinTaskbarButton(this)),
|
||||
m_progressTaskbarIndicator(nullptr),
|
||||
#endif
|
||||
m_cmsManager(nullptr),
|
||||
m_pdfWidget(nullptr),
|
||||
m_settingsDockWidget(nullptr),
|
||||
m_differencesDockWidget(nullptr),
|
||||
m_optionalContentActivity(nullptr),
|
||||
m_diff(nullptr),
|
||||
m_isChangingProgressStep(false),
|
||||
m_dontDisplayErrorMessage(false),
|
||||
m_diffNavigator(nullptr),
|
||||
m_drawInterface(&m_settings, &m_documentMapper, &m_filteredDiffResult)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
setMinimumSize(pdf::PDFWidgetUtils::scaleDPI(this, QSize(800, 600)));
|
||||
|
||||
// Initialize task bar progress
|
||||
#ifdef WIN_TASKBAR_BUTTON
|
||||
m_progressTaskbarIndicator = m_taskbarButton->progress();
|
||||
#endif
|
||||
|
||||
m_settingsDockWidget = new SettingsDockWidget(&m_settings, this);
|
||||
addDockWidget(Qt::LeftDockWidgetArea, m_settingsDockWidget);;
|
||||
connect(m_settingsDockWidget, &SettingsDockWidget::colorsChanged, this, &MainWindow::onColorsChanged);
|
||||
connect(m_settingsDockWidget, &SettingsDockWidget::transparencySliderChanged, this, &MainWindow::updateOverlayTransparency);
|
||||
|
||||
m_differencesDockWidget = new DifferencesDockWidget(this, &m_diffResult, &m_filteredDiffResult, &m_diffNavigator, &m_settings);
|
||||
addDockWidget(Qt::LeftDockWidgetArea, m_differencesDockWidget);
|
||||
|
||||
ui->documentFrame->setLayout(new QVBoxLayout);
|
||||
|
||||
m_cmsManager = new pdf::PDFCMSManager(this);
|
||||
m_pdfWidget = new pdf::PDFWidget(m_cmsManager, pdf::RendererEngine::QPainter, ui->documentFrame);
|
||||
m_pdfWidget->getDrawWidgetProxy()->setProgress(m_progress);
|
||||
ui->documentFrame->layout()->addWidget(m_pdfWidget);
|
||||
m_pdfWidget->getDrawWidgetProxy()->registerDrawInterface(&m_drawInterface);
|
||||
|
||||
ui->menuView->addSeparator();
|
||||
ui->menuView->addAction(m_settingsDockWidget->toggleViewAction());
|
||||
ui->menuView->addAction(m_differencesDockWidget->toggleViewAction());
|
||||
|
||||
ui->actionGet_Source->setData(int(Operation::GetSource));
|
||||
ui->actionBecomeASponsor->setData(int(Operation::BecomeSponsor));
|
||||
ui->actionAbout->setData(int(Operation::About));
|
||||
ui->actionOpen_Left->setData(int(Operation::OpenLeft));
|
||||
ui->actionOpen_Right->setData(int(Operation::OpenRight));
|
||||
ui->actionCompare->setData(int(Operation::Compare));
|
||||
ui->actionClose->setData(int(Operation::Close));
|
||||
ui->actionPrevious_Difference->setData(int(Operation::PreviousDifference));
|
||||
ui->actionNext_Difference->setData(int(Operation::NextDifference));
|
||||
ui->actionCreate_Compare_Report->setData(int(Operation::CreateCompareReport));
|
||||
ui->actionFilter_Text->setData(int(Operation::FilterText));
|
||||
ui->actionFilter_Vector_Graphics->setData(int(Operation::FilterVectorGraphics));
|
||||
ui->actionFilter_Images->setData(int(Operation::FilterImages));
|
||||
ui->actionFilter_Shading->setData(int(Operation::FilterShading));
|
||||
ui->actionFilter_Page_Movement->setData(int(Operation::FilterPageMovement));
|
||||
ui->actionView_Differences->setData(int(Operation::ViewDifferences));
|
||||
ui->actionView_Left->setData(int(Operation::ViewLeft));
|
||||
ui->actionView_Right->setData(int(Operation::ViewRight));
|
||||
ui->actionView_Overlay->setData(int(Operation::ViewOverlay));
|
||||
ui->actionShow_Pages_with_Differences->setData(int(Operation::ShowPageswithDifferences));
|
||||
ui->actionSave_Differences_to_XML->setData(int(Operation::SaveDifferencesToXML));
|
||||
ui->actionDisplay_Differences->setData(int(Operation::DisplayDifferences));
|
||||
ui->actionDisplay_Markers->setData(int(Operation::DisplayMarkers));
|
||||
|
||||
ui->actionSynchronize_View_with_Differences->setChecked(true);
|
||||
|
||||
QActionGroup* actionGroup = new QActionGroup(this);
|
||||
actionGroup->setExclusionPolicy(QActionGroup::ExclusionPolicy::Exclusive);
|
||||
actionGroup->addAction(ui->actionView_Differences);
|
||||
actionGroup->addAction(ui->actionView_Left);
|
||||
actionGroup->addAction(ui->actionView_Right);
|
||||
actionGroup->addAction(ui->actionView_Overlay);
|
||||
ui->actionView_Differences->setChecked(true);
|
||||
|
||||
QToolBar* mainToolbar = addToolBar(tr("&Main"));
|
||||
mainToolbar->setObjectName("main_toolbar");
|
||||
mainToolbar->addActions({ ui->actionOpen_Left, ui->actionOpen_Right });
|
||||
mainToolbar->addSeparator();
|
||||
mainToolbar->addAction(ui->actionCompare);
|
||||
mainToolbar->addAction(ui->actionCreate_Compare_Report);
|
||||
mainToolbar->addAction(ui->actionSave_Differences_to_XML);
|
||||
|
||||
QToolBar* differencesToolbar = addToolBar(tr("&Differences"));
|
||||
differencesToolbar->setObjectName("differences_toolbar");
|
||||
differencesToolbar->addActions({ ui->actionPrevious_Difference, ui->actionNext_Difference });
|
||||
|
||||
QToolBar* viewToolbar = addToolBar(tr("&View"));
|
||||
viewToolbar->setObjectName("view_toolbar");
|
||||
viewToolbar->addActions({ ui->actionView_Differences, ui->actionView_Left, ui->actionView_Right, ui->actionView_Overlay });
|
||||
viewToolbar->addSeparator();
|
||||
viewToolbar->addActions({ ui->actionShow_Pages_with_Differences, ui->actionSynchronize_View_with_Differences });
|
||||
viewToolbar->addSeparator();
|
||||
viewToolbar->addActions({ ui->actionFilter_Text, ui->actionFilter_Vector_Graphics, ui->actionFilter_Images, ui->actionFilter_Shading, ui->actionFilter_Page_Movement });
|
||||
|
||||
QSize iconSize = pdf::PDFWidgetUtils::scaleDPI(this, QSize(24, 24));
|
||||
auto toolbars = findChildren<QToolBar*>();
|
||||
for (QToolBar* toolbar : toolbars)
|
||||
{
|
||||
toolbar->setIconSize(iconSize);
|
||||
ui->menuToolbars->addAction(toolbar->toggleViewAction());
|
||||
}
|
||||
|
||||
connect(&m_mapper, &QSignalMapper::mappedInt, this, &MainWindow::onMappedActionTriggered);
|
||||
|
||||
QList<QAction*> actions = findChildren<QAction*>();
|
||||
for (QAction* action : actions)
|
||||
{
|
||||
QVariant actionData = action->data();
|
||||
if (actionData.isValid())
|
||||
{
|
||||
connect(action, &QAction::triggered, &m_mapper, QOverload<>::of(&QSignalMapper::map));
|
||||
m_mapper.setMapping(action, actionData.toInt());
|
||||
}
|
||||
}
|
||||
|
||||
if (pdf::PDFWidgetUtils::isDarkTheme())
|
||||
{
|
||||
pdf::PDFWidgetUtils::convertActionsForDarkTheme(actions, iconSize, qGuiApp->devicePixelRatio());
|
||||
}
|
||||
|
||||
connect(m_progress, &pdf::PDFProgress::progressStarted, this, &MainWindow::onProgressStarted);
|
||||
connect(m_progress, &pdf::PDFProgress::progressStep, this, &MainWindow::onProgressStep);
|
||||
connect(m_progress, &pdf::PDFProgress::progressFinished, this, &MainWindow::onProgressFinished);
|
||||
|
||||
m_diff.setProgress(m_progress);
|
||||
m_diff.setOption(pdf::PDFDiff::Asynchronous, true);
|
||||
connect(&m_diff, &pdf::PDFDiff::comparationFinished, this, &MainWindow::onComparationFinished);
|
||||
|
||||
m_diff.setLeftDocument(&m_leftDocument);
|
||||
m_diff.setRightDocument(&m_rightDocument);
|
||||
|
||||
m_diffNavigator.setResult(&m_filteredDiffResult);
|
||||
connect(&m_diffNavigator, &pdf::PDFDiffResultNavigator::selectionChanged, this, &MainWindow::onSelectionChanged);
|
||||
|
||||
loadSettings();
|
||||
updateAll(false);
|
||||
updateOverlayTransparency();
|
||||
|
||||
#ifndef NDEBUG
|
||||
pdf::PDFWidgetUtils::checkMenuAccessibility(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
saveSettings();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::showEvent(QShowEvent* event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
#ifdef WIN_TASKBAR_BUTTON
|
||||
m_taskbarButton->setWindow(windowHandle());
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
BaseClass::closeEvent(event);
|
||||
m_diff.stop();
|
||||
}
|
||||
|
||||
void MainWindow::onMappedActionTriggered(int actionId)
|
||||
{
|
||||
performOperation(static_cast<Operation>(actionId));
|
||||
}
|
||||
|
||||
void MainWindow::onComparationFinished()
|
||||
{
|
||||
clear(false, false);
|
||||
|
||||
m_diffResult = m_diff.getResult();
|
||||
|
||||
if (!m_dontDisplayErrorMessage)
|
||||
{
|
||||
if (!m_diffResult.getResult())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), m_diffResult.getResult().getErrorMessage());
|
||||
}
|
||||
if (m_diffResult.isSame())
|
||||
{
|
||||
QMessageBox::information(this, tr("Info"), tr("No differences found between the compared documents."), QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
// Create merged document
|
||||
pdf::PDFDocumentManipulator manipulator;
|
||||
manipulator.setOutlineMode(pdf::PDFDocumentManipulator::OutlineMode::NoOutline);
|
||||
manipulator.addDocument(1, &m_leftDocument);
|
||||
manipulator.addDocument(2, &m_rightDocument);
|
||||
|
||||
pdf::PDFDocumentManipulator::AssembledPages assembledPages1 = pdf::PDFDocumentManipulator::createAllDocumentPages(1, &m_leftDocument);
|
||||
pdf::PDFDocumentManipulator::AssembledPages assembledPages2 = pdf::PDFDocumentManipulator::createAllDocumentPages(2, &m_rightDocument);
|
||||
assembledPages1.insert(assembledPages1.end(), std::make_move_iterator(assembledPages2.begin()), std::make_move_iterator(assembledPages2.end()));
|
||||
|
||||
if (manipulator.assemble(assembledPages1))
|
||||
{
|
||||
m_combinedDocument = manipulator.takeAssembledDocument();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_combinedDocument = pdf::PDFDocument();
|
||||
}
|
||||
|
||||
updateAll(true);
|
||||
}
|
||||
|
||||
void MainWindow::onColorsChanged()
|
||||
{
|
||||
updateFilteredResult();
|
||||
m_pdfWidget->update();
|
||||
}
|
||||
|
||||
void MainWindow::updateActions()
|
||||
{
|
||||
QList<QAction*> actions = findChildren<QAction*>();
|
||||
for (QAction* action : actions)
|
||||
{
|
||||
QVariant actionData = action->data();
|
||||
if (actionData.isValid())
|
||||
{
|
||||
bool canPerformAction = canPerformOperation(static_cast<Operation>(actionData.toInt()));
|
||||
action->setEnabled(canPerformAction);
|
||||
|
||||
if (!canPerformAction && action->isCheckable())
|
||||
{
|
||||
action->setChecked(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onSelectionChanged(size_t currentIndex)
|
||||
{
|
||||
if (ui->actionSynchronize_View_with_Differences->isChecked())
|
||||
{
|
||||
pdf::PDFInteger destinationPage = -1;
|
||||
|
||||
if (destinationPage == -1)
|
||||
{
|
||||
pdf::PDFInteger leftPageIndex = m_filteredDiffResult.getLeftPage(currentIndex);
|
||||
if (leftPageIndex != -1)
|
||||
{
|
||||
destinationPage = m_documentMapper.getPageIndexFromLeftPageIndex(leftPageIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if (destinationPage == -1)
|
||||
{
|
||||
pdf::PDFInteger rightPageIndex = m_filteredDiffResult.getRightPage(currentIndex);
|
||||
if (rightPageIndex != -1)
|
||||
{
|
||||
destinationPage = m_documentMapper.getPageIndexFromRightPageIndex(rightPageIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if (destinationPage != -1)
|
||||
{
|
||||
m_pdfWidget->getDrawWidgetProxy()->goToPage(destinationPage);
|
||||
}
|
||||
}
|
||||
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void MainWindow::loadSettings()
|
||||
{
|
||||
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName());
|
||||
settings.beginGroup("MainWindow");
|
||||
QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray();
|
||||
if (geometry.isEmpty())
|
||||
{
|
||||
QRect availableGeometry = QApplication::primaryScreen()->availableGeometry();
|
||||
QRect windowRect(0, 0, availableGeometry.width() / 2, availableGeometry.height() / 2);
|
||||
windowRect = windowRect.translated(availableGeometry.center() - windowRect.center());
|
||||
setGeometry(windowRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
restoreGeometry(geometry);
|
||||
}
|
||||
|
||||
QByteArray state = settings.value("windowState", QByteArray()).toByteArray();
|
||||
if (!state.isEmpty())
|
||||
{
|
||||
restoreState(state);
|
||||
}
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup("Settings");
|
||||
m_settings.directory = settings.value("directory").toString();
|
||||
m_settings.colorPageMove = settings.value("colorPageMove", m_settings.colorPageMove).value<QColor>();
|
||||
m_settings.colorAdded = settings.value("colorAdded", m_settings.colorAdded).value<QColor>();
|
||||
m_settings.colorRemoved = settings.value("colorRemoved", m_settings.colorRemoved).value<QColor>();
|
||||
m_settings.colorReplaced = settings.value("colorReplaced", m_settings.colorReplaced).value<QColor>();
|
||||
m_settings.displayDifferences = settings.value("displayDifferences", m_settings.displayDifferences).toBool();
|
||||
m_settings.displayMarkers = settings.value("displayMarkers", m_settings.displayDifferences).toBool();
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup("Compare");
|
||||
m_settingsDockWidget->setCompareTextsAsVectorGraphics(settings.value("compareTextsAsVectorGraphics", false).toBool());
|
||||
m_settingsDockWidget->setCompareTextCharactersInsteadOfWords(settings.value("compareTextCharactersInsteadOfWords", false).toBool());
|
||||
settings.endGroup();
|
||||
|
||||
ui->actionDisplay_Differences->setChecked(m_settings.displayDifferences);
|
||||
ui->actionDisplay_Markers->setChecked(m_settings.displayMarkers);
|
||||
|
||||
m_settingsDockWidget->loadColors();
|
||||
}
|
||||
|
||||
void MainWindow::saveSettings()
|
||||
{
|
||||
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName());
|
||||
settings.beginGroup("MainWindow");
|
||||
settings.setValue("geometry", saveGeometry());
|
||||
settings.setValue("windowState", saveState());
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup("Settings");
|
||||
settings.setValue("directory", m_settings.directory);
|
||||
settings.setValue("colorPageMove", m_settings.colorPageMove);
|
||||
settings.setValue("colorAdded", m_settings.colorAdded);
|
||||
settings.setValue("colorRemoved", m_settings.colorRemoved);
|
||||
settings.setValue("colorReplaced", m_settings.colorReplaced);
|
||||
settings.setValue("displayDifferences", m_settings.displayDifferences);
|
||||
settings.setValue("displayMarkers", m_settings.displayMarkers);
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup("Compare");
|
||||
settings.setValue("compareTextsAsVectorGraphics", m_settingsDockWidget->isCompareTextAsVectorGraphics());
|
||||
settings.setValue("compareTextCharactersInsteadOfWords", m_settingsDockWidget->isCompareTextCharactersInsteadOfWords());
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
bool MainWindow::canPerformOperation(Operation operation) const
|
||||
{
|
||||
switch (operation)
|
||||
{
|
||||
case Operation::OpenLeft:
|
||||
case Operation::OpenRight:
|
||||
case Operation::Compare:
|
||||
case Operation::Close:
|
||||
case Operation::GetSource:
|
||||
case Operation::BecomeSponsor:
|
||||
case Operation::About:
|
||||
return true;
|
||||
|
||||
case Operation::ViewDifferences:
|
||||
case Operation::ViewLeft:
|
||||
case Operation::ViewRight:
|
||||
case Operation::ViewOverlay:
|
||||
return true; // Allow always to change a view
|
||||
|
||||
case Operation::FilterText:
|
||||
return m_diffResult.hasTextDifferences();
|
||||
|
||||
case Operation::FilterVectorGraphics:
|
||||
return m_diffResult.hasVectorGraphicsDifferences();
|
||||
|
||||
case Operation::FilterImages:
|
||||
return m_diffResult.hasImageDifferences();
|
||||
|
||||
case Operation::FilterShading:
|
||||
return m_diffResult.hasShadingDifferences();
|
||||
|
||||
case Operation::FilterPageMovement:
|
||||
return m_diffResult.hasPageMoveDifferences();
|
||||
|
||||
case Operation::PreviousDifference:
|
||||
return m_diffNavigator.canGoPrevious();
|
||||
|
||||
case Operation::NextDifference:
|
||||
return m_diffNavigator.canGoNext();
|
||||
|
||||
case Operation::CreateCompareReport:
|
||||
case Operation::SaveDifferencesToXML:
|
||||
return m_filteredDiffResult.isChanged();
|
||||
|
||||
case Operation::ShowPageswithDifferences:
|
||||
return m_diffResult.isChanged();
|
||||
|
||||
case Operation::DisplayDifferences:
|
||||
case Operation::DisplayMarkers:
|
||||
return true;
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MainWindow::performOperation(Operation operation)
|
||||
{
|
||||
switch (operation)
|
||||
{
|
||||
case Operation::OpenLeft:
|
||||
{
|
||||
pdf::PDFTemporaryValueChange guard(&m_dontDisplayErrorMessage, true);
|
||||
m_diff.stop();
|
||||
|
||||
std::optional<pdf::PDFDocument> document = openDocument();
|
||||
if (document)
|
||||
{
|
||||
clear(true, false);
|
||||
m_leftDocument = std::move(*document);
|
||||
|
||||
const size_t pageCount = m_leftDocument.getCatalog()->getPageCount();
|
||||
if (pageCount > 1)
|
||||
{
|
||||
m_settingsDockWidget->getLeftPageSelectionEdit()->setText(QString("1-%2").arg(pageCount));
|
||||
}
|
||||
else if (pageCount == 1)
|
||||
{
|
||||
m_settingsDockWidget->getLeftPageSelectionEdit()->setText("1");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settingsDockWidget->getLeftPageSelectionEdit()->clear();
|
||||
}
|
||||
|
||||
updateViewDocument();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::OpenRight:
|
||||
{
|
||||
pdf::PDFTemporaryValueChange guard(&m_dontDisplayErrorMessage, true);
|
||||
m_diff.stop();
|
||||
|
||||
std::optional<pdf::PDFDocument> document = openDocument();
|
||||
if (document)
|
||||
{
|
||||
clear(false, true);
|
||||
m_rightDocument = std::move(*document);
|
||||
|
||||
const size_t pageCount = m_rightDocument.getCatalog()->getPageCount();
|
||||
if (pageCount > 1)
|
||||
{
|
||||
m_settingsDockWidget->getRightPageSelectionEdit()->setText(QString("1-%2").arg(pageCount));
|
||||
}
|
||||
else if (pageCount == 1)
|
||||
{
|
||||
m_settingsDockWidget->getRightPageSelectionEdit()->setText("1");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settingsDockWidget->getRightPageSelectionEdit()->clear();
|
||||
}
|
||||
|
||||
updateViewDocument();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::Compare:
|
||||
{
|
||||
pdf::PDFTemporaryValueChange guard(&m_dontDisplayErrorMessage, true);
|
||||
m_diff.stop();
|
||||
|
||||
m_diff.setOption(pdf::PDFDiff::CompareTextsAsVector, m_settingsDockWidget->isCompareTextAsVectorGraphics());
|
||||
m_diff.setOption(pdf::PDFDiff::CompareWords, !m_settingsDockWidget->isCompareTextCharactersInsteadOfWords());
|
||||
|
||||
QString errorMessage;
|
||||
|
||||
pdf::PDFClosedIntervalSet rightPageIndices;
|
||||
pdf::PDFClosedIntervalSet leftPageIndices = pdf::PDFClosedIntervalSet::parse(1, qMax<pdf::PDFInteger>(1, m_leftDocument.getCatalog()->getPageCount()), m_settingsDockWidget->getLeftPageSelectionEdit()->text(), &errorMessage);
|
||||
|
||||
if (errorMessage.isEmpty())
|
||||
{
|
||||
rightPageIndices = pdf::PDFClosedIntervalSet::parse(1, qMax<pdf::PDFInteger>(1, m_rightDocument.getCatalog()->getPageCount()), m_settingsDockWidget->getRightPageSelectionEdit()->text(), &errorMessage);
|
||||
}
|
||||
|
||||
// Check if pages are succesfully parsed
|
||||
if (!errorMessage.isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), errorMessage);
|
||||
break;
|
||||
}
|
||||
|
||||
leftPageIndices.translate(-1);
|
||||
rightPageIndices.translate(-1);
|
||||
|
||||
m_diff.setPagesForLeftDocument(std::move(leftPageIndices));
|
||||
m_diff.setPagesForRightDocument(std::move(rightPageIndices));
|
||||
|
||||
m_diff.start();
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::Close:
|
||||
{
|
||||
close();
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::GetSource:
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl("https://github.com/JakubMelka/PDF4QT"));
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::BecomeSponsor:
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl("https://github.com/sponsors/JakubMelka"));
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::About:
|
||||
{
|
||||
PDFAboutDialog aboutDialog(this);
|
||||
aboutDialog.exec();
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::PreviousDifference:
|
||||
m_diffNavigator.goPrevious();
|
||||
break;
|
||||
|
||||
case Operation::NextDifference:
|
||||
m_diffNavigator.goNext();
|
||||
break;
|
||||
|
||||
case Operation::FilterText:
|
||||
case Operation::FilterVectorGraphics:
|
||||
case Operation::FilterImages:
|
||||
case Operation::FilterShading:
|
||||
case Operation::FilterPageMovement:
|
||||
{
|
||||
updateFilteredResult();
|
||||
|
||||
if (ui->actionShow_Pages_with_Differences->isChecked())
|
||||
{
|
||||
updateCustomPageLayout();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::ViewDifferences:
|
||||
case Operation::ViewLeft:
|
||||
case Operation::ViewRight:
|
||||
case Operation::ViewOverlay:
|
||||
updateViewDocument();
|
||||
break;
|
||||
|
||||
case Operation::ShowPageswithDifferences:
|
||||
updateCustomPageLayout();
|
||||
break;
|
||||
|
||||
case Operation::DisplayDifferences:
|
||||
m_settings.displayDifferences = ui->actionDisplay_Differences->isChecked();
|
||||
m_pdfWidget->update();
|
||||
break;
|
||||
|
||||
case Operation::DisplayMarkers:
|
||||
m_settings.displayMarkers = ui->actionDisplay_Markers->isChecked();
|
||||
m_pdfWidget->update();
|
||||
break;
|
||||
|
||||
case Operation::SaveDifferencesToXML:
|
||||
{
|
||||
if (!m_filteredDiffResult.isSame())
|
||||
{
|
||||
QString fileName = QFileDialog::getSaveFileName(this, tr("Select PDF document"), m_settings.directory, tr("XML file (*.xml)"));
|
||||
if (!fileName.isEmpty())
|
||||
{
|
||||
QFile file(fileName);
|
||||
if (file.open(QFile::WriteOnly | QFile::Truncate))
|
||||
{
|
||||
m_filteredDiffResult.saveToXML(&file);
|
||||
file.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("File '%1' cannot be opened. %2").arg(fileName, file.errorString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::information(this, tr("Save results to XML"), tr("Displayed results are empty. Cannot save empty results."));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::CreateCompareReport:
|
||||
{
|
||||
if (m_filteredDiffResult.isSame())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
QString saveFileName = QFileDialog::getSaveFileName(this, tr("Save As"), m_settings.directory, tr("Portable Document (*.pdf);;All files (*.*)"));
|
||||
if (!saveFileName.isEmpty())
|
||||
{
|
||||
pdf::PDFDocumentBuilder builder(m_pdfWidget->getDrawWidgetProxy()->getDocument());
|
||||
m_drawInterface.drawAnnotations(m_pdfWidget->getDrawWidgetProxy()->getDocument(), &builder);
|
||||
|
||||
pdf::PDFDocument document = builder.build();
|
||||
pdf::PDFDocumentWriter writer(m_progress);
|
||||
pdf::PDFOperationResult result = writer.write(saveFileName, &document, QFile::exists(saveFileName));
|
||||
if (!result)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), result.getErrorMessage());
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void MainWindow::setViewDocument(pdf::PDFDocument* document, bool updateCustomPageLayout)
|
||||
{
|
||||
if (document != m_pdfWidget->getDrawWidgetProxy()->getDocument())
|
||||
{
|
||||
m_optionalContentActivity->deleteLater();
|
||||
m_optionalContentActivity = nullptr;
|
||||
|
||||
if (document)
|
||||
{
|
||||
m_optionalContentActivity = new pdf::PDFOptionalContentActivity(document, pdf::OCUsage::View, this);
|
||||
}
|
||||
|
||||
if (document)
|
||||
{
|
||||
pdf::PDFModifiedDocument modifiedDocument(document, m_optionalContentActivity);
|
||||
m_pdfWidget->setDocument(modifiedDocument);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pdfWidget->setDocument(pdf::PDFModifiedDocument());
|
||||
}
|
||||
}
|
||||
|
||||
if (updateCustomPageLayout)
|
||||
{
|
||||
this->updateCustomPageLayout();
|
||||
}
|
||||
}
|
||||
|
||||
ComparedDocumentMapper::Mode MainWindow::getDocumentViewMode() const
|
||||
{
|
||||
if (ui->actionView_Left->isChecked())
|
||||
{
|
||||
return ComparedDocumentMapper::Mode::Left;
|
||||
}
|
||||
|
||||
if (ui->actionView_Right->isChecked())
|
||||
{
|
||||
return ComparedDocumentMapper::Mode::Right;
|
||||
}
|
||||
|
||||
if (ui->actionView_Overlay->isChecked())
|
||||
{
|
||||
return ComparedDocumentMapper::Mode::Overlay;
|
||||
}
|
||||
|
||||
return ComparedDocumentMapper::Mode::Combined;
|
||||
}
|
||||
|
||||
void MainWindow::clear(bool clearLeftDocument, bool clearRightDocument)
|
||||
{
|
||||
setViewDocument(nullptr, true);
|
||||
|
||||
if (clearLeftDocument)
|
||||
{
|
||||
m_leftDocument = pdf::PDFDocument();
|
||||
m_settingsDockWidget->getLeftPageSelectionEdit()->clear();
|
||||
}
|
||||
|
||||
if (clearRightDocument)
|
||||
{
|
||||
m_rightDocument = pdf::PDFDocument();
|
||||
m_settingsDockWidget->getRightPageSelectionEdit()->clear();
|
||||
}
|
||||
|
||||
m_diffResult = pdf::PDFDiffResult();
|
||||
m_filteredDiffResult = pdf::PDFDiffResult();
|
||||
m_diffNavigator.update();
|
||||
|
||||
updateAll(false);
|
||||
}
|
||||
|
||||
void MainWindow::updateAll(bool resetFilters)
|
||||
{
|
||||
if (resetFilters)
|
||||
{
|
||||
ui->actionFilter_Page_Movement->setChecked(m_diffResult.hasPageMoveDifferences());
|
||||
ui->actionFilter_Text->setChecked(m_diffResult.hasTextDifferences());
|
||||
ui->actionFilter_Vector_Graphics->setChecked(m_diffResult.hasVectorGraphicsDifferences());
|
||||
ui->actionFilter_Images->setChecked(m_diffResult.hasImageDifferences());
|
||||
ui->actionFilter_Shading->setChecked(m_diffResult.hasShadingDifferences());
|
||||
}
|
||||
|
||||
updateFilteredResult();
|
||||
updateViewDocument();
|
||||
}
|
||||
|
||||
void MainWindow::updateFilteredResult()
|
||||
{
|
||||
m_filteredDiffResult = m_diffResult.filter(ui->actionFilter_Page_Movement->isChecked(),
|
||||
ui->actionFilter_Text->isChecked(),
|
||||
ui->actionFilter_Vector_Graphics->isChecked(),
|
||||
ui->actionFilter_Images->isChecked(),
|
||||
ui->actionFilter_Shading->isChecked());
|
||||
m_diffNavigator.update();
|
||||
|
||||
if (m_differencesDockWidget)
|
||||
{
|
||||
m_differencesDockWidget->update();
|
||||
}
|
||||
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void MainWindow::updateViewDocument()
|
||||
{
|
||||
pdf::PDFDocument* document = nullptr;
|
||||
|
||||
switch (getDocumentViewMode())
|
||||
{
|
||||
case ComparedDocumentMapper::Mode::Left:
|
||||
document = &m_leftDocument;
|
||||
break;
|
||||
|
||||
case ComparedDocumentMapper::Mode::Right:
|
||||
document = &m_rightDocument;
|
||||
break;
|
||||
|
||||
case ComparedDocumentMapper::Mode::Combined:
|
||||
case ComparedDocumentMapper::Mode::Overlay:
|
||||
document = &m_combinedDocument;
|
||||
break;
|
||||
}
|
||||
|
||||
setViewDocument(document, true);
|
||||
}
|
||||
|
||||
void MainWindow::updateCustomPageLayout()
|
||||
{
|
||||
m_documentMapper.update(getDocumentViewMode(),
|
||||
ui->actionShow_Pages_with_Differences->isChecked(),
|
||||
m_filteredDiffResult,
|
||||
&m_leftDocument,
|
||||
&m_rightDocument,
|
||||
m_pdfWidget->getDrawWidgetProxy()->getDocument());
|
||||
|
||||
|
||||
m_pdfWidget->getDrawWidgetProxy()->setCustomPageLayout(m_documentMapper.getLayout());
|
||||
m_pdfWidget->getDrawWidgetProxy()->setPageLayout(pdf::PageLayout::Custom);
|
||||
}
|
||||
|
||||
void MainWindow::updateOverlayTransparency()
|
||||
{
|
||||
const pdf::PDFReal value = m_settingsDockWidget->getTransparencySliderValue() * 0.01;
|
||||
m_pdfWidget->getDrawWidgetProxy()->setGroupTransparency(1, true, 1.0 - value);
|
||||
m_pdfWidget->getDrawWidgetProxy()->setGroupTransparency(2, false, value);
|
||||
m_pdfWidget->update();
|
||||
}
|
||||
|
||||
std::optional<pdf::PDFDocument> MainWindow::openDocument()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Select PDF document"), m_settings.directory, tr("PDF document (*.pdf)"));
|
||||
if (fileName.isEmpty())
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto queryPassword = [this](bool* ok)
|
||||
{
|
||||
*ok = false;
|
||||
return QInputDialog::getText(this, tr("Encrypted document"), tr("Enter password to access document content"), QLineEdit::Password, QString(), ok);
|
||||
};
|
||||
|
||||
// Mark current directory as this
|
||||
QFileInfo fileInfo(fileName);
|
||||
m_settings.directory = fileInfo.dir().absolutePath();
|
||||
|
||||
// Try to open a new document
|
||||
pdf::PDFDocumentReader reader(nullptr, qMove(queryPassword), true, false);
|
||||
pdf::PDFDocument document = reader.readFromFile(fileName);
|
||||
|
||||
QString errorMessage = reader.getErrorMessage();
|
||||
pdf::PDFDocumentReader::Result result = reader.getReadingResult();
|
||||
if (result == pdf::PDFDocumentReader::Result::OK)
|
||||
{
|
||||
return document;
|
||||
}
|
||||
else if (result == pdf::PDFDocumentReader::Result::Failed)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), errorMessage);
|
||||
}
|
||||
|
||||
return pdf::PDFDocument();
|
||||
}
|
||||
|
||||
void MainWindow::onProgressStarted(pdf::ProgressStartupInfo info)
|
||||
{
|
||||
#ifdef WIN_TASKBAR_BUTTON
|
||||
m_progressTaskbarIndicator->setRange(0, 100);
|
||||
m_progressTaskbarIndicator->reset();
|
||||
m_progressTaskbarIndicator->show();
|
||||
#else
|
||||
Q_UNUSED(info);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::onProgressStep(int percentage)
|
||||
{
|
||||
if (m_isChangingProgressStep)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pdf::PDFTemporaryValueChange guard(&m_isChangingProgressStep, true);
|
||||
#ifdef WIN_TASKBAR_BUTTON
|
||||
m_progressTaskbarIndicator->setValue(percentage);
|
||||
#else
|
||||
Q_UNUSED(percentage);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::onProgressFinished()
|
||||
{
|
||||
#ifdef WIN_TASKBAR_BUTTON
|
||||
m_progressTaskbarIndicator->hide();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace pdfdiff
|
|
@ -0,0 +1,156 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFDIFF_MAINWINDOW_H
|
||||
#define PDFDIFF_MAINWINDOW_H
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include "pdfdocument.h"
|
||||
#include "pdfdrawwidget.h"
|
||||
#include "pdfcms.h"
|
||||
#include "pdfoptionalcontent.h"
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QSignalMapper>
|
||||
#ifdef WIN_TASKBAR_BUTTON
|
||||
#include <QWinTaskbarButton>
|
||||
#include <QWinTaskbarProgress>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
namespace pdfdiff
|
||||
{
|
||||
|
||||
class SettingsDockWidget;
|
||||
class DifferencesDockWidget;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
using BaseClass = QMainWindow;
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget* parent);
|
||||
virtual ~MainWindow() override;
|
||||
|
||||
enum class Operation
|
||||
{
|
||||
OpenLeft,
|
||||
OpenRight,
|
||||
Compare,
|
||||
Close,
|
||||
GetSource,
|
||||
BecomeSponsor,
|
||||
About,
|
||||
PreviousDifference,
|
||||
NextDifference,
|
||||
CreateCompareReport,
|
||||
FilterText,
|
||||
FilterVectorGraphics,
|
||||
FilterImages,
|
||||
FilterShading,
|
||||
FilterPageMovement,
|
||||
ViewDifferences,
|
||||
ViewLeft,
|
||||
ViewRight,
|
||||
ViewOverlay,
|
||||
ShowPageswithDifferences,
|
||||
SaveDifferencesToXML,
|
||||
DisplayDifferences,
|
||||
DisplayMarkers
|
||||
};
|
||||
|
||||
virtual void showEvent(QShowEvent* event) override;
|
||||
virtual void closeEvent(QCloseEvent* event) override;
|
||||
|
||||
private slots:
|
||||
void updateActions();
|
||||
void onSelectionChanged(size_t currentIndex);
|
||||
|
||||
private:
|
||||
void onMappedActionTriggered(int actionId);
|
||||
void onComparationFinished();
|
||||
void onColorsChanged();
|
||||
|
||||
void onProgressStarted(pdf::ProgressStartupInfo info);
|
||||
void onProgressStep(int percentage);
|
||||
void onProgressFinished();
|
||||
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
|
||||
bool canPerformOperation(Operation operation) const;
|
||||
void performOperation(Operation operation);
|
||||
|
||||
void setViewDocument(pdf::PDFDocument* document, bool updateCustomPageLayout);
|
||||
|
||||
ComparedDocumentMapper::Mode getDocumentViewMode() const;
|
||||
|
||||
/// Clears all data, and possibly documents also.
|
||||
/// View document is set to nullptr.
|
||||
/// \param clearLeftDocument Clear left document?
|
||||
/// \param clearRightDocument Clear left document?
|
||||
void clear(bool clearLeftDocument, bool clearRightDocument);
|
||||
|
||||
void updateAll(bool resetFilters);
|
||||
void updateFilteredResult();
|
||||
void updateViewDocument();
|
||||
void updateCustomPageLayout();
|
||||
void updateOverlayTransparency();
|
||||
|
||||
std::optional<pdf::PDFDocument> openDocument();
|
||||
|
||||
Ui::MainWindow* ui;
|
||||
|
||||
pdf::PDFProgress* m_progress;
|
||||
#ifdef WIN_TASKBAR_BUTTON
|
||||
QWinTaskbarButton* m_taskbarButton;
|
||||
QWinTaskbarProgress* m_progressTaskbarIndicator;
|
||||
#endif
|
||||
pdf::PDFCMSManager* m_cmsManager;
|
||||
pdf::PDFWidget* m_pdfWidget;
|
||||
SettingsDockWidget* m_settingsDockWidget;
|
||||
DifferencesDockWidget* m_differencesDockWidget;
|
||||
pdf::PDFOptionalContentActivity* m_optionalContentActivity;
|
||||
|
||||
Settings m_settings;
|
||||
QSignalMapper m_mapper;
|
||||
pdf::PDFDiff m_diff;
|
||||
bool m_isChangingProgressStep;
|
||||
bool m_dontDisplayErrorMessage;
|
||||
|
||||
pdf::PDFDocument m_leftDocument;
|
||||
pdf::PDFDocument m_rightDocument;
|
||||
pdf::PDFDocument m_combinedDocument;
|
||||
|
||||
pdf::PDFDiffResult m_diffResult;
|
||||
pdf::PDFDiffResult m_filteredDiffResult; ///< Difference result with filters applied
|
||||
pdf::PDFDiffResultNavigator m_diffNavigator; ///< Difference navigator
|
||||
ComparedDocumentMapper m_documentMapper;
|
||||
DifferencesDrawInterface m_drawInterface;
|
||||
};
|
||||
|
||||
} // namespace pdfdiff
|
||||
|
||||
#endif // PDFDIFF_MAINWINDOW_H
|
|
@ -0,0 +1,380 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>864</width>
|
||||
<height>638</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Workspace</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout" rowstretch="0">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QFrame" name="documentFrame"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>864</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>&File</string>
|
||||
</property>
|
||||
<addaction name="actionOpen_Left"/>
|
||||
<addaction name="actionOpen_Right"/>
|
||||
<addaction name="actionClose"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuHelp">
|
||||
<property name="title">
|
||||
<string>&Help</string>
|
||||
</property>
|
||||
<addaction name="actionGet_Source"/>
|
||||
<addaction name="actionBecomeASponsor"/>
|
||||
<addaction name="actionAbout"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuToolbars">
|
||||
<property name="title">
|
||||
<string>&Toolbars</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuCompare">
|
||||
<property name="title">
|
||||
<string>&Compare</string>
|
||||
</property>
|
||||
<addaction name="actionCompare"/>
|
||||
<addaction name="actionCreate_Compare_Report"/>
|
||||
<addaction name="actionSave_Differences_to_XML"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuView">
|
||||
<property name="title">
|
||||
<string>&View</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuView_2">
|
||||
<property name="title">
|
||||
<string>&View</string>
|
||||
</property>
|
||||
<addaction name="actionView_Differences"/>
|
||||
<addaction name="actionView_Left"/>
|
||||
<addaction name="actionView_Right"/>
|
||||
<addaction name="actionView_Overlay"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuFilter">
|
||||
<property name="title">
|
||||
<string>&Filter</string>
|
||||
</property>
|
||||
<addaction name="actionFilter_Text"/>
|
||||
<addaction name="actionFilter_Vector_Graphics"/>
|
||||
<addaction name="actionFilter_Images"/>
|
||||
<addaction name="actionFilter_Shading"/>
|
||||
<addaction name="actionFilter_Page_Movement"/>
|
||||
</widget>
|
||||
<addaction name="actionPrevious_Difference"/>
|
||||
<addaction name="actionNext_Difference"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="menuView_2"/>
|
||||
<addaction name="menuFilter"/>
|
||||
<addaction name="actionShow_Pages_with_Differences"/>
|
||||
<addaction name="actionSynchronize_View_with_Differences"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionDisplay_Differences"/>
|
||||
<addaction name="actionDisplay_Markers"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuCompare"/>
|
||||
<addaction name="menuToolbars"/>
|
||||
<addaction name="menuHelp"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<action name="actionGet_Source">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/get-source.svg</normaloff>:/pdfdiff/resources/get-source.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Get Source</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAbout">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/about.svg</normaloff>:/pdfdiff/resources/about.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&About...</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F1</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpen_Left">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/open-left.svg</normaloff>:/pdfdiff/resources/open-left.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open &Left...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpen_Right">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/open-right.svg</normaloff>:/pdfdiff/resources/open-right.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open &Right...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCompare">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/compare.svg</normaloff>:/pdfdiff/resources/compare.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Compare</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F5</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionClose">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/close.svg</normaloff>:/pdfdiff/resources/close.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Close</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+F4</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPrevious_Difference">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/prev-diff.svg</normaloff>:/pdfdiff/resources/prev-diff.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Previous Difference</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Shift+F6</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNext_Difference">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/next-diff.svg</normaloff>:/pdfdiff/resources/next-diff.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Next Difference</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F6</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCreate_Compare_Report">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/create-compare-report.svg</normaloff>:/pdfdiff/resources/create-compare-report.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Create Compare &Report...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFilter_Text">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/filter-text.svg</normaloff>:/pdfdiff/resources/filter-text.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Filter &Text</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFilter_Vector_Graphics">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/filter-vector-graphics.svg</normaloff>:/pdfdiff/resources/filter-vector-graphics.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Filter &Vector Graphics</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFilter_Images">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/filter-images.svg</normaloff>:/pdfdiff/resources/filter-images.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Filter &Images</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFilter_Shading">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/filter-shading.svg</normaloff>:/pdfdiff/resources/filter-shading.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Filter &Shading</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFilter_Page_Movement">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/filter-page-movement.svg</normaloff>:/pdfdiff/resources/filter-page-movement.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Filter &Page Movement</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionView_Differences">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/view-differences.svg</normaloff>:/pdfdiff/resources/view-differences.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>View &Differences</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionView_Left">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/view-left.svg</normaloff>:/pdfdiff/resources/view-left.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>View &Left</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionView_Right">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/view-right.svg</normaloff>:/pdfdiff/resources/view-right.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>View &Right</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionView_Overlay">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/view-overlay.svg</normaloff>:/pdfdiff/resources/view-overlay.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>View &Overlay</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShow_Pages_with_Differences">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/show-p-with-diff.svg</normaloff>:/pdfdiff/resources/show-p-with-diff.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Show Pages with Differences</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show Pages with Differences</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave_Differences_to_XML">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/save-diff-to-xml.svg</normaloff>:/pdfdiff/resources/save-diff-to-xml.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save Differences to &XML...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSynchronize_View_with_Differences">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/synchronize-view.svg</normaloff>:/pdfdiff/resources/synchronize-view.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>S&ynchronize View with Differences</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDisplay_Differences">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/display-differences.svg</normaloff>:/pdfdiff/resources/display-differences.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Display &Differences</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDisplay_Markers">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/display-markers.svg</normaloff>:/pdfdiff/resources/display-markers.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Display &Markers</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionBecomeASponsor">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdiff/resources/wallet.svg</normaloff>:/pdfdiff/resources/wallet.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Become a &Sponsor</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -0,0 +1,28 @@
|
|||
<RCC>
|
||||
<qresource prefix="/pdfdiff">
|
||||
<file>resources/about.svg</file>
|
||||
<file>resources/close.svg</file>
|
||||
<file>resources/compare.svg</file>
|
||||
<file>resources/get-source.svg</file>
|
||||
<file>resources/open-left.svg</file>
|
||||
<file>resources/open-right.svg</file>
|
||||
<file>resources/create-compare-report.svg</file>
|
||||
<file>resources/filter-images.svg</file>
|
||||
<file>resources/filter-page-movement.svg</file>
|
||||
<file>resources/filter-shading.svg</file>
|
||||
<file>resources/filter-text.svg</file>
|
||||
<file>resources/filter-vector-graphics.svg</file>
|
||||
<file>resources/next-diff.svg</file>
|
||||
<file>resources/prev-diff.svg</file>
|
||||
<file>resources/save-diff-to-xml.svg</file>
|
||||
<file>resources/show-p-with-diff.svg</file>
|
||||
<file>resources/synchronize-view.svg</file>
|
||||
<file>resources/view-differences.svg</file>
|
||||
<file>resources/view-left.svg</file>
|
||||
<file>resources/view-overlay.svg</file>
|
||||
<file>resources/view-right.svg</file>
|
||||
<file>resources/display-differences.svg</file>
|
||||
<file>resources/display-markers.svg</file>
|
||||
<file>resources/wallet.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 1022 B After Width: | Height: | Size: 1022 B |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
After Width: | Height: | Size: 7.4 KiB |
|
@ -0,0 +1,39 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFDIFF_SETTINGS_H
|
||||
#define PDFDIFF_SETTINGS_H
|
||||
|
||||
#include <QColor>
|
||||
|
||||
namespace pdfdiff
|
||||
{
|
||||
|
||||
struct Settings
|
||||
{
|
||||
QString directory;
|
||||
QColor colorPageMove = QColor(35, 145, 255);
|
||||
QColor colorAdded = QColor(125, 250, 0);
|
||||
QColor colorRemoved = QColor(255, 50, 50);
|
||||
QColor colorReplaced = QColor(255, 120, 30);
|
||||
bool displayDifferences = true;
|
||||
bool displayMarkers = true;
|
||||
};
|
||||
|
||||
} // namespace pdfdiff
|
||||
|
||||
#endif // PDFDIFF_SETTINGS_H
|
|
@ -0,0 +1,152 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "settingsdockwidget.h"
|
||||
#include "ui_settingsdockwidget.h"
|
||||
|
||||
#include "pdfutils.h"
|
||||
#include "pdfwidgetutils.h"
|
||||
|
||||
namespace pdfdiff
|
||||
{
|
||||
|
||||
SettingsDockWidget::SettingsDockWidget(Settings* settings, QWidget* parent) :
|
||||
QDockWidget(parent),
|
||||
ui(new Ui::SettingsDockWidget),
|
||||
m_settings(settings),
|
||||
m_loadingColors(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
auto colorNames = QColor::colorNames();
|
||||
for (QComboBox* comboBox : findChildren<QComboBox*>())
|
||||
{
|
||||
for (const QString& colorName : colorNames)
|
||||
{
|
||||
QColor color(colorName);
|
||||
comboBox->addItem(getIconForColor(color), colorName, color);
|
||||
}
|
||||
|
||||
connect(comboBox, &QComboBox::editTextChanged, this, &SettingsDockWidget::onEditColorChanged);
|
||||
}
|
||||
|
||||
connect(ui->transparencySlider, &QSlider::valueChanged, this, &SettingsDockWidget::transparencySliderChanged);
|
||||
|
||||
toggleViewAction()->setText(tr("S&ettings"));
|
||||
}
|
||||
|
||||
SettingsDockWidget::~SettingsDockWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SettingsDockWidget::setCompareTextsAsVectorGraphics(bool enabled)
|
||||
{
|
||||
ui->compareTextsAsVectorGraphicsCheckBox->setChecked(enabled);
|
||||
}
|
||||
|
||||
bool SettingsDockWidget::isCompareTextAsVectorGraphics() const
|
||||
{
|
||||
return ui->compareTextsAsVectorGraphicsCheckBox->isChecked();
|
||||
}
|
||||
|
||||
void SettingsDockWidget::setCompareTextCharactersInsteadOfWords(bool enabled)
|
||||
{
|
||||
ui->compareCharactersInsteadOfWordsCheckBox->setChecked(enabled);
|
||||
}
|
||||
|
||||
bool SettingsDockWidget::isCompareTextCharactersInsteadOfWords() const
|
||||
{
|
||||
return ui->compareCharactersInsteadOfWordsCheckBox->isChecked();
|
||||
}
|
||||
|
||||
QLineEdit* SettingsDockWidget::getLeftPageSelectionEdit() const
|
||||
{
|
||||
return ui->leftPageSelectionEdit;
|
||||
}
|
||||
|
||||
QLineEdit* SettingsDockWidget::getRightPageSelectionEdit() const
|
||||
{
|
||||
return ui->rightPageSelectionEdit;
|
||||
}
|
||||
|
||||
void SettingsDockWidget::loadColors()
|
||||
{
|
||||
pdf::PDFTemporaryValueChange guard(&m_loadingColors, true);
|
||||
|
||||
auto loadColor = [](QComboBox* comboBox, QColor color)
|
||||
{
|
||||
auto index = comboBox->findData(color);
|
||||
comboBox->setCurrentIndex(index);
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
comboBox->setCurrentText(color.name());
|
||||
}
|
||||
};
|
||||
|
||||
loadColor(ui->removeColorCombo, m_settings->colorRemoved);
|
||||
loadColor(ui->addColorCombo, m_settings->colorAdded);
|
||||
loadColor(ui->replaceColorCombo, m_settings->colorReplaced);
|
||||
loadColor(ui->moveColorCombo, m_settings->colorPageMove);
|
||||
}
|
||||
|
||||
int SettingsDockWidget::getTransparencySliderValue() const
|
||||
{
|
||||
return ui->transparencySlider->value();
|
||||
}
|
||||
|
||||
QIcon SettingsDockWidget::getIconForColor(QColor color) const
|
||||
{
|
||||
QIcon icon;
|
||||
|
||||
QSize iconSize = pdf::PDFWidgetUtils::scaleDPI(this, QSize(16, 16));
|
||||
|
||||
QPixmap pixmap(iconSize.width(), iconSize.height());
|
||||
pixmap.fill(color);
|
||||
icon.addPixmap(pixmap);
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
void SettingsDockWidget::onEditColorChanged()
|
||||
{
|
||||
if (m_loadingColors)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool isChanged = false;
|
||||
auto saveColor = [&isChanged](QComboBox* comboBox, QColor& color)
|
||||
{
|
||||
QColor oldColor = color;
|
||||
color.fromString(comboBox->currentText());
|
||||
isChanged = isChanged || oldColor != color;
|
||||
};
|
||||
|
||||
saveColor(ui->removeColorCombo, m_settings->colorRemoved);
|
||||
saveColor(ui->addColorCombo, m_settings->colorAdded);
|
||||
saveColor(ui->replaceColorCombo, m_settings->colorReplaced);
|
||||
saveColor(ui->moveColorCombo, m_settings->colorPageMove);
|
||||
|
||||
if (isChanged)
|
||||
{
|
||||
Q_EMIT colorsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pdfdiff
|
|
@ -0,0 +1,73 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFDIFF_SETTINGSDOCKWIDGET_H
|
||||
#define PDFDIFF_SETTINGSDOCKWIDGET_H
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#include <QDockWidget>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class SettingsDockWidget;
|
||||
}
|
||||
|
||||
class QLineEdit;
|
||||
|
||||
namespace pdfdiff
|
||||
{
|
||||
|
||||
class SettingsDockWidget : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsDockWidget(Settings* settings, QWidget* parent);
|
||||
virtual ~SettingsDockWidget() override;
|
||||
|
||||
void setCompareTextsAsVectorGraphics(bool enabled);
|
||||
bool isCompareTextAsVectorGraphics() const;
|
||||
|
||||
void setCompareTextCharactersInsteadOfWords(bool enabled);
|
||||
bool isCompareTextCharactersInsteadOfWords() const;
|
||||
|
||||
QLineEdit* getLeftPageSelectionEdit() const;
|
||||
QLineEdit* getRightPageSelectionEdit() const;
|
||||
|
||||
void loadColors();
|
||||
void saveColors();
|
||||
|
||||
int getTransparencySliderValue() const;
|
||||
|
||||
signals:
|
||||
void colorsChanged();
|
||||
void transparencySliderChanged(int value);
|
||||
|
||||
private:
|
||||
QIcon getIconForColor(QColor color) const;
|
||||
|
||||
void onEditColorChanged();
|
||||
|
||||
Ui::SettingsDockWidget* ui;
|
||||
Settings* m_settings;
|
||||
bool m_loadingColors;
|
||||
};
|
||||
|
||||
} // namespace pdfdiff
|
||||
|
||||
#endif // PDFDIFF_SETTINGSDOCKWIDGET_H
|
|
@ -0,0 +1,563 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "utils.h"
|
||||
#include "pdfutils.h"
|
||||
#include "pdfwidgetutils.h"
|
||||
#include "pdfpainterutils.h"
|
||||
#include "pdfdocumentbuilder.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
namespace pdfdiff
|
||||
{
|
||||
|
||||
void ComparedDocumentMapper::update(ComparedDocumentMapper::Mode mode,
|
||||
bool filterDifferences,
|
||||
const pdf::PDFDiffResult& diff,
|
||||
const pdf::PDFDocument* leftDocument,
|
||||
const pdf::PDFDocument* rightDocument,
|
||||
const pdf::PDFDocument* currentDocument)
|
||||
{
|
||||
m_layout.clear();
|
||||
|
||||
m_leftPageIndices.clear();
|
||||
m_rightPageIndices.clear();
|
||||
|
||||
m_allLeft = false;
|
||||
m_allRight = false;
|
||||
|
||||
if (!leftDocument || !rightDocument || !currentDocument)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Jakub Melka
|
||||
pdf::PDFDiffResult::PageSequence pageSequence = diff.getPageSequence();
|
||||
const bool isEmpty = pageSequence.empty();
|
||||
|
||||
if (filterDifferences)
|
||||
{
|
||||
pdf::PDFDiffResult::PageSequence filteredPageSequence;
|
||||
|
||||
std::vector<pdf::PDFInteger> leftPageIndices = diff.getChangedLeftPageIndices();
|
||||
std::vector<pdf::PDFInteger> rightPageIndices = diff.getChangedRightPageIndices();
|
||||
|
||||
for (const pdf::PDFDiffResult::PageSequenceItem& item : pageSequence)
|
||||
{
|
||||
const bool isLeftModified = std::binary_search(leftPageIndices.cbegin(), leftPageIndices.cend(), item.leftPage);
|
||||
const bool isRightModified = std::binary_search(rightPageIndices.cbegin(), rightPageIndices.cend(), item.rightPage);
|
||||
|
||||
if (isLeftModified || isRightModified)
|
||||
{
|
||||
filteredPageSequence.push_back(item);
|
||||
}
|
||||
}
|
||||
|
||||
pageSequence = std::move(filteredPageSequence);
|
||||
}
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case ComparedDocumentMapper::Mode::Left:
|
||||
{
|
||||
Q_ASSERT(leftDocument == currentDocument);
|
||||
|
||||
m_allLeft = true;
|
||||
double yPos = 0.0;
|
||||
const pdf::PDFCatalog* catalog = leftDocument->getCatalog();
|
||||
|
||||
if (isEmpty)
|
||||
{
|
||||
// Just copy all pages
|
||||
const size_t pageCount = catalog->getPageCount();
|
||||
for (size_t i = 0; i < pageCount; ++i)
|
||||
{
|
||||
QSizeF pageSize = catalog->getPage(i)->getRotatedMediaBoxMM().size();
|
||||
QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||
m_layout.emplace_back(0, i, -1, rect);
|
||||
yPos += pageSize.height() + 5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const pdf::PDFDiffResult::PageSequenceItem& item : pageSequence)
|
||||
{
|
||||
if (item.leftPage == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QSizeF pageSize = catalog->getPage(item.leftPage)->getRotatedMediaBoxMM().size();
|
||||
QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||
m_layout.emplace_back(0, item.leftPage, -1, rect);
|
||||
yPos += pageSize.height() + 5;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ComparedDocumentMapper::Mode::Right:
|
||||
{
|
||||
Q_ASSERT(rightDocument == currentDocument);
|
||||
|
||||
m_allRight = true;
|
||||
double yPos = 0.0;
|
||||
const pdf::PDFCatalog* catalog = rightDocument->getCatalog();
|
||||
|
||||
if (isEmpty)
|
||||
{
|
||||
// Just copy all pages
|
||||
const size_t pageCount = catalog->getPageCount();
|
||||
for (size_t i = 0; i < pageCount; ++i)
|
||||
{
|
||||
QSizeF pageSize = catalog->getPage(i)->getRotatedMediaBoxMM().size();
|
||||
QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||
m_layout.emplace_back(0, i, -1, rect);
|
||||
yPos += pageSize.height() + 5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const pdf::PDFDiffResult::PageSequenceItem& item : pageSequence)
|
||||
{
|
||||
if (item.rightPage == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QSizeF pageSize = catalog->getPage(item.rightPage)->getRotatedMediaBoxMM().size();
|
||||
QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||
m_layout.emplace_back(0, item.rightPage, -1, rect);
|
||||
yPos += pageSize.height() + 5;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ComparedDocumentMapper::Mode::Combined:
|
||||
case ComparedDocumentMapper::Mode::Overlay:
|
||||
{
|
||||
double yPos = 0.0;
|
||||
const pdf::PDFCatalog* catalog = currentDocument->getCatalog();
|
||||
pdf::PDFInteger offset = leftDocument->getCatalog()->getPageCount();
|
||||
|
||||
for (const pdf::PDFDiffResult::PageSequenceItem& item : pageSequence)
|
||||
{
|
||||
double yAdvance = 0.0;
|
||||
|
||||
if (item.leftPage != -1)
|
||||
{
|
||||
QSizeF pageSize = catalog->getPage(item.leftPage)->getRotatedMediaBoxMM().size();
|
||||
QRectF rect;
|
||||
pdf::PDFInteger groupIndex = -1;
|
||||
if (mode == ComparedDocumentMapper::Mode::Combined)
|
||||
{
|
||||
rect = QRectF(-pageSize.width() - 5, yPos, pageSize.width(), pageSize.height());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.rightPage != -1)
|
||||
{
|
||||
groupIndex = 1;
|
||||
}
|
||||
rect = QRectF(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||
}
|
||||
m_layout.emplace_back(0, item.leftPage, groupIndex, rect);
|
||||
yAdvance = pageSize.height() + 5;
|
||||
m_leftPageIndices[item.leftPage] = item.leftPage;
|
||||
}
|
||||
|
||||
if (item.rightPage != -1)
|
||||
{
|
||||
pdf::PDFInteger rightPageIndex = item.rightPage + offset;
|
||||
QSizeF pageSize = catalog->getPage(rightPageIndex)->getRotatedMediaBoxMM().size();
|
||||
QRectF rect;
|
||||
pdf::PDFInteger groupIndex = -1;
|
||||
if (mode == ComparedDocumentMapper::Mode::Combined)
|
||||
{
|
||||
rect = QRectF(5, yPos, pageSize.width(), pageSize.height());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.leftPage != -1)
|
||||
{
|
||||
groupIndex = 2;
|
||||
}
|
||||
rect = QRectF(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||
}
|
||||
m_layout.emplace_back(0, rightPageIndex, groupIndex, rect);
|
||||
yAdvance = qMax(yAdvance, pageSize.height() + 5);
|
||||
m_rightPageIndices[rightPageIndex] = item.rightPage;
|
||||
}
|
||||
|
||||
yPos += yAdvance;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pdf::PDFInteger ComparedDocumentMapper::getLeftPageIndex(pdf::PDFInteger pageIndex) const
|
||||
{
|
||||
if (m_allLeft)
|
||||
{
|
||||
return pageIndex;
|
||||
}
|
||||
|
||||
auto it = m_leftPageIndices.find(pageIndex);
|
||||
if (it != m_leftPageIndices.cend())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
pdf::PDFInteger ComparedDocumentMapper::getRightPageIndex(pdf::PDFInteger pageIndex) const
|
||||
{
|
||||
if (m_allRight)
|
||||
{
|
||||
return pageIndex;
|
||||
}
|
||||
|
||||
auto it = m_rightPageIndices.find(pageIndex);
|
||||
if (it != m_rightPageIndices.cend())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
pdf::PDFInteger ComparedDocumentMapper::getPageIndexFromLeftPageIndex(pdf::PDFInteger leftPageIndex) const
|
||||
{
|
||||
if (m_allLeft)
|
||||
{
|
||||
return leftPageIndex;
|
||||
}
|
||||
|
||||
for (const auto& indexItem : m_leftPageIndices)
|
||||
{
|
||||
if (indexItem.second == leftPageIndex)
|
||||
{
|
||||
return indexItem.first;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
pdf::PDFInteger ComparedDocumentMapper::getPageIndexFromRightPageIndex(pdf::PDFInteger rightPageIndex) const
|
||||
{
|
||||
if (m_allRight)
|
||||
{
|
||||
return rightPageIndex;
|
||||
}
|
||||
|
||||
for (const auto& indexItem : m_rightPageIndices)
|
||||
{
|
||||
if (indexItem.second == rightPageIndex)
|
||||
{
|
||||
return indexItem.first;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
DifferencesDrawInterface::DifferencesDrawInterface(const Settings* settings,
|
||||
const ComparedDocumentMapper* mapper,
|
||||
const pdf::PDFDiffResult* diffResult) :
|
||||
m_settings(settings),
|
||||
m_mapper(mapper),
|
||||
m_diffResult(diffResult)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DifferencesDrawInterface::drawPage(QPainter* painter,
|
||||
pdf::PDFInteger pageIndex,
|
||||
const pdf::PDFPrecompiledPage* compiledPage,
|
||||
pdf::PDFTextLayoutGetter& layoutGetter,
|
||||
const QTransform& pagePointToDevicePointMatrix,
|
||||
QList<pdf::PDFRenderError>& errors) const
|
||||
{
|
||||
Q_UNUSED(compiledPage);
|
||||
Q_UNUSED(layoutGetter);
|
||||
Q_UNUSED(errors);
|
||||
|
||||
if (!m_settings->displayDifferences)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t differencesCount = m_diffResult->getDifferencesCount();
|
||||
const pdf::PDFInteger leftPageIndex = m_mapper->getLeftPageIndex(pageIndex);
|
||||
const pdf::PDFInteger rightPageIndex = m_mapper->getRightPageIndex(pageIndex);
|
||||
|
||||
std::optional<size_t> pageMoveIndex;
|
||||
|
||||
if (leftPageIndex != -1)
|
||||
{
|
||||
for (size_t i = 0; i < differencesCount; ++i)
|
||||
{
|
||||
auto leftRectangles = m_diffResult->getLeftRectangles(i);
|
||||
for (auto it = leftRectangles.first; it != leftRectangles.second; ++it)
|
||||
{
|
||||
const auto& item = *it;
|
||||
if (item.first == leftPageIndex)
|
||||
{
|
||||
QColor color = getColorForIndex(i);
|
||||
drawRectangle(painter, pagePointToDevicePointMatrix, item.second, color);
|
||||
drawMarker(painter, pagePointToDevicePointMatrix, item.second, color, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_diffResult->isPageMoveAddRemoveDifference(i) && m_diffResult->getLeftPage(i) == leftPageIndex)
|
||||
{
|
||||
pageMoveIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rightPageIndex != -1)
|
||||
{
|
||||
for (size_t i = 0; i < differencesCount; ++i)
|
||||
{
|
||||
auto rightRectangles = m_diffResult->getRightRectangles(i);
|
||||
for (auto it = rightRectangles.first; it != rightRectangles.second; ++it)
|
||||
{
|
||||
const auto& item = *it;
|
||||
if (item.first == rightPageIndex)
|
||||
{
|
||||
QColor color = getColorForIndex(i);
|
||||
drawRectangle(painter, pagePointToDevicePointMatrix, item.second, color);
|
||||
drawMarker(painter, pagePointToDevicePointMatrix, item.second, color, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_diffResult->isPageMoveAddRemoveDifference(i) && m_diffResult->getRightPage(i) == rightPageIndex)
|
||||
{
|
||||
pageMoveIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pageMoveIndex)
|
||||
{
|
||||
QString text;
|
||||
|
||||
switch (m_diffResult->getType(*pageMoveIndex))
|
||||
{
|
||||
case pdf::PDFDiffResult::Type::PageAdded:
|
||||
text = " + ";
|
||||
break;
|
||||
|
||||
case pdf::PDFDiffResult::Type::PageRemoved:
|
||||
text = " - ";
|
||||
break;
|
||||
|
||||
case pdf::PDFDiffResult::Type::PageMoved:
|
||||
text = QString("%1🠖%2").arg(m_diffResult->getLeftPage(*pageMoveIndex) + 1).arg(m_diffResult->getRightPage(*pageMoveIndex) + 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
QColor color = getColorForIndex(*pageMoveIndex);
|
||||
QPointF targetPoint = pagePointToDevicePointMatrix.map(QPointF(5, 5));
|
||||
pdf::PDFPainterHelper::drawBubble(painter, targetPoint.toPoint(), color, text, Qt::AlignRight | Qt::AlignTop);
|
||||
}
|
||||
}
|
||||
|
||||
QColor DifferencesDrawInterface::getColorForIndex(size_t index) const
|
||||
{
|
||||
QColor color;
|
||||
|
||||
const size_t resultIndex = index;
|
||||
|
||||
if (m_diffResult->isReplaceDifference(resultIndex))
|
||||
{
|
||||
color = m_settings->colorReplaced;
|
||||
}
|
||||
else if (m_diffResult->isRemoveDifference(resultIndex))
|
||||
{
|
||||
color = m_settings->colorRemoved;
|
||||
}
|
||||
else if (m_diffResult->isAddDifference(resultIndex))
|
||||
{
|
||||
color = m_settings->colorAdded;
|
||||
}
|
||||
else if (m_diffResult->isPageMoveDifference(resultIndex))
|
||||
{
|
||||
color = m_settings->colorPageMove;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void DifferencesDrawInterface::drawPostRendering(QPainter* painter, QRect rect) const
|
||||
{
|
||||
Q_UNUSED(painter);
|
||||
Q_UNUSED(rect);
|
||||
}
|
||||
|
||||
void DifferencesDrawInterface::drawAnnotations(const pdf::PDFDocument* document,
|
||||
pdf::PDFDocumentBuilder* builder)
|
||||
{
|
||||
pdf::PDFInteger pageCount = document->getCatalog()->getPageCount();
|
||||
|
||||
QString title = pdf::PDFSysUtils::getUserName();
|
||||
QString subject = tr("Difference");
|
||||
|
||||
for (pdf::PDFInteger pageIndex = 0; pageIndex < pageCount; ++pageIndex)
|
||||
{
|
||||
const size_t differencesCount = m_diffResult->getDifferencesCount();
|
||||
const pdf::PDFInteger leftPageIndex = m_mapper->getLeftPageIndex(pageIndex);
|
||||
const pdf::PDFInteger rightPageIndex = m_mapper->getRightPageIndex(pageIndex);
|
||||
|
||||
const pdf::PDFPage* page = document->getCatalog()->getPage(pageIndex);
|
||||
pdf::PDFObjectReference reference = page->getPageReference();
|
||||
|
||||
if (leftPageIndex != -1)
|
||||
{
|
||||
for (size_t i = 0; i < differencesCount; ++i)
|
||||
{
|
||||
auto leftRectangles = m_diffResult->getLeftRectangles(i);
|
||||
for (auto it = leftRectangles.first; it != leftRectangles.second; ++it)
|
||||
{
|
||||
const auto& item = *it;
|
||||
if (item.first == leftPageIndex)
|
||||
{
|
||||
QColor color = getColorForIndex(i);
|
||||
const QRectF& rect = item.second;
|
||||
QPolygonF polygon;
|
||||
polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft();
|
||||
pdf::PDFObjectReference annotation = builder->createAnnotationPolygon(reference, polygon, 1.0, color, color, title, subject, m_diffResult->getMessage(i));
|
||||
builder->setAnnotationOpacity(annotation, 0.3);
|
||||
builder->updateAnnotationAppearanceStreams(annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rightPageIndex != -1)
|
||||
{
|
||||
for (size_t i = 0; i < differencesCount; ++i)
|
||||
{
|
||||
auto rightRectangles = m_diffResult->getRightRectangles(i);
|
||||
for (auto it = rightRectangles.first; it != rightRectangles.second; ++it)
|
||||
{
|
||||
const auto& item = *it;
|
||||
if (item.first == rightPageIndex)
|
||||
{
|
||||
QColor color = getColorForIndex(i);
|
||||
const QRectF& rect = item.second;
|
||||
QPolygonF polygon;
|
||||
polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft();
|
||||
pdf::PDFObjectReference annotation = builder->createAnnotationPolygon(reference, polygon, 1.0, color, color, title, subject, m_diffResult->getMessage(i));
|
||||
builder->setAnnotationOpacity(annotation, 0.3);
|
||||
builder->updateAnnotationAppearanceStreams(annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DifferencesDrawInterface::drawRectangle(QPainter* painter,
|
||||
const QTransform& pagePointToDevicePointMatrix,
|
||||
const QRectF& rect,
|
||||
QColor color) const
|
||||
{
|
||||
color.setAlphaF(0.5);
|
||||
|
||||
QRectF resultRect = pagePointToDevicePointMatrix.mapRect(rect);
|
||||
painter->fillRect(resultRect, color);
|
||||
}
|
||||
|
||||
void DifferencesDrawInterface::drawMarker(QPainter* painter,
|
||||
const QTransform& pagePointToDevicePointMatrix,
|
||||
const QRectF& rect,
|
||||
QColor color,
|
||||
bool isLeft) const
|
||||
{
|
||||
if (!m_settings->displayMarkers)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pdf::PDFPainterStateGuard guard(painter);
|
||||
QRectF deviceRect = pagePointToDevicePointMatrix.mapRect(rect);
|
||||
|
||||
QPointF snapPoint;
|
||||
QPointF markPoint;
|
||||
|
||||
if (isLeft)
|
||||
{
|
||||
snapPoint.ry() = deviceRect.center().y();
|
||||
snapPoint.rx() = deviceRect.left();
|
||||
markPoint = snapPoint;
|
||||
markPoint.rx() = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
snapPoint.ry() = deviceRect.center().y();
|
||||
snapPoint.rx() = deviceRect.right();
|
||||
markPoint = snapPoint;
|
||||
markPoint.rx() = painter->device()->width();
|
||||
}
|
||||
|
||||
const qreal lineWidthF = pdf::PDFWidgetUtils::scaleDPI_y(painter->device(), 2);
|
||||
|
||||
QPen pen(Qt::DotLine);
|
||||
pen.setColor(color);
|
||||
pen.setWidthF(lineWidthF);
|
||||
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->setPen(pen);
|
||||
painter->drawLine(snapPoint, markPoint);
|
||||
|
||||
const qreal markSizeX = pdf::PDFWidgetUtils::scaleDPI_x(painter->device(), 10);
|
||||
const qreal markSizeY = pdf::PDFWidgetUtils::scaleDPI_y(painter->device(), 10);
|
||||
|
||||
QPointF ptc = markPoint;
|
||||
QPointF ptTop = ptc;
|
||||
QPointF ptBottom = ptc;
|
||||
|
||||
ptTop.ry() -= markSizeY;
|
||||
ptBottom.ry() += markSizeY;
|
||||
ptc.rx() += isLeft ? markSizeX : -markSizeX;
|
||||
|
||||
std::array points = { ptTop, ptc, ptBottom };
|
||||
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(QBrush(color));
|
||||
painter->drawConvexPolygon(points.data(), int(points.size()));
|
||||
}
|
||||
|
||||
} // namespace pdfdiff
|
|
@ -0,0 +1,126 @@
|
|||
// Copyright (C) 2021-2024 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFDIFF_UTILS_H
|
||||
#define PDFDIFF_UTILS_H
|
||||
|
||||
#include "settings.h"
|
||||
#include "pdfdiff.h"
|
||||
#include "pdfdrawspacecontroller.h"
|
||||
#include "pdfdocumentdrawinterface.h"
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
class PDFDocumentBuilder;
|
||||
} // namespace pdf
|
||||
|
||||
namespace pdfdiff
|
||||
{
|
||||
|
||||
class ComparedDocumentMapper
|
||||
{
|
||||
public:
|
||||
|
||||
enum class Mode
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
Combined,
|
||||
Overlay
|
||||
};
|
||||
|
||||
void update(Mode mode,
|
||||
bool filterDifferences,
|
||||
const pdf::PDFDiffResult& diff,
|
||||
const pdf::PDFDocument* leftDocument,
|
||||
const pdf::PDFDocument* rightDocument,
|
||||
const pdf::PDFDocument* currentDocument);
|
||||
|
||||
const pdf::PDFDrawSpaceController::LayoutItems& getLayout() const { return m_layout; }
|
||||
void setPageSequence(const pdf::PDFDiffResult::PageSequence& sequence) { m_pageSequence = sequence; }
|
||||
|
||||
/// Returns left page index (that means page index in left document),
|
||||
/// if it doesn't exist, -1 is returned.
|
||||
/// \param pageIndex Actual page index
|
||||
pdf::PDFInteger getLeftPageIndex(pdf::PDFInteger pageIndex) const;
|
||||
|
||||
/// Returns right page index (that means page index in right document),
|
||||
/// if it doesn't exist, -1 is returned.
|
||||
/// \param pageIndex Actual page index
|
||||
pdf::PDFInteger getRightPageIndex(pdf::PDFInteger pageIndex) const;
|
||||
|
||||
/// Returns actual page index from left page index, or -1.
|
||||
/// \param leftPageIndex Left page index
|
||||
pdf::PDFInteger getPageIndexFromLeftPageIndex(pdf::PDFInteger leftPageIndex) const;
|
||||
|
||||
/// Returns actual page index from right page index, or -1.
|
||||
/// \param rightPageIndex Right page index
|
||||
pdf::PDFInteger getPageIndexFromRightPageIndex(pdf::PDFInteger rightPageIndex) const;
|
||||
|
||||
private:
|
||||
pdf::PDFDrawSpaceController::LayoutItems m_layout;
|
||||
bool m_allLeft = false;
|
||||
bool m_allRight = false;
|
||||
std::map<pdf::PDFInteger, pdf::PDFInteger> m_leftPageIndices;
|
||||
std::map<pdf::PDFInteger, pdf::PDFInteger> m_rightPageIndices;
|
||||
pdf::PDFDiffResult::PageSequence m_pageSequence;
|
||||
};
|
||||
|
||||
class DifferencesDrawInterface : public pdf::IDocumentDrawInterface
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(pdfdiff::DifferencesDrawInterface)
|
||||
|
||||
public:
|
||||
explicit DifferencesDrawInterface(const Settings* settings,
|
||||
const ComparedDocumentMapper* mapper,
|
||||
const pdf::PDFDiffResult* diffResult);
|
||||
|
||||
virtual void drawPage(QPainter* painter, pdf::PDFInteger pageIndex,
|
||||
const pdf::PDFPrecompiledPage* compiledPage,
|
||||
pdf::PDFTextLayoutGetter& layoutGetter,
|
||||
const QTransform& pagePointToDevicePointMatrix,
|
||||
QList<pdf::PDFRenderError>& errors) const override;
|
||||
|
||||
virtual void drawPostRendering(QPainter* painter, QRect rect) const override;
|
||||
|
||||
/// Draw annotations for differences
|
||||
/// \param document Document
|
||||
/// \param builder Builder
|
||||
void drawAnnotations(const pdf::PDFDocument* document, pdf::PDFDocumentBuilder* builder);
|
||||
|
||||
private:
|
||||
void drawRectangle(QPainter* painter,
|
||||
const QTransform& pagePointToDevicePointMatrix,
|
||||
const QRectF& rect,
|
||||
QColor color) const;
|
||||
|
||||
void drawMarker(QPainter* painter,
|
||||
const QTransform& pagePointToDevicePointMatrix,
|
||||
const QRectF& rect,
|
||||
QColor color,
|
||||
bool isLeft) const;
|
||||
|
||||
QColor getColorForIndex(size_t index) const;
|
||||
|
||||
const Settings* m_settings;
|
||||
const ComparedDocumentMapper* m_mapper;
|
||||
const pdf::PDFDiffResult* m_diffResult;
|
||||
};
|
||||
|
||||
} // namespace pdfdiff
|
||||
|
||||
#endif // PDFDIFF_UTILS_H
|
|
@ -1,40 +0,0 @@
|
|||
# Copyright (C) 2022 Jakub Melka
|
||||
#
|
||||
# This file is part of PDF4QT.
|
||||
#
|
||||
# PDF4QT is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# with the written consent of the copyright owner, any later version.
|
||||
#
|
||||
# PDF4QT is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
add_executable(Pdf4QtDocDiff
|
||||
aboutdialog.cpp
|
||||
differencesdockwidget.cpp
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
settingsdockwidget.cpp
|
||||
utils.cpp
|
||||
aboutdialog.ui
|
||||
differencesdockwidget.ui
|
||||
mainwindow.ui
|
||||
settingsdockwidget.ui
|
||||
resources.qrc
|
||||
icon.rc
|
||||
)
|
||||
|
||||
target_link_libraries(Pdf4QtDocDiff PRIVATE Pdf4QtLib Qt6::Core Qt6::Gui Qt6::Widgets Qt6::OpenGLWidgets)
|
||||
|
||||
set_target_properties(Pdf4QtDocDiff PROPERTIES
|
||||
WIN32_EXECUTABLE ON
|
||||
MACOSX_BUNDLE ON
|
||||
)
|
||||
|
||||
install(TARGETS Pdf4QtDocDiff)
|
|
@ -1,64 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "aboutdialog.h"
|
||||
#include "ui_aboutdialog.h"
|
||||
|
||||
#include "pdfutils.h"
|
||||
#include "pdfwidgetutils.h"
|
||||
|
||||
namespace pdfdocdiff
|
||||
{
|
||||
|
||||
PDFAboutDialog::PDFAboutDialog(QWidget* parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::PDFAboutDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QString html = ui->copyrightLabel->text();
|
||||
html.replace("PdfForQtViewer", QString("%1 %2").arg(QApplication::applicationDisplayName(), QApplication::applicationVersion()));
|
||||
ui->copyrightLabel->setText(html);
|
||||
|
||||
std::vector<pdf::PDFDependentLibraryInfo> infos = pdf::PDFDependentLibraryInfo::getLibraryInfo();
|
||||
|
||||
ui->tableWidget->setColumnCount(4);
|
||||
ui->tableWidget->setRowCount(static_cast<int>(infos.size()));
|
||||
ui->tableWidget->setHorizontalHeaderLabels(QStringList() << tr("Library") << tr("Version") << tr("License") << tr("URL"));
|
||||
ui->tableWidget->setEditTriggers(QTableWidget::NoEditTriggers);
|
||||
ui->tableWidget->setSelectionMode(QTableView::SingleSelection);
|
||||
ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
|
||||
for (int i = 0; i < infos.size(); ++i)
|
||||
{
|
||||
const pdf::PDFDependentLibraryInfo& info = infos[i];
|
||||
ui->tableWidget->setItem(i, 0, new QTableWidgetItem(info.library));
|
||||
ui->tableWidget->setItem(i, 1, new QTableWidgetItem(info.version));
|
||||
ui->tableWidget->setItem(i, 2, new QTableWidgetItem(info.license));
|
||||
ui->tableWidget->setItem(i, 3, new QTableWidgetItem(info.url));
|
||||
}
|
||||
|
||||
pdf::PDFWidgetUtils::scaleWidget(this, QSize(750, 600));
|
||||
pdf::PDFWidgetUtils::style(this);
|
||||
}
|
||||
|
||||
PDFAboutDialog::~PDFAboutDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
} // namespace pdfdocdiff
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFDOCDIFF_PDFABOUTDIALOG_H
|
||||
#define PDFDOCDIFF_PDFABOUTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class PDFAboutDialog;
|
||||
}
|
||||
|
||||
namespace pdfdocdiff
|
||||
{
|
||||
|
||||
class PDFAboutDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PDFAboutDialog(QWidget* parent);
|
||||
virtual ~PDFAboutDialog() override;
|
||||
|
||||
private:
|
||||
Ui::PDFAboutDialog* ui;
|
||||
};
|
||||
|
||||
} // namespace pdfdocdiff
|
||||
|
||||
#endif // PDFDOCDIFF_PDFABOUTDIALOG_H
|
|
@ -1,269 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PDFAboutDialog</class>
|
||||
<widget class="QDialog" name="PDFAboutDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>900</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>900</width>
|
||||
<height>600</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>About</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="copyrightLabel">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-weight:600;">PdfForQtViewer</span></p><p>Copyright 2018-2023 Jakub Melka. All rights reserved.</p><p>THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="textEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> GNU LESSER GENERAL PUBLIC LICENSE</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Version 3, 29 June 2007</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Copyright (C) 2007 Free Software Foundation, Inc. &lt;https://fsf.org/&gt;</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Everyone is permitted to copy and distribute verbatim copies</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> of this license document, but changing it is not allowed.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> This version of the GNU Lesser General Public License incorporates</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the terms and conditions of version 3 of the GNU General Public</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">License, supplemented by the additional permissions listed below.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 0. Additional Definitions.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> As used herein, &quot;this License&quot; refers to version 3 of the GNU Lesser</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">General Public License, and the &quot;GNU GPL&quot; refers to version 3 of the GNU</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">General Public License.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> &quot;The Library&quot; refers to a covered work governed by this License,</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">other than an Application or a Combined Work as defined below.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> An &quot;Application&quot; is any work that makes use of an interface provided</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">by the Library, but which is not otherwise based on the Library.</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Defining a subclass of a class defined by the Library is deemed a mode</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">of using an interface provided by the Library.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A &quot;Combined Work&quot; is a work produced by combining or linking an</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Application with the Library. The particular version of the Library</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">with which the Combined Work was made is also called the &quot;Linked</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Version&quot;.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The &quot;Minimal Corresponding Source&quot; for a Combined Work means the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Corresponding Source for the Combined Work, excluding any source code</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">for portions of the Combined Work that, considered in isolation, are</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">based on the Application, and not on the Linked Version.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The &quot;Corresponding Application Code&quot; for a Combined Work means the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">object code and/or source code for the Application, including any data</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">and utility programs needed for reproducing the Combined Work from the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Application, but excluding the System Libraries of the Combined Work.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 1. Exception to Section 3 of the GNU GPL.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> You may convey a covered work under sections 3 and 4 of this License</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">without being bound by section 3 of the GNU GPL.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 2. Conveying Modified Versions.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> If you modify a copy of the Library, and, in your modifications, a</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">facility refers to a function or data to be supplied by an Application</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">that uses the facility (other than as an argument passed when the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">facility is invoked), then you may convey a copy of the modified</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">version:</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> a) under this License, provided that you make a good faith effort to</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> ensure that, in the event an Application does not supply the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> function or data, the facility still operates, and performs</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> whatever part of its purpose remains meaningful, or</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> b) under the GNU GPL, with none of the additional permissions of</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> this License applicable to that copy.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 3. Object Code Incorporating Material from Library Header Files.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The object code form of an Application may incorporate material from</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">a header file that is part of the Library. You may convey such object</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">code under terms of your choice, provided that, if the incorporated</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">material is not limited to numerical parameters, data structure</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">layouts and accessors, or small macros, inline functions and templates</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(ten or fewer lines in length), you do both of the following:</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> a) Give prominent notice with each copy of the object code that the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Library is used in it and that the Library and its use are</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> covered by this License.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> b) Accompany the object code with a copy of the GNU GPL and this license</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> document.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 4. Combined Works.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> You may convey a Combined Work under terms of your choice that,</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">taken together, effectively do not restrict modification of the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">portions of the Library contained in the Combined Work and reverse</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">engineering for debugging such modifications, if you also do each of</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the following:</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> a) Give prominent notice with each copy of the Combined Work that</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> the Library is used in it and that the Library and its use are</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> covered by this License.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> b) Accompany the Combined Work with a copy of the GNU GPL and this license</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> document.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> c) For a Combined Work that displays copyright notices during</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> execution, include the copyright notice for the Library among</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> these notices, as well as a reference directing the user to the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> copies of the GNU GPL and this license document.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> d) Do one of the following:</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 0) Convey the Minimal Corresponding Source under the terms of this</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> License, and the Corresponding Application Code in a form</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> suitable for, and under terms that permit, the user to</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> recombine or relink the Application with a modified version of</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> the Linked Version to produce a modified Combined Work, in the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> manner specified by section 6 of the GNU GPL for conveying</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Corresponding Source.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 1) Use a suitable shared library mechanism for linking with the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Library. A suitable mechanism is one that (a) uses at run time</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> a copy of the Library already present on the user's computer</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> system, and (b) will operate properly with a modified version</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> of the Library that is interface-compatible with the Linked</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Version.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> e) Provide Installation Information, but only if you would otherwise</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> be required to provide such information under section 6 of the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> GNU GPL, and only to the extent that such information is</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> necessary to install and execute a modified version of the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Combined Work produced by recombining or relinking the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Application with a modified version of the Linked Version. (If</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> you use option 4d0, the Installation Information must accompany</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> the Minimal Corresponding Source and Corresponding Application</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Code. If you use option 4d1, you must provide the Installation</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Information in the manner specified by section 6 of the GNU GPL</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> for conveying Corresponding Source.)</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 5. Combined Libraries.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> You may place library facilities that are a work based on the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Library side by side in a single library together with other library</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">facilities that are not Applications and are not covered by this</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">License, and convey such a combined library under terms of your</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">choice, if you do both of the following:</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> a) Accompany the combined library with a copy of the same work based</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> on the Library, uncombined with any other library facilities,</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> conveyed under the terms of this License.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> b) Give prominent notice with the combined library that part of it</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> is a work based on the Library, and explaining where to find the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> accompanying uncombined form of the same work.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 6. Revised Versions of the GNU Lesser General Public License.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The Free Software Foundation may publish revised and/or new versions</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">of the GNU Lesser General Public License from time to time. Such new</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">versions will be similar in spirit to the present version, but may</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">differ in detail to address new problems or concerns.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Each version is given a distinguishing version number. If the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Library as you received it specifies that a certain numbered version</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">of the GNU Lesser General Public License &quot;or any later version&quot;</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">applies to it, you have the option of following the terms and</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">conditions either of that published version or of any later version</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">published by the Free Software Foundation. If the Library as you</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">received it does not specify a version number of the GNU Lesser</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">General Public License, you may choose any version of the GNU Lesser</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">General Public License ever published by the Free Software Foundation.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> If the Library as you received it specifies that a proxy can decide</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">whether future versions of the GNU Lesser General Public License shall</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">apply, that proxy's public statement of acceptance of any version is</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">permanent authorization for you to choose that version for the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Library.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="usedLibrariesLabel">
|
||||
<property name="text">
|
||||
<string>Used libraries</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="tableWidget"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>PDFAboutDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>PDFAboutDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -1,305 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "differencesdockwidget.h"
|
||||
#include "ui_differencesdockwidget.h"
|
||||
|
||||
#include "pdfdiff.h"
|
||||
#include "pdfwidgetutils.h"
|
||||
|
||||
#include <QPixmap>
|
||||
#include <QPainter>
|
||||
#include <QTreeWidgetItem>
|
||||
|
||||
namespace pdfdocdiff
|
||||
{
|
||||
|
||||
DifferenceItemDelegate::DifferenceItemDelegate(QObject* parent) :
|
||||
BaseClass(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DifferenceItemDelegate::paint(QPainter* painter,
|
||||
const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const
|
||||
{
|
||||
BaseClass::paint(painter, option, index);
|
||||
}
|
||||
|
||||
QSize DifferenceItemDelegate::sizeHint(const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const
|
||||
{
|
||||
QStyleOptionViewItem adjustedOption = option;
|
||||
|
||||
if (!option.rect.isValid())
|
||||
{
|
||||
// Jakub Melka: Why this? We need to use text wrapping. Unfortunately,
|
||||
// standard delegate needs correct text rectangle (at least rectangle width),
|
||||
// for word wrap calculation. So we must manually calculate rectangle width.
|
||||
// Of course, we cant use visualRect of the tree widget, because of cyclical
|
||||
// dependence.
|
||||
|
||||
const QTreeWidget* treeWidget = qobject_cast<const QTreeWidget*>(option.widget);
|
||||
int xOffset = treeWidget->columnViewportPosition(index.column());
|
||||
int height = option.fontMetrics.lineSpacing();
|
||||
int yOffset = 0;
|
||||
int width = treeWidget->columnWidth(index.column());
|
||||
|
||||
int level = treeWidget->rootIsDecorated() ? 1 : 0;
|
||||
QModelIndex currentIndex = index.parent();
|
||||
while (currentIndex.isValid())
|
||||
{
|
||||
++level;
|
||||
currentIndex = currentIndex.parent();
|
||||
}
|
||||
|
||||
xOffset += level * treeWidget->indentation();
|
||||
adjustedOption.rect = QRect(xOffset, yOffset, width - xOffset, height);
|
||||
}
|
||||
|
||||
return BaseClass::sizeHint(adjustedOption, index);
|
||||
}
|
||||
|
||||
DifferencesDockWidget::DifferencesDockWidget(QWidget* parent,
|
||||
pdf::PDFDiffResult* unfilteredDiffResult,
|
||||
pdf::PDFDiffResult* diffResult,
|
||||
pdf::PDFDiffResultNavigator* diffNavigator,
|
||||
Settings* settings) :
|
||||
QDockWidget(parent),
|
||||
ui(new Ui::DifferencesDockWidget),
|
||||
m_unfilteredDiffResult(unfilteredDiffResult),
|
||||
m_diffResult(diffResult),
|
||||
m_diffNavigator(diffNavigator),
|
||||
m_settings(settings),
|
||||
m_disableChangeSelectedResultIndex(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
ui->differencesTreeWidget->setItemDelegate(new DifferenceItemDelegate(this));
|
||||
ui->differencesTreeWidget->setIconSize(pdf::PDFWidgetUtils::scaleDPI(ui->differencesTreeWidget, QSize(16, 16)));
|
||||
connect(diffNavigator, &pdf::PDFDiffResultNavigator::selectionChanged, this, &DifferencesDockWidget::onSelectionChanged);
|
||||
connect(ui->differencesTreeWidget, &QTreeWidget::currentItemChanged, this, &DifferencesDockWidget::onCurrentItemChanged);
|
||||
|
||||
setMinimumWidth(pdf::PDFWidgetUtils::scaleDPI_x(this, 120));
|
||||
}
|
||||
|
||||
DifferencesDockWidget::~DifferencesDockWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QColor DifferencesDockWidget::getColorForIndex(size_t index) const
|
||||
{
|
||||
QColor color;
|
||||
|
||||
const size_t resultIndex = index;
|
||||
|
||||
if (m_diffResult->isReplaceDifference(resultIndex))
|
||||
{
|
||||
color = m_settings->colorReplaced;
|
||||
}
|
||||
else if (m_diffResult->isRemoveDifference(resultIndex))
|
||||
{
|
||||
color = m_settings->colorRemoved;
|
||||
}
|
||||
else if (m_diffResult->isAddDifference(resultIndex))
|
||||
{
|
||||
color = m_settings->colorAdded;
|
||||
}
|
||||
else if (m_diffResult->isPageMoveDifference(resultIndex))
|
||||
{
|
||||
color = m_settings->colorPageMove;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
QModelIndex DifferencesDockWidget::findResultIndex(size_t index) const
|
||||
{
|
||||
QAbstractItemModel* model = ui->differencesTreeWidget->model();
|
||||
const int count = ui->differencesTreeWidget->topLevelItemCount();
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
QModelIndex parentIndex = model->index(i, 0);
|
||||
if (parentIndex.isValid())
|
||||
{
|
||||
const int childCount = model->rowCount(parentIndex);
|
||||
for (int j = 0; j < childCount; ++j)
|
||||
{
|
||||
QModelIndex childIndex = model->index(j, 0, parentIndex);
|
||||
QVariant childUserData = childIndex.data(Qt::UserRole);
|
||||
if (childUserData.isValid())
|
||||
{
|
||||
if (childUserData.toULongLong() == index)
|
||||
{
|
||||
return childIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
void DifferencesDockWidget::update()
|
||||
{
|
||||
ui->differencesTreeWidget->clear();
|
||||
|
||||
QList<QTreeWidgetItem*> topItems;
|
||||
|
||||
QLocale locale;
|
||||
|
||||
if (m_diffResult && !m_diffResult->isSame())
|
||||
{
|
||||
std::map<QRgb, QIcon> icons;
|
||||
auto getIcon = [this, &icons](QColor color)
|
||||
{
|
||||
auto it = icons.find(color.rgb());
|
||||
if (it == icons.end())
|
||||
{
|
||||
QPixmap pixmap(ui->differencesTreeWidget->iconSize());
|
||||
pixmap.fill(Qt::transparent);
|
||||
|
||||
QPainter painter(&pixmap);
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setBrush(QBrush(color));
|
||||
painter.drawEllipse(0, 0, pixmap.width(), pixmap.height());
|
||||
painter.end();
|
||||
|
||||
QIcon icon(pixmap);
|
||||
it = icons.insert(std::make_pair(color.rgb(), std::move(icon))).first;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
};
|
||||
|
||||
const size_t differenceCount = m_diffResult->getDifferencesCount();
|
||||
const size_t unfilteredDifferenceCount = m_unfilteredDiffResult->getDifferencesCount();
|
||||
const size_t hiddenDifferences = unfilteredDifferenceCount - differenceCount;
|
||||
|
||||
if (hiddenDifferences > 0)
|
||||
{
|
||||
ui->infoTextLabel->setText(tr("%1 Differences (+%2 hidden)").arg(differenceCount).arg(hiddenDifferences));
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->infoTextLabel->setText(tr("%1 Differences").arg(differenceCount));
|
||||
}
|
||||
|
||||
pdf::PDFInteger lastLeftPageIndex = -1;
|
||||
pdf::PDFInteger lastRightPageIndex = -1;
|
||||
|
||||
for (size_t i = 0; i < differenceCount; ++i)
|
||||
{
|
||||
pdf::PDFInteger pageIndexLeft = m_diffResult->getLeftPage(i);
|
||||
pdf::PDFInteger pageIndexRight = m_diffResult->getRightPage(i);
|
||||
|
||||
if (lastLeftPageIndex != pageIndexLeft ||
|
||||
lastRightPageIndex != pageIndexRight ||
|
||||
topItems.empty())
|
||||
{
|
||||
// Create new top level item
|
||||
QStringList captionParts;
|
||||
captionParts << QString("#%1:").arg(topItems.size() + 1);
|
||||
|
||||
if (pageIndexLeft == pageIndexRight)
|
||||
{
|
||||
captionParts << tr("Page %1").arg(locale.toString(pageIndexLeft + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pageIndexLeft != -1)
|
||||
{
|
||||
captionParts << tr("Left %1").arg(locale.toString(pageIndexLeft + 1));
|
||||
}
|
||||
|
||||
if (pageIndexRight != -1)
|
||||
{
|
||||
captionParts << tr("Right %1").arg(locale.toString(pageIndexRight + 1));
|
||||
}
|
||||
}
|
||||
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(QStringList() << captionParts.join(" "));
|
||||
topItems << item;
|
||||
|
||||
lastLeftPageIndex = pageIndexLeft;
|
||||
lastRightPageIndex = pageIndexRight;
|
||||
}
|
||||
|
||||
Q_ASSERT(!topItems.isEmpty());
|
||||
QTreeWidgetItem* parent = topItems.back();
|
||||
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem(parent, QStringList() << m_diffResult->getMessage(i));
|
||||
item->setData(0, Qt::UserRole, QVariant(static_cast<qint64>(i)));
|
||||
|
||||
QColor color = getColorForIndex(i);
|
||||
|
||||
if (color.isValid())
|
||||
{
|
||||
item->setData(0, Qt::DecorationRole, getIcon(color));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->infoTextLabel->setText(tr("No Differences Found!"));
|
||||
}
|
||||
|
||||
ui->differencesTreeWidget->addTopLevelItems(topItems);
|
||||
ui->differencesTreeWidget->expandAll();
|
||||
}
|
||||
|
||||
void DifferencesDockWidget::onSelectionChanged(size_t currentIndex)
|
||||
{
|
||||
if (m_disableChangeSelectedResultIndex)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pdf::PDFTemporaryValueChange guard(&m_disableChangeSelectedResultIndex, true);
|
||||
|
||||
QModelIndex index = findResultIndex(currentIndex);
|
||||
if (index.isValid())
|
||||
{
|
||||
ui->differencesTreeWidget->scrollTo(index);
|
||||
ui->differencesTreeWidget->setCurrentIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
void DifferencesDockWidget::onCurrentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous)
|
||||
{
|
||||
Q_UNUSED(previous);
|
||||
|
||||
if (m_disableChangeSelectedResultIndex || !current)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pdf::PDFTemporaryValueChange guard(&m_disableChangeSelectedResultIndex, true);
|
||||
QVariant childUserData = current->data(0, Qt::UserRole);
|
||||
|
||||
if (childUserData.isValid())
|
||||
{
|
||||
m_diffNavigator->select(childUserData.toULongLong());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pdfdocdiff
|
|
@ -1,89 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef DIFFERENCESDOCKWIDGET_H
|
||||
#define DIFFERENCESDOCKWIDGET_H
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QItemDelegate>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class DifferencesDockWidget;
|
||||
}
|
||||
|
||||
class QTreeWidgetItem;
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
class PDFDiffResult;
|
||||
class PDFDiffResultNavigator;
|
||||
}
|
||||
|
||||
namespace pdfdocdiff
|
||||
{
|
||||
|
||||
class DifferenceItemDelegate : public QItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
using BaseClass = QItemDelegate;
|
||||
|
||||
public:
|
||||
DifferenceItemDelegate(QObject* parent);
|
||||
|
||||
virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
};
|
||||
|
||||
class DifferencesDockWidget : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit DifferencesDockWidget(QWidget* parent,
|
||||
pdf::PDFDiffResult* unfilteredDiffResult,
|
||||
pdf::PDFDiffResult* diffResult,
|
||||
pdf::PDFDiffResultNavigator* diffNavigator,
|
||||
Settings* settings);
|
||||
virtual ~DifferencesDockWidget() override;
|
||||
|
||||
void update();
|
||||
|
||||
private slots:
|
||||
void onSelectionChanged(size_t currentIndex);
|
||||
void onCurrentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous);
|
||||
|
||||
private:
|
||||
Ui::DifferencesDockWidget* ui;
|
||||
|
||||
QColor getColorForIndex(size_t index) const;
|
||||
QModelIndex findResultIndex(size_t index) const;
|
||||
|
||||
pdf::PDFDiffResult* m_unfilteredDiffResult;
|
||||
pdf::PDFDiffResult* m_diffResult;
|
||||
pdf::PDFDiffResultNavigator* m_diffNavigator;
|
||||
Settings* m_settings;
|
||||
bool m_disableChangeSelectedResultIndex;
|
||||
};
|
||||
|
||||
} // namespace pdfdocdiff
|
||||
|
||||
#endif // DIFFERENCESDOCKWIDGET_H
|
|
@ -1,51 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "pdfconstants.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCommandLineParser>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents, true);
|
||||
QApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity, true);
|
||||
|
||||
#if !defined(Q_OS_WIN)
|
||||
QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, true);
|
||||
#endif
|
||||
|
||||
QApplication application(argc, argv);
|
||||
|
||||
QCoreApplication::setOrganizationName("MelkaJ");
|
||||
QCoreApplication::setApplicationName("PDF4QT Document Diff");
|
||||
QCoreApplication::setApplicationVersion(pdf::PDF_LIBRARY_VERSION);
|
||||
QApplication::setApplicationDisplayName(QApplication::translate("Application", "PDF4QT Document Diff"));
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(QCoreApplication::applicationName());
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
parser.addPositionalArgument("file1", "The PDF file to be compared.");
|
||||
parser.addPositionalArgument("file2", "The PDF file to be compared.");
|
||||
parser.process(application);
|
||||
|
||||
pdfdocdiff::MainWindow mainWindow(nullptr);
|
||||
mainWindow.show();
|
||||
|
||||
return application.exec();
|
||||
}
|
|
@ -1,880 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include "aboutdialog.h"
|
||||
#include "differencesdockwidget.h"
|
||||
#include "settingsdockwidget.h"
|
||||
|
||||
#include "pdfwidgetutils.h"
|
||||
#include "pdfdocumentreader.h"
|
||||
#include "pdfdrawspacecontroller.h"
|
||||
#include "pdfdocumentmanipulator.h"
|
||||
#include "pdfdocumentbuilder.h"
|
||||
#include "pdfdocumentwriter.h"
|
||||
|
||||
#include <QToolBar>
|
||||
#include <QDesktopServices>
|
||||
#include <QMessageBox>
|
||||
#include <QInputDialog>
|
||||
#include <QFileDialog>
|
||||
#include <QVBoxLayout>
|
||||
#include <QActionGroup>
|
||||
#include <QScreen>
|
||||
|
||||
namespace pdfdocdiff
|
||||
{
|
||||
|
||||
MainWindow::MainWindow(QWidget* parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow),
|
||||
m_progress(new pdf::PDFProgress(this)),
|
||||
#ifdef WIN_TASKBAR_BUTTON
|
||||
m_taskbarButton(new QWinTaskbarButton(this)),
|
||||
m_progressTaskbarIndicator(nullptr),
|
||||
#endif
|
||||
m_cmsManager(nullptr),
|
||||
m_pdfWidget(nullptr),
|
||||
m_settingsDockWidget(nullptr),
|
||||
m_differencesDockWidget(nullptr),
|
||||
m_optionalContentActivity(nullptr),
|
||||
m_diff(nullptr),
|
||||
m_isChangingProgressStep(false),
|
||||
m_dontDisplayErrorMessage(false),
|
||||
m_diffNavigator(nullptr),
|
||||
m_drawInterface(&m_settings, &m_documentMapper, &m_filteredDiffResult)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
setMinimumSize(pdf::PDFWidgetUtils::scaleDPI(this, QSize(800, 600)));
|
||||
|
||||
// Initialize task bar progress
|
||||
#ifdef WIN_TASKBAR_BUTTON
|
||||
m_progressTaskbarIndicator = m_taskbarButton->progress();
|
||||
#endif
|
||||
|
||||
m_settingsDockWidget = new SettingsDockWidget(&m_settings, this);
|
||||
addDockWidget(Qt::LeftDockWidgetArea, m_settingsDockWidget);;
|
||||
connect(m_settingsDockWidget, &SettingsDockWidget::colorsChanged, this, &MainWindow::onColorsChanged);
|
||||
connect(m_settingsDockWidget, &SettingsDockWidget::transparencySliderChanged, this, &MainWindow::updateOverlayTransparency);
|
||||
|
||||
m_differencesDockWidget = new DifferencesDockWidget(this, &m_diffResult, &m_filteredDiffResult, &m_diffNavigator, &m_settings);
|
||||
addDockWidget(Qt::LeftDockWidgetArea, m_differencesDockWidget);
|
||||
|
||||
ui->documentFrame->setLayout(new QVBoxLayout);
|
||||
|
||||
m_cmsManager = new pdf::PDFCMSManager(this);
|
||||
m_pdfWidget = new pdf::PDFWidget(m_cmsManager, pdf::RendererEngine::Software, 1, ui->documentFrame);
|
||||
m_pdfWidget->getDrawWidgetProxy()->setProgress(m_progress);
|
||||
ui->documentFrame->layout()->addWidget(m_pdfWidget);
|
||||
m_pdfWidget->getDrawWidgetProxy()->registerDrawInterface(&m_drawInterface);
|
||||
|
||||
ui->menuView->addSeparator();
|
||||
ui->menuView->addAction(m_settingsDockWidget->toggleViewAction());
|
||||
ui->menuView->addAction(m_differencesDockWidget->toggleViewAction());
|
||||
|
||||
ui->actionGet_Source->setData(int(Operation::GetSource));
|
||||
ui->actionAbout->setData(int(Operation::About));
|
||||
ui->actionOpen_Left->setData(int(Operation::OpenLeft));
|
||||
ui->actionOpen_Right->setData(int(Operation::OpenRight));
|
||||
ui->actionCompare->setData(int(Operation::Compare));
|
||||
ui->actionClose->setData(int(Operation::Close));
|
||||
ui->actionPrevious_Difference->setData(int(Operation::PreviousDifference));
|
||||
ui->actionNext_Difference->setData(int(Operation::NextDifference));
|
||||
ui->actionCreate_Compare_Report->setData(int(Operation::CreateCompareReport));
|
||||
ui->actionFilter_Text->setData(int(Operation::FilterText));
|
||||
ui->actionFilter_Vector_Graphics->setData(int(Operation::FilterVectorGraphics));
|
||||
ui->actionFilter_Images->setData(int(Operation::FilterImages));
|
||||
ui->actionFilter_Shading->setData(int(Operation::FilterShading));
|
||||
ui->actionFilter_Page_Movement->setData(int(Operation::FilterPageMovement));
|
||||
ui->actionView_Differences->setData(int(Operation::ViewDifferences));
|
||||
ui->actionView_Left->setData(int(Operation::ViewLeft));
|
||||
ui->actionView_Right->setData(int(Operation::ViewRight));
|
||||
ui->actionView_Overlay->setData(int(Operation::ViewOverlay));
|
||||
ui->actionShow_Pages_with_Differences->setData(int(Operation::ShowPageswithDifferences));
|
||||
ui->actionSave_Differences_to_XML->setData(int(Operation::SaveDifferencesToXML));
|
||||
ui->actionDisplay_Differences->setData(int(Operation::DisplayDifferences));
|
||||
ui->actionDisplay_Markers->setData(int(Operation::DisplayMarkers));
|
||||
|
||||
ui->actionSynchronize_View_with_Differences->setChecked(true);
|
||||
|
||||
QActionGroup* actionGroup = new QActionGroup(this);
|
||||
actionGroup->setExclusionPolicy(QActionGroup::ExclusionPolicy::Exclusive);
|
||||
actionGroup->addAction(ui->actionView_Differences);
|
||||
actionGroup->addAction(ui->actionView_Left);
|
||||
actionGroup->addAction(ui->actionView_Right);
|
||||
actionGroup->addAction(ui->actionView_Overlay);
|
||||
ui->actionView_Differences->setChecked(true);
|
||||
|
||||
QToolBar* mainToolbar = addToolBar(tr("Main"));
|
||||
mainToolbar->setObjectName("main_toolbar");
|
||||
mainToolbar->addActions({ ui->actionOpen_Left, ui->actionOpen_Right });
|
||||
mainToolbar->addSeparator();
|
||||
mainToolbar->addAction(ui->actionCompare);
|
||||
mainToolbar->addAction(ui->actionCreate_Compare_Report);
|
||||
mainToolbar->addAction(ui->actionSave_Differences_to_XML);
|
||||
|
||||
QToolBar* differencesToolbar = addToolBar(tr("Differences"));
|
||||
differencesToolbar->setObjectName("differences_toolbar");
|
||||
differencesToolbar->addActions({ ui->actionPrevious_Difference, ui->actionNext_Difference });
|
||||
|
||||
QToolBar* viewToolbar = addToolBar(tr("View"));
|
||||
viewToolbar->setObjectName("view_toolbar");
|
||||
viewToolbar->addActions({ ui->actionView_Differences, ui->actionView_Left, ui->actionView_Right, ui->actionView_Overlay });
|
||||
viewToolbar->addSeparator();
|
||||
viewToolbar->addActions({ ui->actionShow_Pages_with_Differences, ui->actionSynchronize_View_with_Differences });
|
||||
viewToolbar->addSeparator();
|
||||
viewToolbar->addActions({ ui->actionFilter_Text, ui->actionFilter_Vector_Graphics, ui->actionFilter_Images, ui->actionFilter_Shading, ui->actionFilter_Page_Movement });
|
||||
|
||||
QSize iconSize = pdf::PDFWidgetUtils::scaleDPI(this, QSize(24, 24));
|
||||
auto toolbars = findChildren<QToolBar*>();
|
||||
for (QToolBar* toolbar : toolbars)
|
||||
{
|
||||
toolbar->setIconSize(iconSize);
|
||||
ui->menuToolbars->addAction(toolbar->toggleViewAction());
|
||||
}
|
||||
|
||||
connect(&m_mapper, &QSignalMapper::mappedInt, this, &MainWindow::onMappedActionTriggered);
|
||||
|
||||
QList<QAction*> actions = findChildren<QAction*>();
|
||||
for (QAction* action : actions)
|
||||
{
|
||||
QVariant actionData = action->data();
|
||||
if (actionData.isValid())
|
||||
{
|
||||
connect(action, &QAction::triggered, &m_mapper, QOverload<>::of(&QSignalMapper::map));
|
||||
m_mapper.setMapping(action, actionData.toInt());
|
||||
}
|
||||
}
|
||||
|
||||
connect(m_progress, &pdf::PDFProgress::progressStarted, this, &MainWindow::onProgressStarted);
|
||||
connect(m_progress, &pdf::PDFProgress::progressStep, this, &MainWindow::onProgressStep);
|
||||
connect(m_progress, &pdf::PDFProgress::progressFinished, this, &MainWindow::onProgressFinished);
|
||||
|
||||
m_diff.setProgress(m_progress);
|
||||
m_diff.setOption(pdf::PDFDiff::Asynchronous, true);
|
||||
connect(&m_diff, &pdf::PDFDiff::comparationFinished, this, &MainWindow::onComparationFinished);
|
||||
|
||||
m_diff.setLeftDocument(&m_leftDocument);
|
||||
m_diff.setRightDocument(&m_rightDocument);
|
||||
|
||||
m_diffNavigator.setResult(&m_filteredDiffResult);
|
||||
connect(&m_diffNavigator, &pdf::PDFDiffResultNavigator::selectionChanged, this, &MainWindow::onSelectionChanged);
|
||||
|
||||
loadSettings();
|
||||
updateAll(false);
|
||||
updateOverlayTransparency();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
saveSettings();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::showEvent(QShowEvent* event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
#ifdef WIN_TASKBAR_BUTTON
|
||||
m_taskbarButton->setWindow(windowHandle());
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
BaseClass::closeEvent(event);
|
||||
m_diff.stop();
|
||||
}
|
||||
|
||||
void MainWindow::onMappedActionTriggered(int actionId)
|
||||
{
|
||||
performOperation(static_cast<Operation>(actionId));
|
||||
}
|
||||
|
||||
void MainWindow::onComparationFinished()
|
||||
{
|
||||
clear(false, false);
|
||||
|
||||
m_diffResult = m_diff.getResult();
|
||||
|
||||
if (!m_dontDisplayErrorMessage)
|
||||
{
|
||||
if (!m_diffResult.getResult())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), m_diffResult.getResult().getErrorMessage());
|
||||
}
|
||||
if (m_diffResult.isSame())
|
||||
{
|
||||
QMessageBox::information(this, tr("Info"), tr("No differences found between the compared documents."), QMessageBox::Ok);
|
||||
}
|
||||
}
|
||||
|
||||
// Create merged document
|
||||
pdf::PDFDocumentManipulator manipulator;
|
||||
manipulator.setOutlineMode(pdf::PDFDocumentManipulator::OutlineMode::NoOutline);
|
||||
manipulator.addDocument(1, &m_leftDocument);
|
||||
manipulator.addDocument(2, &m_rightDocument);
|
||||
|
||||
pdf::PDFDocumentManipulator::AssembledPages assembledPages1 = pdf::PDFDocumentManipulator::createAllDocumentPages(1, &m_leftDocument);
|
||||
pdf::PDFDocumentManipulator::AssembledPages assembledPages2 = pdf::PDFDocumentManipulator::createAllDocumentPages(2, &m_rightDocument);
|
||||
assembledPages1.insert(assembledPages1.end(), std::make_move_iterator(assembledPages2.begin()), std::make_move_iterator(assembledPages2.end()));
|
||||
|
||||
if (manipulator.assemble(assembledPages1))
|
||||
{
|
||||
m_combinedDocument = manipulator.takeAssembledDocument();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_combinedDocument = pdf::PDFDocument();
|
||||
}
|
||||
|
||||
updateAll(true);
|
||||
}
|
||||
|
||||
void MainWindow::onColorsChanged()
|
||||
{
|
||||
updateFilteredResult();
|
||||
m_pdfWidget->update();
|
||||
}
|
||||
|
||||
void MainWindow::updateActions()
|
||||
{
|
||||
QList<QAction*> actions = findChildren<QAction*>();
|
||||
for (QAction* action : actions)
|
||||
{
|
||||
QVariant actionData = action->data();
|
||||
if (actionData.isValid())
|
||||
{
|
||||
bool canPerformAction = canPerformOperation(static_cast<Operation>(actionData.toInt()));
|
||||
action->setEnabled(canPerformAction);
|
||||
|
||||
if (!canPerformAction && action->isCheckable())
|
||||
{
|
||||
action->setChecked(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onSelectionChanged(size_t currentIndex)
|
||||
{
|
||||
if (ui->actionSynchronize_View_with_Differences->isChecked())
|
||||
{
|
||||
pdf::PDFInteger destinationPage = -1;
|
||||
|
||||
if (destinationPage == -1)
|
||||
{
|
||||
pdf::PDFInteger leftPageIndex = m_filteredDiffResult.getLeftPage(currentIndex);
|
||||
if (leftPageIndex != -1)
|
||||
{
|
||||
destinationPage = m_documentMapper.getPageIndexFromLeftPageIndex(leftPageIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if (destinationPage == -1)
|
||||
{
|
||||
pdf::PDFInteger rightPageIndex = m_filteredDiffResult.getRightPage(currentIndex);
|
||||
if (rightPageIndex != -1)
|
||||
{
|
||||
destinationPage = m_documentMapper.getPageIndexFromRightPageIndex(rightPageIndex);
|
||||
}
|
||||
}
|
||||
|
||||
if (destinationPage != -1)
|
||||
{
|
||||
m_pdfWidget->getDrawWidgetProxy()->goToPage(destinationPage);
|
||||
}
|
||||
}
|
||||
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void MainWindow::loadSettings()
|
||||
{
|
||||
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName());
|
||||
settings.beginGroup("MainWindow");
|
||||
QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray();
|
||||
if (geometry.isEmpty())
|
||||
{
|
||||
QRect availableGeometry = QApplication::primaryScreen()->availableGeometry();
|
||||
QRect windowRect(0, 0, availableGeometry.width() / 2, availableGeometry.height() / 2);
|
||||
windowRect = windowRect.translated(availableGeometry.center() - windowRect.center());
|
||||
setGeometry(windowRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
restoreGeometry(geometry);
|
||||
}
|
||||
|
||||
QByteArray state = settings.value("windowState", QByteArray()).toByteArray();
|
||||
if (!state.isEmpty())
|
||||
{
|
||||
restoreState(state);
|
||||
}
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup("Settings");
|
||||
m_settings.directory = settings.value("directory").toString();
|
||||
m_settings.colorPageMove = settings.value("colorPageMove", m_settings.colorPageMove).value<QColor>();
|
||||
m_settings.colorAdded = settings.value("colorAdded", m_settings.colorAdded).value<QColor>();
|
||||
m_settings.colorRemoved = settings.value("colorRemoved", m_settings.colorRemoved).value<QColor>();
|
||||
m_settings.colorReplaced = settings.value("colorReplaced", m_settings.colorReplaced).value<QColor>();
|
||||
m_settings.displayDifferences = settings.value("displayDifferences", m_settings.displayDifferences).toBool();
|
||||
m_settings.displayMarkers = settings.value("displayMarkers", m_settings.displayDifferences).toBool();
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup("Compare");
|
||||
m_settingsDockWidget->setCompareTextsAsVectorGraphics(settings.value("compareTextsAsVectorGraphics", false).toBool());
|
||||
m_settingsDockWidget->setCompareTextCharactersInsteadOfWords(settings.value("compareTextCharactersInsteadOfWords", false).toBool());
|
||||
settings.endGroup();
|
||||
|
||||
ui->actionDisplay_Differences->setChecked(m_settings.displayDifferences);
|
||||
ui->actionDisplay_Markers->setChecked(m_settings.displayMarkers);
|
||||
|
||||
m_settingsDockWidget->loadColors();
|
||||
}
|
||||
|
||||
void MainWindow::saveSettings()
|
||||
{
|
||||
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName());
|
||||
settings.beginGroup("MainWindow");
|
||||
settings.setValue("geometry", saveGeometry());
|
||||
settings.setValue("windowState", saveState());
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup("Settings");
|
||||
settings.setValue("directory", m_settings.directory);
|
||||
settings.setValue("colorPageMove", m_settings.colorPageMove);
|
||||
settings.setValue("colorAdded", m_settings.colorAdded);
|
||||
settings.setValue("colorRemoved", m_settings.colorRemoved);
|
||||
settings.setValue("colorReplaced", m_settings.colorReplaced);
|
||||
settings.setValue("displayDifferences", m_settings.displayDifferences);
|
||||
settings.setValue("displayMarkers", m_settings.displayMarkers);
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup("Compare");
|
||||
settings.setValue("compareTextsAsVectorGraphics", m_settingsDockWidget->isCompareTextAsVectorGraphics());
|
||||
settings.setValue("compareTextCharactersInsteadOfWords", m_settingsDockWidget->isCompareTextCharactersInsteadOfWords());
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
bool MainWindow::canPerformOperation(Operation operation) const
|
||||
{
|
||||
switch (operation)
|
||||
{
|
||||
case Operation::OpenLeft:
|
||||
case Operation::OpenRight:
|
||||
case Operation::Compare:
|
||||
case Operation::Close:
|
||||
case Operation::GetSource:
|
||||
case Operation::About:
|
||||
return true;
|
||||
|
||||
case Operation::ViewDifferences:
|
||||
case Operation::ViewLeft:
|
||||
case Operation::ViewRight:
|
||||
case Operation::ViewOverlay:
|
||||
return true; // Allow always to change a view
|
||||
|
||||
case Operation::FilterText:
|
||||
return m_diffResult.hasTextDifferences();
|
||||
|
||||
case Operation::FilterVectorGraphics:
|
||||
return m_diffResult.hasVectorGraphicsDifferences();
|
||||
|
||||
case Operation::FilterImages:
|
||||
return m_diffResult.hasImageDifferences();
|
||||
|
||||
case Operation::FilterShading:
|
||||
return m_diffResult.hasShadingDifferences();
|
||||
|
||||
case Operation::FilterPageMovement:
|
||||
return m_diffResult.hasPageMoveDifferences();
|
||||
|
||||
case Operation::PreviousDifference:
|
||||
return m_diffNavigator.canGoPrevious();
|
||||
|
||||
case Operation::NextDifference:
|
||||
return m_diffNavigator.canGoNext();
|
||||
|
||||
case Operation::CreateCompareReport:
|
||||
case Operation::SaveDifferencesToXML:
|
||||
return m_filteredDiffResult.isChanged();
|
||||
|
||||
case Operation::ShowPageswithDifferences:
|
||||
return m_diffResult.isChanged();
|
||||
|
||||
case Operation::DisplayDifferences:
|
||||
case Operation::DisplayMarkers:
|
||||
return true;
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MainWindow::performOperation(Operation operation)
|
||||
{
|
||||
switch (operation)
|
||||
{
|
||||
case Operation::OpenLeft:
|
||||
{
|
||||
pdf::PDFTemporaryValueChange guard(&m_dontDisplayErrorMessage, true);
|
||||
m_diff.stop();
|
||||
|
||||
std::optional<pdf::PDFDocument> document = openDocument();
|
||||
if (document)
|
||||
{
|
||||
clear(true, false);
|
||||
m_leftDocument = std::move(*document);
|
||||
|
||||
const size_t pageCount = m_leftDocument.getCatalog()->getPageCount();
|
||||
if (pageCount > 1)
|
||||
{
|
||||
m_settingsDockWidget->getLeftPageSelectionEdit()->setText(QString("1-%2").arg(pageCount));
|
||||
}
|
||||
else if (pageCount == 1)
|
||||
{
|
||||
m_settingsDockWidget->getLeftPageSelectionEdit()->setText("1");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settingsDockWidget->getLeftPageSelectionEdit()->clear();
|
||||
}
|
||||
|
||||
updateViewDocument();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::OpenRight:
|
||||
{
|
||||
pdf::PDFTemporaryValueChange guard(&m_dontDisplayErrorMessage, true);
|
||||
m_diff.stop();
|
||||
|
||||
std::optional<pdf::PDFDocument> document = openDocument();
|
||||
if (document)
|
||||
{
|
||||
clear(false, true);
|
||||
m_rightDocument = std::move(*document);
|
||||
|
||||
const size_t pageCount = m_rightDocument.getCatalog()->getPageCount();
|
||||
if (pageCount > 1)
|
||||
{
|
||||
m_settingsDockWidget->getRightPageSelectionEdit()->setText(QString("1-%2").arg(pageCount));
|
||||
}
|
||||
else if (pageCount == 1)
|
||||
{
|
||||
m_settingsDockWidget->getRightPageSelectionEdit()->setText("1");
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settingsDockWidget->getRightPageSelectionEdit()->clear();
|
||||
}
|
||||
|
||||
updateViewDocument();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::Compare:
|
||||
{
|
||||
pdf::PDFTemporaryValueChange guard(&m_dontDisplayErrorMessage, true);
|
||||
m_diff.stop();
|
||||
|
||||
m_diff.setOption(pdf::PDFDiff::CompareTextsAsVector, m_settingsDockWidget->isCompareTextAsVectorGraphics());
|
||||
m_diff.setOption(pdf::PDFDiff::CompareWords, !m_settingsDockWidget->isCompareTextCharactersInsteadOfWords());
|
||||
|
||||
QString errorMessage;
|
||||
|
||||
pdf::PDFClosedIntervalSet rightPageIndices;
|
||||
pdf::PDFClosedIntervalSet leftPageIndices = pdf::PDFClosedIntervalSet::parse(1, qMax<pdf::PDFInteger>(1, m_leftDocument.getCatalog()->getPageCount()), m_settingsDockWidget->getLeftPageSelectionEdit()->text(), &errorMessage);
|
||||
|
||||
if (errorMessage.isEmpty())
|
||||
{
|
||||
rightPageIndices = pdf::PDFClosedIntervalSet::parse(1, qMax<pdf::PDFInteger>(1, m_rightDocument.getCatalog()->getPageCount()), m_settingsDockWidget->getRightPageSelectionEdit()->text(), &errorMessage);
|
||||
}
|
||||
|
||||
// Check if pages are succesfully parsed
|
||||
if (!errorMessage.isEmpty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), errorMessage);
|
||||
break;
|
||||
}
|
||||
|
||||
leftPageIndices.translate(-1);
|
||||
rightPageIndices.translate(-1);
|
||||
|
||||
m_diff.setPagesForLeftDocument(std::move(leftPageIndices));
|
||||
m_diff.setPagesForRightDocument(std::move(rightPageIndices));
|
||||
|
||||
m_diff.start();
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::Close:
|
||||
{
|
||||
close();
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::GetSource:
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl("https://github.com/JakubMelka/PDF4QT"));
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::About:
|
||||
{
|
||||
PDFAboutDialog aboutDialog(this);
|
||||
aboutDialog.exec();
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::PreviousDifference:
|
||||
m_diffNavigator.goPrevious();
|
||||
break;
|
||||
|
||||
case Operation::NextDifference:
|
||||
m_diffNavigator.goNext();
|
||||
break;
|
||||
|
||||
case Operation::FilterText:
|
||||
case Operation::FilterVectorGraphics:
|
||||
case Operation::FilterImages:
|
||||
case Operation::FilterShading:
|
||||
case Operation::FilterPageMovement:
|
||||
{
|
||||
updateFilteredResult();
|
||||
|
||||
if (ui->actionShow_Pages_with_Differences->isChecked())
|
||||
{
|
||||
updateCustomPageLayout();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::ViewDifferences:
|
||||
case Operation::ViewLeft:
|
||||
case Operation::ViewRight:
|
||||
case Operation::ViewOverlay:
|
||||
updateViewDocument();
|
||||
break;
|
||||
|
||||
case Operation::ShowPageswithDifferences:
|
||||
updateCustomPageLayout();
|
||||
break;
|
||||
|
||||
case Operation::DisplayDifferences:
|
||||
m_settings.displayDifferences = ui->actionDisplay_Differences->isChecked();
|
||||
m_pdfWidget->update();
|
||||
break;
|
||||
|
||||
case Operation::DisplayMarkers:
|
||||
m_settings.displayMarkers = ui->actionDisplay_Markers->isChecked();
|
||||
m_pdfWidget->update();
|
||||
break;
|
||||
|
||||
case Operation::SaveDifferencesToXML:
|
||||
{
|
||||
if (!m_filteredDiffResult.isSame())
|
||||
{
|
||||
QString fileName = QFileDialog::getSaveFileName(this, tr("Select PDF document"), m_settings.directory, tr("XML file (*.xml)"));
|
||||
if (!fileName.isEmpty())
|
||||
{
|
||||
QFile file(fileName);
|
||||
if (file.open(QFile::WriteOnly | QFile::Truncate))
|
||||
{
|
||||
m_filteredDiffResult.saveToXML(&file);
|
||||
file.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("File '%1' cannot be opened. %2").arg(fileName, file.errorString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::information(this, tr("Save results to XML"), tr("Displayed results are empty. Cannot save empty results."));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::CreateCompareReport:
|
||||
{
|
||||
if (m_filteredDiffResult.isSame())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
QString saveFileName = QFileDialog::getSaveFileName(this, tr("Save As"), m_settings.directory, tr("Portable Document (*.pdf);;All files (*.*)"));
|
||||
if (!saveFileName.isEmpty())
|
||||
{
|
||||
pdf::PDFDocumentBuilder builder(m_pdfWidget->getDrawWidgetProxy()->getDocument());
|
||||
m_drawInterface.drawAnnotations(m_pdfWidget->getDrawWidgetProxy()->getDocument(), &builder);
|
||||
|
||||
pdf::PDFDocument document = builder.build();
|
||||
pdf::PDFDocumentWriter writer(m_progress);
|
||||
pdf::PDFOperationResult result = writer.write(saveFileName, &document, QFile::exists(saveFileName));
|
||||
if (!result)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), result.getErrorMessage());
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void MainWindow::setViewDocument(pdf::PDFDocument* document, bool updateCustomPageLayout)
|
||||
{
|
||||
if (document != m_pdfWidget->getDrawWidgetProxy()->getDocument())
|
||||
{
|
||||
m_optionalContentActivity->deleteLater();
|
||||
m_optionalContentActivity = nullptr;
|
||||
|
||||
if (document)
|
||||
{
|
||||
m_optionalContentActivity = new pdf::PDFOptionalContentActivity(document, pdf::OCUsage::View, this);
|
||||
}
|
||||
|
||||
if (document)
|
||||
{
|
||||
pdf::PDFModifiedDocument modifiedDocument(document, m_optionalContentActivity);
|
||||
m_pdfWidget->setDocument(modifiedDocument);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pdfWidget->setDocument(pdf::PDFModifiedDocument());
|
||||
}
|
||||
}
|
||||
|
||||
if (updateCustomPageLayout)
|
||||
{
|
||||
this->updateCustomPageLayout();
|
||||
}
|
||||
}
|
||||
|
||||
ComparedDocumentMapper::Mode MainWindow::getDocumentViewMode() const
|
||||
{
|
||||
if (ui->actionView_Left->isChecked())
|
||||
{
|
||||
return ComparedDocumentMapper::Mode::Left;
|
||||
}
|
||||
|
||||
if (ui->actionView_Right->isChecked())
|
||||
{
|
||||
return ComparedDocumentMapper::Mode::Right;
|
||||
}
|
||||
|
||||
if (ui->actionView_Overlay->isChecked())
|
||||
{
|
||||
return ComparedDocumentMapper::Mode::Overlay;
|
||||
}
|
||||
|
||||
return ComparedDocumentMapper::Mode::Combined;
|
||||
}
|
||||
|
||||
void MainWindow::clear(bool clearLeftDocument, bool clearRightDocument)
|
||||
{
|
||||
setViewDocument(nullptr, true);
|
||||
|
||||
if (clearLeftDocument)
|
||||
{
|
||||
m_leftDocument = pdf::PDFDocument();
|
||||
m_settingsDockWidget->getLeftPageSelectionEdit()->clear();
|
||||
}
|
||||
|
||||
if (clearRightDocument)
|
||||
{
|
||||
m_rightDocument = pdf::PDFDocument();
|
||||
m_settingsDockWidget->getRightPageSelectionEdit()->clear();
|
||||
}
|
||||
|
||||
m_diffResult = pdf::PDFDiffResult();
|
||||
m_filteredDiffResult = pdf::PDFDiffResult();
|
||||
m_diffNavigator.update();
|
||||
|
||||
updateAll(false);
|
||||
}
|
||||
|
||||
void MainWindow::updateAll(bool resetFilters)
|
||||
{
|
||||
if (resetFilters)
|
||||
{
|
||||
ui->actionFilter_Page_Movement->setChecked(m_diffResult.hasPageMoveDifferences());
|
||||
ui->actionFilter_Text->setChecked(m_diffResult.hasTextDifferences());
|
||||
ui->actionFilter_Vector_Graphics->setChecked(m_diffResult.hasVectorGraphicsDifferences());
|
||||
ui->actionFilter_Images->setChecked(m_diffResult.hasImageDifferences());
|
||||
ui->actionFilter_Shading->setChecked(m_diffResult.hasShadingDifferences());
|
||||
}
|
||||
|
||||
updateFilteredResult();
|
||||
updateViewDocument();
|
||||
}
|
||||
|
||||
void MainWindow::updateFilteredResult()
|
||||
{
|
||||
m_filteredDiffResult = m_diffResult.filter(ui->actionFilter_Page_Movement->isChecked(),
|
||||
ui->actionFilter_Text->isChecked(),
|
||||
ui->actionFilter_Vector_Graphics->isChecked(),
|
||||
ui->actionFilter_Images->isChecked(),
|
||||
ui->actionFilter_Shading->isChecked());
|
||||
m_diffNavigator.update();
|
||||
|
||||
if (m_differencesDockWidget)
|
||||
{
|
||||
m_differencesDockWidget->update();
|
||||
}
|
||||
|
||||
updateActions();
|
||||
}
|
||||
|
||||
void MainWindow::updateViewDocument()
|
||||
{
|
||||
pdf::PDFDocument* document = nullptr;
|
||||
|
||||
switch (getDocumentViewMode())
|
||||
{
|
||||
case ComparedDocumentMapper::Mode::Left:
|
||||
document = &m_leftDocument;
|
||||
break;
|
||||
|
||||
case ComparedDocumentMapper::Mode::Right:
|
||||
document = &m_rightDocument;
|
||||
break;
|
||||
|
||||
case ComparedDocumentMapper::Mode::Combined:
|
||||
case ComparedDocumentMapper::Mode::Overlay:
|
||||
document = &m_combinedDocument;
|
||||
break;
|
||||
}
|
||||
|
||||
setViewDocument(document, true);
|
||||
}
|
||||
|
||||
void MainWindow::updateCustomPageLayout()
|
||||
{
|
||||
m_documentMapper.update(getDocumentViewMode(),
|
||||
ui->actionShow_Pages_with_Differences->isChecked(),
|
||||
m_filteredDiffResult,
|
||||
&m_leftDocument,
|
||||
&m_rightDocument,
|
||||
m_pdfWidget->getDrawWidgetProxy()->getDocument());
|
||||
|
||||
|
||||
m_pdfWidget->getDrawWidgetProxy()->setCustomPageLayout(m_documentMapper.getLayout());
|
||||
m_pdfWidget->getDrawWidgetProxy()->setPageLayout(pdf::PageLayout::Custom);
|
||||
}
|
||||
|
||||
void MainWindow::updateOverlayTransparency()
|
||||
{
|
||||
const pdf::PDFReal value = m_settingsDockWidget->getTransparencySliderValue() * 0.01;
|
||||
m_pdfWidget->getDrawWidgetProxy()->setGroupTransparency(1, true, 1.0 - value);
|
||||
m_pdfWidget->getDrawWidgetProxy()->setGroupTransparency(2, false, value);
|
||||
m_pdfWidget->update();
|
||||
}
|
||||
|
||||
std::optional<pdf::PDFDocument> MainWindow::openDocument()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Select PDF document"), m_settings.directory, tr("PDF document (*.pdf)"));
|
||||
if (fileName.isEmpty())
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto queryPassword = [this](bool* ok)
|
||||
{
|
||||
*ok = false;
|
||||
return QInputDialog::getText(this, tr("Encrypted document"), tr("Enter password to access document content"), QLineEdit::Password, QString(), ok);
|
||||
};
|
||||
|
||||
// Mark current directory as this
|
||||
QFileInfo fileInfo(fileName);
|
||||
m_settings.directory = fileInfo.dir().absolutePath();
|
||||
|
||||
// Try to open a new document
|
||||
pdf::PDFDocumentReader reader(nullptr, qMove(queryPassword), true, false);
|
||||
pdf::PDFDocument document = reader.readFromFile(fileName);
|
||||
|
||||
QString errorMessage = reader.getErrorMessage();
|
||||
pdf::PDFDocumentReader::Result result = reader.getReadingResult();
|
||||
if (result == pdf::PDFDocumentReader::Result::OK)
|
||||
{
|
||||
return document;
|
||||
}
|
||||
else if (result == pdf::PDFDocumentReader::Result::Failed)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), errorMessage);
|
||||
}
|
||||
|
||||
return pdf::PDFDocument();
|
||||
}
|
||||
|
||||
void MainWindow::onProgressStarted(pdf::ProgressStartupInfo info)
|
||||
{
|
||||
#ifdef WIN_TASKBAR_BUTTON
|
||||
m_progressTaskbarIndicator->setRange(0, 100);
|
||||
m_progressTaskbarIndicator->reset();
|
||||
m_progressTaskbarIndicator->show();
|
||||
#else
|
||||
Q_UNUSED(info);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::onProgressStep(int percentage)
|
||||
{
|
||||
if (m_isChangingProgressStep)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pdf::PDFTemporaryValueChange guard(&m_isChangingProgressStep, true);
|
||||
#ifdef WIN_TASKBAR_BUTTON
|
||||
m_progressTaskbarIndicator->setValue(percentage);
|
||||
#else
|
||||
Q_UNUSED(percentage);
|
||||
#endif
|
||||
}
|
||||
|
||||
void MainWindow::onProgressFinished()
|
||||
{
|
||||
#ifdef WIN_TASKBAR_BUTTON
|
||||
m_progressTaskbarIndicator->hide();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace pdfdocdiff
|
|
@ -1,155 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFDOCDIFF_MAINWINDOW_H
|
||||
#define PDFDOCDIFF_MAINWINDOW_H
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include "pdfdocument.h"
|
||||
#include "pdfdrawwidget.h"
|
||||
#include "pdfcms.h"
|
||||
#include "pdfoptionalcontent.h"
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QSignalMapper>
|
||||
#ifdef WIN_TASKBAR_BUTTON
|
||||
#include <QWinTaskbarButton>
|
||||
#include <QWinTaskbarProgress>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
namespace pdfdocdiff
|
||||
{
|
||||
|
||||
class SettingsDockWidget;
|
||||
class DifferencesDockWidget;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
using BaseClass = QMainWindow;
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget* parent);
|
||||
virtual ~MainWindow() override;
|
||||
|
||||
enum class Operation
|
||||
{
|
||||
OpenLeft,
|
||||
OpenRight,
|
||||
Compare,
|
||||
Close,
|
||||
GetSource,
|
||||
About,
|
||||
PreviousDifference,
|
||||
NextDifference,
|
||||
CreateCompareReport,
|
||||
FilterText,
|
||||
FilterVectorGraphics,
|
||||
FilterImages,
|
||||
FilterShading,
|
||||
FilterPageMovement,
|
||||
ViewDifferences,
|
||||
ViewLeft,
|
||||
ViewRight,
|
||||
ViewOverlay,
|
||||
ShowPageswithDifferences,
|
||||
SaveDifferencesToXML,
|
||||
DisplayDifferences,
|
||||
DisplayMarkers
|
||||
};
|
||||
|
||||
virtual void showEvent(QShowEvent* event) override;
|
||||
virtual void closeEvent(QCloseEvent* event) override;
|
||||
|
||||
private slots:
|
||||
void updateActions();
|
||||
void onSelectionChanged(size_t currentIndex);
|
||||
|
||||
private:
|
||||
void onMappedActionTriggered(int actionId);
|
||||
void onComparationFinished();
|
||||
void onColorsChanged();
|
||||
|
||||
void onProgressStarted(pdf::ProgressStartupInfo info);
|
||||
void onProgressStep(int percentage);
|
||||
void onProgressFinished();
|
||||
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
|
||||
bool canPerformOperation(Operation operation) const;
|
||||
void performOperation(Operation operation);
|
||||
|
||||
void setViewDocument(pdf::PDFDocument* document, bool updateCustomPageLayout);
|
||||
|
||||
ComparedDocumentMapper::Mode getDocumentViewMode() const;
|
||||
|
||||
/// Clears all data, and possibly documents also.
|
||||
/// View document is set to nullptr.
|
||||
/// \param clearLeftDocument Clear left document?
|
||||
/// \param clearRightDocument Clear left document?
|
||||
void clear(bool clearLeftDocument, bool clearRightDocument);
|
||||
|
||||
void updateAll(bool resetFilters);
|
||||
void updateFilteredResult();
|
||||
void updateViewDocument();
|
||||
void updateCustomPageLayout();
|
||||
void updateOverlayTransparency();
|
||||
|
||||
std::optional<pdf::PDFDocument> openDocument();
|
||||
|
||||
Ui::MainWindow* ui;
|
||||
|
||||
pdf::PDFProgress* m_progress;
|
||||
#ifdef WIN_TASKBAR_BUTTON
|
||||
QWinTaskbarButton* m_taskbarButton;
|
||||
QWinTaskbarProgress* m_progressTaskbarIndicator;
|
||||
#endif
|
||||
pdf::PDFCMSManager* m_cmsManager;
|
||||
pdf::PDFWidget* m_pdfWidget;
|
||||
SettingsDockWidget* m_settingsDockWidget;
|
||||
DifferencesDockWidget* m_differencesDockWidget;
|
||||
pdf::PDFOptionalContentActivity* m_optionalContentActivity;
|
||||
|
||||
Settings m_settings;
|
||||
QSignalMapper m_mapper;
|
||||
pdf::PDFDiff m_diff;
|
||||
bool m_isChangingProgressStep;
|
||||
bool m_dontDisplayErrorMessage;
|
||||
|
||||
pdf::PDFDocument m_leftDocument;
|
||||
pdf::PDFDocument m_rightDocument;
|
||||
pdf::PDFDocument m_combinedDocument;
|
||||
|
||||
pdf::PDFDiffResult m_diffResult;
|
||||
pdf::PDFDiffResult m_filteredDiffResult; ///< Difference result with filters applied
|
||||
pdf::PDFDiffResultNavigator m_diffNavigator; ///< Difference navigator
|
||||
ComparedDocumentMapper m_documentMapper;
|
||||
DifferencesDrawInterface m_drawInterface;
|
||||
};
|
||||
|
||||
} // namespace pdfdocdiff
|
||||
|
||||
#endif // PDFDOCDIFF_MAINWINDOW_H
|
|
@ -1,370 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>864</width>
|
||||
<height>638</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Workspace</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QGridLayout" name="gridLayout" rowstretch="0">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QFrame" name="documentFrame"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>864</width>
|
||||
<height>21</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<addaction name="actionOpen_Left"/>
|
||||
<addaction name="actionOpen_Right"/>
|
||||
<addaction name="actionClose"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuHelp">
|
||||
<property name="title">
|
||||
<string>Help</string>
|
||||
</property>
|
||||
<addaction name="actionGet_Source"/>
|
||||
<addaction name="actionAbout"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuToolbars">
|
||||
<property name="title">
|
||||
<string>Toolbars</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuCompare">
|
||||
<property name="title">
|
||||
<string>Compare</string>
|
||||
</property>
|
||||
<addaction name="actionCompare"/>
|
||||
<addaction name="actionCreate_Compare_Report"/>
|
||||
<addaction name="actionSave_Differences_to_XML"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuView">
|
||||
<property name="title">
|
||||
<string>View</string>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuView_2">
|
||||
<property name="title">
|
||||
<string>View</string>
|
||||
</property>
|
||||
<addaction name="actionView_Differences"/>
|
||||
<addaction name="actionView_Left"/>
|
||||
<addaction name="actionView_Right"/>
|
||||
<addaction name="actionView_Overlay"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuFilter">
|
||||
<property name="title">
|
||||
<string>Filter</string>
|
||||
</property>
|
||||
<addaction name="actionFilter_Text"/>
|
||||
<addaction name="actionFilter_Vector_Graphics"/>
|
||||
<addaction name="actionFilter_Images"/>
|
||||
<addaction name="actionFilter_Shading"/>
|
||||
<addaction name="actionFilter_Page_Movement"/>
|
||||
</widget>
|
||||
<addaction name="actionPrevious_Difference"/>
|
||||
<addaction name="actionNext_Difference"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="menuView_2"/>
|
||||
<addaction name="menuFilter"/>
|
||||
<addaction name="actionShow_Pages_with_Differences"/>
|
||||
<addaction name="actionSynchronize_View_with_Differences"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionDisplay_Differences"/>
|
||||
<addaction name="actionDisplay_Markers"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuCompare"/>
|
||||
<addaction name="menuToolbars"/>
|
||||
<addaction name="menuHelp"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<action name="actionGet_Source">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/get-source.svg</normaloff>:/pdfdocdiff/resources/get-source.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Get Source</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAbout">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/about.svg</normaloff>:/pdfdocdiff/resources/about.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>About...</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F1</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpen_Left">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/open-left.svg</normaloff>:/pdfdocdiff/resources/open-left.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open Left...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpen_Right">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/open-right.svg</normaloff>:/pdfdocdiff/resources/open-right.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open Right...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCompare">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/compare.svg</normaloff>:/pdfdocdiff/resources/compare.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Compare</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F5</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionClose">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/close.svg</normaloff>:/pdfdocdiff/resources/close.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+F4</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPrevious_Difference">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/prev-diff.svg</normaloff>:/pdfdocdiff/resources/prev-diff.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Previous Difference</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Shift+F6</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNext_Difference">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/next-diff.svg</normaloff>:/pdfdocdiff/resources/next-diff.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Next Difference</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F6</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCreate_Compare_Report">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/create-compare-report.svg</normaloff>:/pdfdocdiff/resources/create-compare-report.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Create Compare Report...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFilter_Text">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/filter-text.svg</normaloff>:/pdfdocdiff/resources/filter-text.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Filter Text</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFilter_Vector_Graphics">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/filter-vector-graphics.svg</normaloff>:/pdfdocdiff/resources/filter-vector-graphics.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Filter Vector Graphics</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFilter_Images">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/filter-images.svg</normaloff>:/pdfdocdiff/resources/filter-images.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Filter Images</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFilter_Shading">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/filter-shading.svg</normaloff>:/pdfdocdiff/resources/filter-shading.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Filter Shading</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFilter_Page_Movement">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/filter-page-movement.svg</normaloff>:/pdfdocdiff/resources/filter-page-movement.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Filter Page Movement</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionView_Differences">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/view-differences.svg</normaloff>:/pdfdocdiff/resources/view-differences.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>View Differences</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionView_Left">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/view-left.svg</normaloff>:/pdfdocdiff/resources/view-left.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>View Left</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionView_Right">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/view-right.svg</normaloff>:/pdfdocdiff/resources/view-right.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>View Right</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionView_Overlay">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/view-overlay.svg</normaloff>:/pdfdocdiff/resources/view-overlay.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>View Overlay</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShow_Pages_with_Differences">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/show-p-with-diff.svg</normaloff>:/pdfdocdiff/resources/show-p-with-diff.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Pages with Differences</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show Pages with Differences</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave_Differences_to_XML">
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/save-diff-to-xml.svg</normaloff>:/pdfdocdiff/resources/save-diff-to-xml.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save Differences to XML...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSynchronize_View_with_Differences">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/synchronize-view.svg</normaloff>:/pdfdocdiff/resources/synchronize-view.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Synchronize View with Differences</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDisplay_Differences">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/display-differences.svg</normaloff>:/pdfdocdiff/resources/display-differences.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Display Differences</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDisplay_Markers">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="resources.qrc">
|
||||
<normaloff>:/pdfdocdiff/resources/display-markers.svg</normaloff>:/pdfdocdiff/resources/display-markers.svg</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Display Markers</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -1,27 +0,0 @@
|
|||
<RCC>
|
||||
<qresource prefix="/pdfdocdiff">
|
||||
<file>resources/about.svg</file>
|
||||
<file>resources/close.svg</file>
|
||||
<file>resources/compare.svg</file>
|
||||
<file>resources/get-source.svg</file>
|
||||
<file>resources/open-left.svg</file>
|
||||
<file>resources/open-right.svg</file>
|
||||
<file>resources/create-compare-report.svg</file>
|
||||
<file>resources/filter-images.svg</file>
|
||||
<file>resources/filter-page-movement.svg</file>
|
||||
<file>resources/filter-shading.svg</file>
|
||||
<file>resources/filter-text.svg</file>
|
||||
<file>resources/filter-vector-graphics.svg</file>
|
||||
<file>resources/next-diff.svg</file>
|
||||
<file>resources/prev-diff.svg</file>
|
||||
<file>resources/save-diff-to-xml.svg</file>
|
||||
<file>resources/show-p-with-diff.svg</file>
|
||||
<file>resources/synchronize-view.svg</file>
|
||||
<file>resources/view-differences.svg</file>
|
||||
<file>resources/view-left.svg</file>
|
||||
<file>resources/view-overlay.svg</file>
|
||||
<file>resources/view-right.svg</file>
|
||||
<file>resources/display-differences.svg</file>
|
||||
<file>resources/display-markers.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -1,40 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SETTINGS_H
|
||||
#define SETTINGS_H
|
||||
|
||||
#include <QColor>
|
||||
|
||||
namespace pdfdocdiff
|
||||
{
|
||||
|
||||
struct Settings
|
||||
{
|
||||
QString directory;
|
||||
QColor colorPageMove = QColor(35, 145, 255);
|
||||
QColor colorAdded = QColor(125, 250, 0);
|
||||
QColor colorRemoved = QColor(255, 50, 50);
|
||||
QColor colorReplaced = QColor(255, 120, 30);
|
||||
bool displayDifferences = true;
|
||||
bool displayMarkers = true;
|
||||
};
|
||||
|
||||
} // namespace pdfdocdiff
|
||||
|
||||
|
||||
#endif // SETTINGS_H
|
|
@ -1,150 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "settingsdockwidget.h"
|
||||
#include "ui_settingsdockwidget.h"
|
||||
|
||||
#include "pdfutils.h"
|
||||
#include "pdfwidgetutils.h"
|
||||
|
||||
namespace pdfdocdiff
|
||||
{
|
||||
|
||||
SettingsDockWidget::SettingsDockWidget(Settings* settings, QWidget* parent) :
|
||||
QDockWidget(parent),
|
||||
ui(new Ui::SettingsDockWidget),
|
||||
m_settings(settings),
|
||||
m_loadingColors(false)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
auto colorNames = QColor::colorNames();
|
||||
for (QComboBox* comboBox : findChildren<QComboBox*>())
|
||||
{
|
||||
for (const QString& colorName : colorNames)
|
||||
{
|
||||
QColor color(colorName);
|
||||
comboBox->addItem(getIconForColor(color), colorName, color);
|
||||
}
|
||||
|
||||
connect(comboBox, &QComboBox::editTextChanged, this, &SettingsDockWidget::onEditColorChanged);
|
||||
}
|
||||
|
||||
connect(ui->transparencySlider, &QSlider::valueChanged, this, &SettingsDockWidget::transparencySliderChanged);
|
||||
}
|
||||
|
||||
SettingsDockWidget::~SettingsDockWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void SettingsDockWidget::setCompareTextsAsVectorGraphics(bool enabled)
|
||||
{
|
||||
ui->compareTextsAsVectorGraphicsCheckBox->setChecked(enabled);
|
||||
}
|
||||
|
||||
bool SettingsDockWidget::isCompareTextAsVectorGraphics() const
|
||||
{
|
||||
return ui->compareTextsAsVectorGraphicsCheckBox->isChecked();
|
||||
}
|
||||
|
||||
void SettingsDockWidget::setCompareTextCharactersInsteadOfWords(bool enabled)
|
||||
{
|
||||
ui->compareCharactersInsteadOfWordsCheckBox->setChecked(enabled);
|
||||
}
|
||||
|
||||
bool SettingsDockWidget::isCompareTextCharactersInsteadOfWords() const
|
||||
{
|
||||
return ui->compareCharactersInsteadOfWordsCheckBox->isChecked();
|
||||
}
|
||||
|
||||
QLineEdit* SettingsDockWidget::getLeftPageSelectionEdit() const
|
||||
{
|
||||
return ui->leftPageSelectionEdit;
|
||||
}
|
||||
|
||||
QLineEdit* SettingsDockWidget::getRightPageSelectionEdit() const
|
||||
{
|
||||
return ui->rightPageSelectionEdit;
|
||||
}
|
||||
|
||||
void SettingsDockWidget::loadColors()
|
||||
{
|
||||
pdf::PDFTemporaryValueChange guard(&m_loadingColors, true);
|
||||
|
||||
auto loadColor = [](QComboBox* comboBox, QColor color)
|
||||
{
|
||||
auto index = comboBox->findData(color);
|
||||
comboBox->setCurrentIndex(index);
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
comboBox->setCurrentText(color.name());
|
||||
}
|
||||
};
|
||||
|
||||
loadColor(ui->removeColorCombo, m_settings->colorRemoved);
|
||||
loadColor(ui->addColorCombo, m_settings->colorAdded);
|
||||
loadColor(ui->replaceColorCombo, m_settings->colorReplaced);
|
||||
loadColor(ui->moveColorCombo, m_settings->colorPageMove);
|
||||
}
|
||||
|
||||
int SettingsDockWidget::getTransparencySliderValue() const
|
||||
{
|
||||
return ui->transparencySlider->value();
|
||||
}
|
||||
|
||||
QIcon SettingsDockWidget::getIconForColor(QColor color) const
|
||||
{
|
||||
QIcon icon;
|
||||
|
||||
QSize iconSize = pdf::PDFWidgetUtils::scaleDPI(this, QSize(16, 16));
|
||||
|
||||
QPixmap pixmap(iconSize.width(), iconSize.height());
|
||||
pixmap.fill(color);
|
||||
icon.addPixmap(pixmap);
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
void SettingsDockWidget::onEditColorChanged()
|
||||
{
|
||||
if (m_loadingColors)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool isChanged = false;
|
||||
auto saveColor = [&isChanged](QComboBox* comboBox, QColor& color)
|
||||
{
|
||||
QColor oldColor = color;
|
||||
color.setNamedColor(comboBox->currentText());
|
||||
isChanged = isChanged || oldColor != color;
|
||||
};
|
||||
|
||||
saveColor(ui->removeColorCombo, m_settings->colorRemoved);
|
||||
saveColor(ui->addColorCombo, m_settings->colorAdded);
|
||||
saveColor(ui->replaceColorCombo, m_settings->colorReplaced);
|
||||
saveColor(ui->moveColorCombo, m_settings->colorPageMove);
|
||||
|
||||
if (isChanged)
|
||||
{
|
||||
Q_EMIT colorsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pdfdocdiff
|
|
@ -1,73 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef SETTINGSDOCKWIDGET_H
|
||||
#define SETTINGSDOCKWIDGET_H
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#include <QDockWidget>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class SettingsDockWidget;
|
||||
}
|
||||
|
||||
class QLineEdit;
|
||||
|
||||
namespace pdfdocdiff
|
||||
{
|
||||
|
||||
class SettingsDockWidget : public QDockWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SettingsDockWidget(Settings* settings, QWidget* parent);
|
||||
virtual ~SettingsDockWidget() override;
|
||||
|
||||
void setCompareTextsAsVectorGraphics(bool enabled);
|
||||
bool isCompareTextAsVectorGraphics() const;
|
||||
|
||||
void setCompareTextCharactersInsteadOfWords(bool enabled);
|
||||
bool isCompareTextCharactersInsteadOfWords() const;
|
||||
|
||||
QLineEdit* getLeftPageSelectionEdit() const;
|
||||
QLineEdit* getRightPageSelectionEdit() const;
|
||||
|
||||
void loadColors();
|
||||
void saveColors();
|
||||
|
||||
int getTransparencySliderValue() const;
|
||||
|
||||
signals:
|
||||
void colorsChanged();
|
||||
void transparencySliderChanged(int value);
|
||||
|
||||
private:
|
||||
QIcon getIconForColor(QColor color) const;
|
||||
|
||||
void onEditColorChanged();
|
||||
|
||||
Ui::SettingsDockWidget* ui;
|
||||
Settings* m_settings;
|
||||
bool m_loadingColors;
|
||||
};
|
||||
|
||||
} // namespace pdfdocdiff
|
||||
|
||||
#endif // SETTINGSDOCKWIDGET_H
|
|
@ -1,563 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "utils.h"
|
||||
#include "pdfutils.h"
|
||||
#include "pdfwidgetutils.h"
|
||||
#include "pdfpainterutils.h"
|
||||
#include "pdfdocumentbuilder.h"
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
namespace pdfdocdiff
|
||||
{
|
||||
|
||||
void ComparedDocumentMapper::update(ComparedDocumentMapper::Mode mode,
|
||||
bool filterDifferences,
|
||||
const pdf::PDFDiffResult& diff,
|
||||
const pdf::PDFDocument* leftDocument,
|
||||
const pdf::PDFDocument* rightDocument,
|
||||
const pdf::PDFDocument* currentDocument)
|
||||
{
|
||||
m_layout.clear();
|
||||
|
||||
m_leftPageIndices.clear();
|
||||
m_rightPageIndices.clear();
|
||||
|
||||
m_allLeft = false;
|
||||
m_allRight = false;
|
||||
|
||||
if (!leftDocument || !rightDocument || !currentDocument)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Jakub Melka
|
||||
pdf::PDFDiffResult::PageSequence pageSequence = diff.getPageSequence();
|
||||
const bool isEmpty = pageSequence.empty();
|
||||
|
||||
if (filterDifferences)
|
||||
{
|
||||
pdf::PDFDiffResult::PageSequence filteredPageSequence;
|
||||
|
||||
std::vector<pdf::PDFInteger> leftPageIndices = diff.getChangedLeftPageIndices();
|
||||
std::vector<pdf::PDFInteger> rightPageIndices = diff.getChangedRightPageIndices();
|
||||
|
||||
for (const pdf::PDFDiffResult::PageSequenceItem& item : pageSequence)
|
||||
{
|
||||
const bool isLeftModified = std::binary_search(leftPageIndices.cbegin(), leftPageIndices.cend(), item.leftPage);
|
||||
const bool isRightModified = std::binary_search(rightPageIndices.cbegin(), rightPageIndices.cend(), item.rightPage);
|
||||
|
||||
if (isLeftModified || isRightModified)
|
||||
{
|
||||
filteredPageSequence.push_back(item);
|
||||
}
|
||||
}
|
||||
|
||||
pageSequence = std::move(filteredPageSequence);
|
||||
}
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case ComparedDocumentMapper::Mode::Left:
|
||||
{
|
||||
Q_ASSERT(leftDocument == currentDocument);
|
||||
|
||||
m_allLeft = true;
|
||||
double yPos = 0.0;
|
||||
const pdf::PDFCatalog* catalog = leftDocument->getCatalog();
|
||||
|
||||
if (isEmpty)
|
||||
{
|
||||
// Just copy all pages
|
||||
const size_t pageCount = catalog->getPageCount();
|
||||
for (size_t i = 0; i < pageCount; ++i)
|
||||
{
|
||||
QSizeF pageSize = catalog->getPage(i)->getRotatedMediaBoxMM().size();
|
||||
QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||
m_layout.emplace_back(0, i, -1, rect);
|
||||
yPos += pageSize.height() + 5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const pdf::PDFDiffResult::PageSequenceItem& item : pageSequence)
|
||||
{
|
||||
if (item.leftPage == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QSizeF pageSize = catalog->getPage(item.leftPage)->getRotatedMediaBoxMM().size();
|
||||
QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||
m_layout.emplace_back(0, item.leftPage, -1, rect);
|
||||
yPos += pageSize.height() + 5;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ComparedDocumentMapper::Mode::Right:
|
||||
{
|
||||
Q_ASSERT(rightDocument == currentDocument);
|
||||
|
||||
m_allRight = true;
|
||||
double yPos = 0.0;
|
||||
const pdf::PDFCatalog* catalog = rightDocument->getCatalog();
|
||||
|
||||
if (isEmpty)
|
||||
{
|
||||
// Just copy all pages
|
||||
const size_t pageCount = catalog->getPageCount();
|
||||
for (size_t i = 0; i < pageCount; ++i)
|
||||
{
|
||||
QSizeF pageSize = catalog->getPage(i)->getRotatedMediaBoxMM().size();
|
||||
QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||
m_layout.emplace_back(0, i, -1, rect);
|
||||
yPos += pageSize.height() + 5;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const pdf::PDFDiffResult::PageSequenceItem& item : pageSequence)
|
||||
{
|
||||
if (item.rightPage == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QSizeF pageSize = catalog->getPage(item.rightPage)->getRotatedMediaBoxMM().size();
|
||||
QRectF rect(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||
m_layout.emplace_back(0, item.rightPage, -1, rect);
|
||||
yPos += pageSize.height() + 5;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ComparedDocumentMapper::Mode::Combined:
|
||||
case ComparedDocumentMapper::Mode::Overlay:
|
||||
{
|
||||
double yPos = 0.0;
|
||||
const pdf::PDFCatalog* catalog = currentDocument->getCatalog();
|
||||
pdf::PDFInteger offset = leftDocument->getCatalog()->getPageCount();
|
||||
|
||||
for (const pdf::PDFDiffResult::PageSequenceItem& item : pageSequence)
|
||||
{
|
||||
double yAdvance = 0.0;
|
||||
|
||||
if (item.leftPage != -1)
|
||||
{
|
||||
QSizeF pageSize = catalog->getPage(item.leftPage)->getRotatedMediaBoxMM().size();
|
||||
QRectF rect;
|
||||
pdf::PDFInteger groupIndex = -1;
|
||||
if (mode == ComparedDocumentMapper::Mode::Combined)
|
||||
{
|
||||
rect = QRectF(-pageSize.width() - 5, yPos, pageSize.width(), pageSize.height());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.rightPage != -1)
|
||||
{
|
||||
groupIndex = 1;
|
||||
}
|
||||
rect = QRectF(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||
}
|
||||
m_layout.emplace_back(0, item.leftPage, groupIndex, rect);
|
||||
yAdvance = pageSize.height() + 5;
|
||||
m_leftPageIndices[item.leftPage] = item.leftPage;
|
||||
}
|
||||
|
||||
if (item.rightPage != -1)
|
||||
{
|
||||
pdf::PDFInteger rightPageIndex = item.rightPage + offset;
|
||||
QSizeF pageSize = catalog->getPage(rightPageIndex)->getRotatedMediaBoxMM().size();
|
||||
QRectF rect;
|
||||
pdf::PDFInteger groupIndex = -1;
|
||||
if (mode == ComparedDocumentMapper::Mode::Combined)
|
||||
{
|
||||
rect = QRectF(5, yPos, pageSize.width(), pageSize.height());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item.leftPage != -1)
|
||||
{
|
||||
groupIndex = 2;
|
||||
}
|
||||
rect = QRectF(-pageSize.width() * 0.5, yPos, pageSize.width(), pageSize.height());
|
||||
}
|
||||
m_layout.emplace_back(0, rightPageIndex, groupIndex, rect);
|
||||
yAdvance = qMax(yAdvance, pageSize.height() + 5);
|
||||
m_rightPageIndices[rightPageIndex] = item.rightPage;
|
||||
}
|
||||
|
||||
yPos += yAdvance;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pdf::PDFInteger ComparedDocumentMapper::getLeftPageIndex(pdf::PDFInteger pageIndex) const
|
||||
{
|
||||
if (m_allLeft)
|
||||
{
|
||||
return pageIndex;
|
||||
}
|
||||
|
||||
auto it = m_leftPageIndices.find(pageIndex);
|
||||
if (it != m_leftPageIndices.cend())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
pdf::PDFInteger ComparedDocumentMapper::getRightPageIndex(pdf::PDFInteger pageIndex) const
|
||||
{
|
||||
if (m_allRight)
|
||||
{
|
||||
return pageIndex;
|
||||
}
|
||||
|
||||
auto it = m_rightPageIndices.find(pageIndex);
|
||||
if (it != m_rightPageIndices.cend())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
pdf::PDFInteger ComparedDocumentMapper::getPageIndexFromLeftPageIndex(pdf::PDFInteger leftPageIndex) const
|
||||
{
|
||||
if (m_allLeft)
|
||||
{
|
||||
return leftPageIndex;
|
||||
}
|
||||
|
||||
for (const auto& indexItem : m_leftPageIndices)
|
||||
{
|
||||
if (indexItem.second == leftPageIndex)
|
||||
{
|
||||
return indexItem.first;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
pdf::PDFInteger ComparedDocumentMapper::getPageIndexFromRightPageIndex(pdf::PDFInteger rightPageIndex) const
|
||||
{
|
||||
if (m_allRight)
|
||||
{
|
||||
return rightPageIndex;
|
||||
}
|
||||
|
||||
for (const auto& indexItem : m_rightPageIndices)
|
||||
{
|
||||
if (indexItem.second == rightPageIndex)
|
||||
{
|
||||
return indexItem.first;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
DifferencesDrawInterface::DifferencesDrawInterface(const Settings* settings,
|
||||
const ComparedDocumentMapper* mapper,
|
||||
const pdf::PDFDiffResult* diffResult) :
|
||||
m_settings(settings),
|
||||
m_mapper(mapper),
|
||||
m_diffResult(diffResult)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void DifferencesDrawInterface::drawPage(QPainter* painter,
|
||||
pdf::PDFInteger pageIndex,
|
||||
const pdf::PDFPrecompiledPage* compiledPage,
|
||||
pdf::PDFTextLayoutGetter& layoutGetter,
|
||||
const QTransform& pagePointToDevicePointMatrix,
|
||||
QList<pdf::PDFRenderError>& errors) const
|
||||
{
|
||||
Q_UNUSED(compiledPage);
|
||||
Q_UNUSED(layoutGetter);
|
||||
Q_UNUSED(errors);
|
||||
|
||||
if (!m_settings->displayDifferences)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t differencesCount = m_diffResult->getDifferencesCount();
|
||||
const pdf::PDFInteger leftPageIndex = m_mapper->getLeftPageIndex(pageIndex);
|
||||
const pdf::PDFInteger rightPageIndex = m_mapper->getRightPageIndex(pageIndex);
|
||||
|
||||
std::optional<size_t> pageMoveIndex;
|
||||
|
||||
if (leftPageIndex != -1)
|
||||
{
|
||||
for (size_t i = 0; i < differencesCount; ++i)
|
||||
{
|
||||
auto leftRectangles = m_diffResult->getLeftRectangles(i);
|
||||
for (auto it = leftRectangles.first; it != leftRectangles.second; ++it)
|
||||
{
|
||||
const auto& item = *it;
|
||||
if (item.first == leftPageIndex)
|
||||
{
|
||||
QColor color = getColorForIndex(i);
|
||||
drawRectangle(painter, pagePointToDevicePointMatrix, item.second, color);
|
||||
drawMarker(painter, pagePointToDevicePointMatrix, item.second, color, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_diffResult->isPageMoveAddRemoveDifference(i) && m_diffResult->getLeftPage(i) == leftPageIndex)
|
||||
{
|
||||
pageMoveIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rightPageIndex != -1)
|
||||
{
|
||||
for (size_t i = 0; i < differencesCount; ++i)
|
||||
{
|
||||
auto rightRectangles = m_diffResult->getRightRectangles(i);
|
||||
for (auto it = rightRectangles.first; it != rightRectangles.second; ++it)
|
||||
{
|
||||
const auto& item = *it;
|
||||
if (item.first == rightPageIndex)
|
||||
{
|
||||
QColor color = getColorForIndex(i);
|
||||
drawRectangle(painter, pagePointToDevicePointMatrix, item.second, color);
|
||||
drawMarker(painter, pagePointToDevicePointMatrix, item.second, color, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_diffResult->isPageMoveAddRemoveDifference(i) && m_diffResult->getRightPage(i) == rightPageIndex)
|
||||
{
|
||||
pageMoveIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pageMoveIndex)
|
||||
{
|
||||
QString text;
|
||||
|
||||
switch (m_diffResult->getType(*pageMoveIndex))
|
||||
{
|
||||
case pdf::PDFDiffResult::Type::PageAdded:
|
||||
text = " + ";
|
||||
break;
|
||||
|
||||
case pdf::PDFDiffResult::Type::PageRemoved:
|
||||
text = " - ";
|
||||
break;
|
||||
|
||||
case pdf::PDFDiffResult::Type::PageMoved:
|
||||
text = QString("%1🠖%2").arg(m_diffResult->getLeftPage(*pageMoveIndex) + 1).arg(m_diffResult->getRightPage(*pageMoveIndex) + 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
QColor color = getColorForIndex(*pageMoveIndex);
|
||||
QPointF targetPoint = pagePointToDevicePointMatrix.map(QPointF(5, 5));
|
||||
pdf::PDFPainterHelper::drawBubble(painter, targetPoint.toPoint(), color, text, Qt::AlignRight | Qt::AlignTop);
|
||||
}
|
||||
}
|
||||
|
||||
QColor DifferencesDrawInterface::getColorForIndex(size_t index) const
|
||||
{
|
||||
QColor color;
|
||||
|
||||
const size_t resultIndex = index;
|
||||
|
||||
if (m_diffResult->isReplaceDifference(resultIndex))
|
||||
{
|
||||
color = m_settings->colorReplaced;
|
||||
}
|
||||
else if (m_diffResult->isRemoveDifference(resultIndex))
|
||||
{
|
||||
color = m_settings->colorRemoved;
|
||||
}
|
||||
else if (m_diffResult->isAddDifference(resultIndex))
|
||||
{
|
||||
color = m_settings->colorAdded;
|
||||
}
|
||||
else if (m_diffResult->isPageMoveDifference(resultIndex))
|
||||
{
|
||||
color = m_settings->colorPageMove;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
void DifferencesDrawInterface::drawPostRendering(QPainter* painter, QRect rect) const
|
||||
{
|
||||
Q_UNUSED(painter);
|
||||
Q_UNUSED(rect);
|
||||
}
|
||||
|
||||
void DifferencesDrawInterface::drawAnnotations(const pdf::PDFDocument* document,
|
||||
pdf::PDFDocumentBuilder* builder)
|
||||
{
|
||||
pdf::PDFInteger pageCount = document->getCatalog()->getPageCount();
|
||||
|
||||
QString title = pdf::PDFSysUtils::getUserName();
|
||||
QString subject = tr("Difference");
|
||||
|
||||
for (pdf::PDFInteger pageIndex = 0; pageIndex < pageCount; ++pageIndex)
|
||||
{
|
||||
const size_t differencesCount = m_diffResult->getDifferencesCount();
|
||||
const pdf::PDFInteger leftPageIndex = m_mapper->getLeftPageIndex(pageIndex);
|
||||
const pdf::PDFInteger rightPageIndex = m_mapper->getRightPageIndex(pageIndex);
|
||||
|
||||
const pdf::PDFPage* page = document->getCatalog()->getPage(pageIndex);
|
||||
pdf::PDFObjectReference reference = page->getPageReference();
|
||||
|
||||
if (leftPageIndex != -1)
|
||||
{
|
||||
for (size_t i = 0; i < differencesCount; ++i)
|
||||
{
|
||||
auto leftRectangles = m_diffResult->getLeftRectangles(i);
|
||||
for (auto it = leftRectangles.first; it != leftRectangles.second; ++it)
|
||||
{
|
||||
const auto& item = *it;
|
||||
if (item.first == leftPageIndex)
|
||||
{
|
||||
QColor color = getColorForIndex(i);
|
||||
const QRectF& rect = item.second;
|
||||
QPolygonF polygon;
|
||||
polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft();
|
||||
pdf::PDFObjectReference annotation = builder->createAnnotationPolygon(reference, polygon, 1.0, color, color, title, subject, m_diffResult->getMessage(i));
|
||||
builder->setAnnotationOpacity(annotation, 0.3);
|
||||
builder->updateAnnotationAppearanceStreams(annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rightPageIndex != -1)
|
||||
{
|
||||
for (size_t i = 0; i < differencesCount; ++i)
|
||||
{
|
||||
auto rightRectangles = m_diffResult->getRightRectangles(i);
|
||||
for (auto it = rightRectangles.first; it != rightRectangles.second; ++it)
|
||||
{
|
||||
const auto& item = *it;
|
||||
if (item.first == rightPageIndex)
|
||||
{
|
||||
QColor color = getColorForIndex(i);
|
||||
const QRectF& rect = item.second;
|
||||
QPolygonF polygon;
|
||||
polygon << rect.topLeft() << rect.topRight() << rect.bottomRight() << rect.bottomLeft();
|
||||
pdf::PDFObjectReference annotation = builder->createAnnotationPolygon(reference, polygon, 1.0, color, color, title, subject, m_diffResult->getMessage(i));
|
||||
builder->setAnnotationOpacity(annotation, 0.3);
|
||||
builder->updateAnnotationAppearanceStreams(annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DifferencesDrawInterface::drawRectangle(QPainter* painter,
|
||||
const QTransform& pagePointToDevicePointMatrix,
|
||||
const QRectF& rect,
|
||||
QColor color) const
|
||||
{
|
||||
color.setAlphaF(0.5);
|
||||
|
||||
QRectF resultRect = pagePointToDevicePointMatrix.mapRect(rect);
|
||||
painter->fillRect(resultRect, color);
|
||||
}
|
||||
|
||||
void DifferencesDrawInterface::drawMarker(QPainter* painter,
|
||||
const QTransform& pagePointToDevicePointMatrix,
|
||||
const QRectF& rect,
|
||||
QColor color,
|
||||
bool isLeft) const
|
||||
{
|
||||
if (!m_settings->displayMarkers)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
pdf::PDFPainterStateGuard guard(painter);
|
||||
QRectF deviceRect = pagePointToDevicePointMatrix.mapRect(rect);
|
||||
|
||||
QPointF snapPoint;
|
||||
QPointF markPoint;
|
||||
|
||||
if (isLeft)
|
||||
{
|
||||
snapPoint.ry() = deviceRect.center().y();
|
||||
snapPoint.rx() = deviceRect.left();
|
||||
markPoint = snapPoint;
|
||||
markPoint.rx() = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
snapPoint.ry() = deviceRect.center().y();
|
||||
snapPoint.rx() = deviceRect.right();
|
||||
markPoint = snapPoint;
|
||||
markPoint.rx() = painter->device()->width();
|
||||
}
|
||||
|
||||
const qreal lineWidthF = pdf::PDFWidgetUtils::scaleDPI_y(painter->device(), 2);
|
||||
|
||||
QPen pen(Qt::DotLine);
|
||||
pen.setColor(color);
|
||||
pen.setWidthF(lineWidthF);
|
||||
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->setPen(pen);
|
||||
painter->drawLine(snapPoint, markPoint);
|
||||
|
||||
const qreal markSizeX = pdf::PDFWidgetUtils::scaleDPI_x(painter->device(), 10);
|
||||
const qreal markSizeY = pdf::PDFWidgetUtils::scaleDPI_y(painter->device(), 10);
|
||||
|
||||
QPointF ptc = markPoint;
|
||||
QPointF ptTop = ptc;
|
||||
QPointF ptBottom = ptc;
|
||||
|
||||
ptTop.ry() -= markSizeY;
|
||||
ptBottom.ry() += markSizeY;
|
||||
ptc.rx() += isLeft ? markSizeX : -markSizeX;
|
||||
|
||||
std::array points = { ptTop, ptc, ptBottom };
|
||||
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(QBrush(color));
|
||||
painter->drawConvexPolygon(points.data(), int(points.size()));
|
||||
}
|
||||
|
||||
} // namespace pdfdocdiff
|
|
@ -1,128 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include "settings.h"
|
||||
#include "pdfdiff.h"
|
||||
#include "pdfdrawspacecontroller.h"
|
||||
#include "pdfdocumentdrawinterface.h"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
class PDFDocumentBuilder;
|
||||
} // namespace pdf
|
||||
|
||||
namespace pdfdocdiff
|
||||
{
|
||||
|
||||
class ComparedDocumentMapper
|
||||
{
|
||||
public:
|
||||
|
||||
enum class Mode
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
Combined,
|
||||
Overlay
|
||||
};
|
||||
|
||||
void update(Mode mode,
|
||||
bool filterDifferences,
|
||||
const pdf::PDFDiffResult& diff,
|
||||
const pdf::PDFDocument* leftDocument,
|
||||
const pdf::PDFDocument* rightDocument,
|
||||
const pdf::PDFDocument* currentDocument);
|
||||
|
||||
const pdf::PDFDrawSpaceController::LayoutItems& getLayout() const { return m_layout; }
|
||||
void setPageSequence(const pdf::PDFDiffResult::PageSequence& sequence) { m_pageSequence = sequence; }
|
||||
|
||||
/// Returns left page index (that means page index in left document),
|
||||
/// if it doesn't exist, -1 is returned.
|
||||
/// \param pageIndex Actual page index
|
||||
pdf::PDFInteger getLeftPageIndex(pdf::PDFInteger pageIndex) const;
|
||||
|
||||
/// Returns right page index (that means page index in right document),
|
||||
/// if it doesn't exist, -1 is returned.
|
||||
/// \param pageIndex Actual page index
|
||||
pdf::PDFInteger getRightPageIndex(pdf::PDFInteger pageIndex) const;
|
||||
|
||||
/// Returns actual page index from left page index, or -1.
|
||||
/// \param leftPageIndex Left page index
|
||||
pdf::PDFInteger getPageIndexFromLeftPageIndex(pdf::PDFInteger leftPageIndex) const;
|
||||
|
||||
/// Returns actual page index from right page index, or -1.
|
||||
/// \param rightPageIndex Right page index
|
||||
pdf::PDFInteger getPageIndexFromRightPageIndex(pdf::PDFInteger rightPageIndex) const;
|
||||
|
||||
private:
|
||||
pdf::PDFDrawSpaceController::LayoutItems m_layout;
|
||||
bool m_allLeft = false;
|
||||
bool m_allRight = false;
|
||||
std::map<pdf::PDFInteger, pdf::PDFInteger> m_leftPageIndices;
|
||||
std::map<pdf::PDFInteger, pdf::PDFInteger> m_rightPageIndices;
|
||||
pdf::PDFDiffResult::PageSequence m_pageSequence;
|
||||
};
|
||||
|
||||
class DifferencesDrawInterface : public pdf::IDocumentDrawInterface
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(pdfdocdiff::DifferencesDrawInterface)
|
||||
|
||||
public:
|
||||
explicit DifferencesDrawInterface(const Settings* settings,
|
||||
const ComparedDocumentMapper* mapper,
|
||||
const pdf::PDFDiffResult* diffResult);
|
||||
|
||||
virtual void drawPage(QPainter* painter, pdf::PDFInteger pageIndex,
|
||||
const pdf::PDFPrecompiledPage* compiledPage,
|
||||
pdf::PDFTextLayoutGetter& layoutGetter,
|
||||
const QTransform& pagePointToDevicePointMatrix,
|
||||
QList<pdf::PDFRenderError>& errors) const override;
|
||||
|
||||
virtual void drawPostRendering(QPainter* painter, QRect rect) const override;
|
||||
|
||||
/// Draw annotations for differences
|
||||
/// \param document Document
|
||||
/// \param builder Builder
|
||||
void drawAnnotations(const pdf::PDFDocument* document, pdf::PDFDocumentBuilder* builder);
|
||||
|
||||
private:
|
||||
void drawRectangle(QPainter* painter,
|
||||
const QTransform& pagePointToDevicePointMatrix,
|
||||
const QRectF& rect,
|
||||
QColor color) const;
|
||||
|
||||
void drawMarker(QPainter* painter,
|
||||
const QTransform& pagePointToDevicePointMatrix,
|
||||
const QRectF& rect,
|
||||
QColor color,
|
||||
bool isLeft) const;
|
||||
|
||||
QColor getColorForIndex(size_t index) const;
|
||||
|
||||
const Settings* m_settings;
|
||||
const ComparedDocumentMapper* m_mapper;
|
||||
const pdf::PDFDiffResult* m_diffResult;
|
||||
};
|
||||
|
||||
} // namespace pdfdocdiff
|
||||
|
||||
#endif // UTILS_H
|
|
@ -1,41 +0,0 @@
|
|||
# Copyright (C) 2022 Jakub Melka
|
||||
#
|
||||
# This file is part of PDF4QT.
|
||||
#
|
||||
# PDF4QT is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# with the written consent of the copyright owner, any later version.
|
||||
#
|
||||
# PDF4QT is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
add_executable(Pdf4QtDocPageOrganizer
|
||||
aboutdialog.cpp
|
||||
assembleoutputsettingsdialog.cpp
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
pageitemdelegate.cpp
|
||||
pageitemmodel.cpp
|
||||
selectbookmarkstoregroupdialog.cpp
|
||||
aboutdialog.ui
|
||||
assembleoutputsettingsdialog.ui
|
||||
mainwindow.ui
|
||||
selectbookmarkstoregroupdialog.ui
|
||||
resources.qrc
|
||||
icon.rc
|
||||
)
|
||||
|
||||
target_link_libraries(Pdf4QtDocPageOrganizer PRIVATE Pdf4QtLib Qt6::Core Qt6::Gui Qt6::Widgets)
|
||||
|
||||
set_target_properties(Pdf4QtDocPageOrganizer PROPERTIES
|
||||
WIN32_EXECUTABLE ON
|
||||
MACOSX_BUNDLE ON
|
||||
)
|
||||
|
||||
install(TARGETS Pdf4QtDocPageOrganizer)
|
|
@ -1,64 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "aboutdialog.h"
|
||||
#include "ui_aboutdialog.h"
|
||||
|
||||
#include "pdfutils.h"
|
||||
#include "pdfwidgetutils.h"
|
||||
|
||||
namespace pdfdocpage
|
||||
{
|
||||
|
||||
PDFAboutDialog::PDFAboutDialog(QWidget* parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::PDFAboutDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
QString html = ui->copyrightLabel->text();
|
||||
html.replace("PdfForQtViewer", QString("%1 %2").arg(QApplication::applicationDisplayName(), QApplication::applicationVersion()));
|
||||
ui->copyrightLabel->setText(html);
|
||||
|
||||
std::vector<pdf::PDFDependentLibraryInfo> infos = pdf::PDFDependentLibraryInfo::getLibraryInfo();
|
||||
|
||||
ui->tableWidget->setColumnCount(4);
|
||||
ui->tableWidget->setRowCount(static_cast<int>(infos.size()));
|
||||
ui->tableWidget->setHorizontalHeaderLabels(QStringList() << tr("Library") << tr("Version") << tr("License") << tr("URL"));
|
||||
ui->tableWidget->setEditTriggers(QTableWidget::NoEditTriggers);
|
||||
ui->tableWidget->setSelectionMode(QTableView::SingleSelection);
|
||||
ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
|
||||
for (int i = 0; i < infos.size(); ++i)
|
||||
{
|
||||
const pdf::PDFDependentLibraryInfo& info = infos[i];
|
||||
ui->tableWidget->setItem(i, 0, new QTableWidgetItem(info.library));
|
||||
ui->tableWidget->setItem(i, 1, new QTableWidgetItem(info.version));
|
||||
ui->tableWidget->setItem(i, 2, new QTableWidgetItem(info.license));
|
||||
ui->tableWidget->setItem(i, 3, new QTableWidgetItem(info.url));
|
||||
}
|
||||
|
||||
pdf::PDFWidgetUtils::scaleWidget(this, QSize(750, 600));
|
||||
pdf::PDFWidgetUtils::style(this);
|
||||
}
|
||||
|
||||
PDFAboutDialog::~PDFAboutDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
} // namespace pdfdocpage
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFDOCPAGEORGANIZER_PDFABOUTDIALOG_H
|
||||
#define PDFDOCPAGEORGANIZER_PDFABOUTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class PDFAboutDialog;
|
||||
}
|
||||
|
||||
namespace pdfdocpage
|
||||
{
|
||||
|
||||
class PDFAboutDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PDFAboutDialog(QWidget* parent);
|
||||
virtual ~PDFAboutDialog() override;
|
||||
|
||||
private:
|
||||
Ui::PDFAboutDialog* ui;
|
||||
};
|
||||
|
||||
} // namespace pdfdocpage
|
||||
|
||||
#endif // PDFDOCPAGEORGANIZER_PDFABOUTDIALOG_H
|
|
@ -1,269 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PDFAboutDialog</class>
|
||||
<widget class="QDialog" name="PDFAboutDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>900</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>900</width>
|
||||
<height>600</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>About</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="copyrightLabel">
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-weight:600;">PdfForQtViewer</span></p><p>Copyright 2018-2021 Jakub Melka. All rights reserved.</p><p>THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</p></body></html></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="textEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="html">
|
||||
<string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
|
||||
<html><head><meta name="qrichtext" content="1" /><style type="text/css">
|
||||
p, li { white-space: pre-wrap; }
|
||||
</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.875pt; font-weight:400; font-style:normal;">
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> GNU LESSER GENERAL PUBLIC LICENSE</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Version 3, 29 June 2007</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Copyright (C) 2007 Free Software Foundation, Inc. &lt;https://fsf.org/&gt;</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Everyone is permitted to copy and distribute verbatim copies</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> of this license document, but changing it is not allowed.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> This version of the GNU Lesser General Public License incorporates</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the terms and conditions of version 3 of the GNU General Public</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">License, supplemented by the additional permissions listed below.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 0. Additional Definitions.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> As used herein, &quot;this License&quot; refers to version 3 of the GNU Lesser</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">General Public License, and the &quot;GNU GPL&quot; refers to version 3 of the GNU</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">General Public License.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> &quot;The Library&quot; refers to a covered work governed by this License,</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">other than an Application or a Combined Work as defined below.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> An &quot;Application&quot; is any work that makes use of an interface provided</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">by the Library, but which is not otherwise based on the Library.</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Defining a subclass of a class defined by the Library is deemed a mode</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">of using an interface provided by the Library.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> A &quot;Combined Work&quot; is a work produced by combining or linking an</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Application with the Library. The particular version of the Library</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">with which the Combined Work was made is also called the &quot;Linked</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Version&quot;.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The &quot;Minimal Corresponding Source&quot; for a Combined Work means the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Corresponding Source for the Combined Work, excluding any source code</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">for portions of the Combined Work that, considered in isolation, are</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">based on the Application, and not on the Linked Version.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The &quot;Corresponding Application Code&quot; for a Combined Work means the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">object code and/or source code for the Application, including any data</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">and utility programs needed for reproducing the Combined Work from the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Application, but excluding the System Libraries of the Combined Work.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 1. Exception to Section 3 of the GNU GPL.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> You may convey a covered work under sections 3 and 4 of this License</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">without being bound by section 3 of the GNU GPL.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 2. Conveying Modified Versions.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> If you modify a copy of the Library, and, in your modifications, a</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">facility refers to a function or data to be supplied by an Application</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">that uses the facility (other than as an argument passed when the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">facility is invoked), then you may convey a copy of the modified</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">version:</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> a) under this License, provided that you make a good faith effort to</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> ensure that, in the event an Application does not supply the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> function or data, the facility still operates, and performs</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> whatever part of its purpose remains meaningful, or</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> b) under the GNU GPL, with none of the additional permissions of</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> this License applicable to that copy.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 3. Object Code Incorporating Material from Library Header Files.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The object code form of an Application may incorporate material from</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">a header file that is part of the Library. You may convey such object</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">code under terms of your choice, provided that, if the incorporated</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">material is not limited to numerical parameters, data structure</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">layouts and accessors, or small macros, inline functions and templates</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">(ten or fewer lines in length), you do both of the following:</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> a) Give prominent notice with each copy of the object code that the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Library is used in it and that the Library and its use are</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> covered by this License.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> b) Accompany the object code with a copy of the GNU GPL and this license</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> document.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 4. Combined Works.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> You may convey a Combined Work under terms of your choice that,</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">taken together, effectively do not restrict modification of the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">portions of the Library contained in the Combined Work and reverse</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">engineering for debugging such modifications, if you also do each of</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">the following:</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> a) Give prominent notice with each copy of the Combined Work that</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> the Library is used in it and that the Library and its use are</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> covered by this License.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> b) Accompany the Combined Work with a copy of the GNU GPL and this license</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> document.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> c) For a Combined Work that displays copyright notices during</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> execution, include the copyright notice for the Library among</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> these notices, as well as a reference directing the user to the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> copies of the GNU GPL and this license document.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> d) Do one of the following:</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 0) Convey the Minimal Corresponding Source under the terms of this</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> License, and the Corresponding Application Code in a form</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> suitable for, and under terms that permit, the user to</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> recombine or relink the Application with a modified version of</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> the Linked Version to produce a modified Combined Work, in the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> manner specified by section 6 of the GNU GPL for conveying</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Corresponding Source.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 1) Use a suitable shared library mechanism for linking with the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Library. A suitable mechanism is one that (a) uses at run time</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> a copy of the Library already present on the user's computer</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> system, and (b) will operate properly with a modified version</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> of the Library that is interface-compatible with the Linked</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Version.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> e) Provide Installation Information, but only if you would otherwise</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> be required to provide such information under section 6 of the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> GNU GPL, and only to the extent that such information is</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> necessary to install and execute a modified version of the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Combined Work produced by recombining or relinking the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Application with a modified version of the Linked Version. (If</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> you use option 4d0, the Installation Information must accompany</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> the Minimal Corresponding Source and Corresponding Application</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Code. If you use option 4d1, you must provide the Installation</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Information in the manner specified by section 6 of the GNU GPL</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> for conveying Corresponding Source.)</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 5. Combined Libraries.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> You may place library facilities that are a work based on the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Library side by side in a single library together with other library</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">facilities that are not Applications and are not covered by this</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">License, and convey such a combined library under terms of your</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">choice, if you do both of the following:</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> a) Accompany the combined library with a copy of the same work based</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> on the Library, uncombined with any other library facilities,</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> conveyed under the terms of this License.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> b) Give prominent notice with the combined library that part of it</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> is a work based on the Library, and explaining where to find the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> accompanying uncombined form of the same work.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> 6. Revised Versions of the GNU Lesser General Public License.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> The Free Software Foundation may publish revised and/or new versions</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">of the GNU Lesser General Public License from time to time. Such new</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">versions will be similar in spirit to the present version, but may</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">differ in detail to address new problems or concerns.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Each version is given a distinguishing version number. If the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Library as you received it specifies that a certain numbered version</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">of the GNU Lesser General Public License &quot;or any later version&quot;</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">applies to it, you have the option of following the terms and</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">conditions either of that published version or of any later version</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">published by the Free Software Foundation. If the Library as you</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">received it does not specify a version number of the GNU Lesser</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">General Public License, you may choose any version of the GNU Lesser</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">General Public License ever published by the Free Software Foundation.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> If the Library as you received it specifies that a proxy can decide</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">whether future versions of the GNU Lesser General Public License shall</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">apply, that proxy's public statement of acceptance of any version is</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">permanent authorization for you to choose that version for the</p>
|
||||
<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Library.</p>
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="usedLibrariesLabel">
|
||||
<property name="text">
|
||||
<string>Used libraries</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="tableWidget"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>PDFAboutDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>PDFAboutDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -1,78 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "assembleoutputsettingsdialog.h"
|
||||
#include "ui_assembleoutputsettingsdialog.h"
|
||||
|
||||
#include "pdfwidgetutils.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
namespace pdfdocpage
|
||||
{
|
||||
|
||||
AssembleOutputSettingsDialog::AssembleOutputSettingsDialog(QString directory, QWidget* parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AssembleOutputSettingsDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->directoryEdit->setText(directory);
|
||||
|
||||
ui->outlineModeComboBox->addItem(tr("No Outline"), int(pdf::PDFDocumentManipulator::OutlineMode::NoOutline));
|
||||
ui->outlineModeComboBox->addItem(tr("Join Outlines"), int(pdf::PDFDocumentManipulator::OutlineMode::Join));
|
||||
ui->outlineModeComboBox->addItem(tr("Document Parts"), int(pdf::PDFDocumentManipulator::OutlineMode::DocumentParts));
|
||||
ui->outlineModeComboBox->setCurrentIndex(ui->outlineModeComboBox->findData(int(pdf::PDFDocumentManipulator::OutlineMode::DocumentParts)));
|
||||
|
||||
pdf::PDFWidgetUtils::scaleWidget(this, QSize(450, 150));
|
||||
pdf::PDFWidgetUtils::style(this);
|
||||
}
|
||||
|
||||
AssembleOutputSettingsDialog::~AssembleOutputSettingsDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QString AssembleOutputSettingsDialog::getDirectory() const
|
||||
{
|
||||
return ui->directoryEdit->text();
|
||||
}
|
||||
|
||||
QString AssembleOutputSettingsDialog::getFileName() const
|
||||
{
|
||||
return ui->fileTemplateEdit->text();
|
||||
}
|
||||
|
||||
bool AssembleOutputSettingsDialog::isOverwriteFiles() const
|
||||
{
|
||||
return ui->overwriteFilesCheckBox->isChecked();
|
||||
}
|
||||
|
||||
pdf::PDFDocumentManipulator::OutlineMode AssembleOutputSettingsDialog::getOutlineMode() const
|
||||
{
|
||||
return pdf::PDFDocumentManipulator::OutlineMode(ui->outlineModeComboBox->currentData().toInt());
|
||||
}
|
||||
|
||||
void AssembleOutputSettingsDialog::on_selectDirectoryButton_clicked()
|
||||
{
|
||||
QString directory = QFileDialog::getExistingDirectory(this, tr("Select output directory"), ui->directoryEdit->text());
|
||||
if (!directory.isEmpty())
|
||||
{
|
||||
ui->directoryEdit->setText(directory);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pdfdocpage
|
|
@ -1,55 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFDOCPAGEORGANIZER_ASSEMBLEOUTPUTSETTINGSDIALOG_H
|
||||
#define PDFDOCPAGEORGANIZER_ASSEMBLEOUTPUTSETTINGSDIALOG_H
|
||||
|
||||
#include "pdfdocumentmanipulator.h"
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class AssembleOutputSettingsDialog;
|
||||
}
|
||||
|
||||
namespace pdfdocpage
|
||||
{
|
||||
|
||||
class AssembleOutputSettingsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AssembleOutputSettingsDialog(QString directory, QWidget* parent);
|
||||
virtual ~AssembleOutputSettingsDialog() override;
|
||||
|
||||
QString getDirectory() const;
|
||||
QString getFileName() const;
|
||||
bool isOverwriteFiles() const;
|
||||
pdf::PDFDocumentManipulator::OutlineMode getOutlineMode() const;
|
||||
|
||||
private slots:
|
||||
void on_selectDirectoryButton_clicked();
|
||||
|
||||
private:
|
||||
Ui::AssembleOutputSettingsDialog* ui;
|
||||
};
|
||||
|
||||
} // namespace pdfdocpage
|
||||
|
||||
#endif // PDFDOCPAGEORGANIZER_ASSEMBLEOUTPUTSETTINGSDIALOG_H
|
|
@ -1,50 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "pdfconstants.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCommandLineParser>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents, true);
|
||||
QApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity, true);
|
||||
|
||||
#if !defined(Q_OS_WIN)
|
||||
QApplication::setAttribute(Qt::AA_DontUseNativeDialogs, true);
|
||||
#endif
|
||||
|
||||
QApplication application(argc, argv);
|
||||
|
||||
QCoreApplication::setOrganizationName("MelkaJ");
|
||||
QCoreApplication::setApplicationName("PDF4QT DocPage Organizer");
|
||||
QCoreApplication::setApplicationVersion(pdf::PDF_LIBRARY_VERSION);
|
||||
QApplication::setApplicationDisplayName(QApplication::translate("Application", "PDF4QT DocPage Organizer"));
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription(QCoreApplication::applicationName());
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
parser.addPositionalArgument("file", "The PDF file to open.");
|
||||
parser.process(application);
|
||||
|
||||
pdfdocpage::MainWindow mainWindow(nullptr);
|
||||
mainWindow.show();
|
||||
|
||||
return application.exec();
|
||||
}
|
|
@ -1,955 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include "aboutdialog.h"
|
||||
#include "assembleoutputsettingsdialog.h"
|
||||
#include "selectbookmarkstoregroupdialog.h"
|
||||
|
||||
#include "pdfaction.h"
|
||||
#include "pdfwidgetutils.h"
|
||||
#include "pdfdocumentreader.h"
|
||||
#include "pdfdocumentwriter.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QInputDialog>
|
||||
#include <QClipboard>
|
||||
#include <QToolBar>
|
||||
#include <QDesktopServices>
|
||||
#include <QImageReader>
|
||||
#include <QPixmapCache>
|
||||
#include <QScreen>
|
||||
#include <QGuiApplication>
|
||||
|
||||
namespace pdfdocpage
|
||||
{
|
||||
|
||||
MainWindow::MainWindow(QWidget* parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow),
|
||||
m_model(new PageItemModel(this)),
|
||||
m_delegate(new PageItemDelegate(m_model, this)),
|
||||
m_dropAction(Qt::IgnoreAction)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
m_delegate->setPageImageSize(getDefaultPageImageSize());
|
||||
|
||||
ui->documentItemsView->setModel(m_model);
|
||||
ui->documentItemsView->setItemDelegate(m_delegate);
|
||||
setMinimumSize(pdf::PDFWidgetUtils::scaleDPI(this, QSize(800, 600)));
|
||||
|
||||
ui->actionClear->setData(int(Operation::Clear));
|
||||
ui->actionCloneSelection->setData(int(Operation::CloneSelection));
|
||||
ui->actionRemoveSelection->setData(int(Operation::RemoveSelection));
|
||||
ui->actionReplaceSelection->setData(int(Operation::ReplaceSelection));
|
||||
ui->actionRestoreRemovedItems->setData(int(Operation::RestoreRemovedItems));
|
||||
ui->actionUndo->setData(int(Operation::Undo));
|
||||
ui->actionRedo->setData(int(Operation::Redo));
|
||||
ui->actionCut->setData(int(Operation::Cut));
|
||||
ui->actionCopy->setData(int(Operation::Copy));
|
||||
ui->actionPaste->setData(int(Operation::Paste));
|
||||
ui->actionRotate_Left->setData(int(Operation::RotateLeft));
|
||||
ui->actionRotate_Right->setData(int(Operation::RotateRight));
|
||||
ui->actionGroup->setData(int(Operation::Group));
|
||||
ui->actionUngroup->setData(int(Operation::Ungroup));
|
||||
ui->actionSelect_None->setData(int(Operation::SelectNone));
|
||||
ui->actionSelect_All->setData(int(Operation::SelectAll));
|
||||
ui->actionSelect_Even->setData(int(Operation::SelectEven));
|
||||
ui->actionSelect_Odd->setData(int(Operation::SelectOdd));
|
||||
ui->actionSelect_Portrait->setData(int(Operation::SelectPortrait));
|
||||
ui->actionSelect_Landscape->setData(int(Operation::SelectLandscape));
|
||||
ui->actionZoom_In->setData(int(Operation::ZoomIn));
|
||||
ui->actionZoom_Out->setData(int(Operation::ZoomOut));
|
||||
ui->actionUnited_Document->setData(int(Operation::Unite));
|
||||
ui->actionSeparate_to_Multiple_Documents->setData(int(Operation::Separate));
|
||||
ui->actionSeparate_to_Multiple_Documents_Grouped->setData(int(Operation::SeparateGrouped));
|
||||
ui->actionInsert_Image->setData(int(Operation::InsertImage));
|
||||
ui->actionInsert_Empty_Page->setData(int(Operation::InsertEmptyPage));
|
||||
ui->actionInsert_PDF->setData(int(Operation::InsertPDF));
|
||||
ui->actionGet_Source->setData(int(Operation::GetSource));
|
||||
ui->actionAbout->setData(int(Operation::About));
|
||||
ui->actionInvert_Selection->setData(int(Operation::InvertSelection));
|
||||
ui->actionRegroup_Even_Odd->setData(int(Operation::RegroupEvenOdd));
|
||||
ui->actionRegroup_by_Page_Pairs->setData(int(Operation::RegroupPaired));
|
||||
ui->actionRegroup_by_Bookmarks->setData(int(Operation::RegroupBookmarks));
|
||||
ui->actionRegroup_by_Alternating_Pages->setData(int(Operation::RegroupAlternatingPages));
|
||||
ui->actionRegroup_by_Alternating_Pages_Reversed_Order->setData(int(Operation::RegroupAlternatingPagesReversed));
|
||||
ui->actionPrepare_Icon_Theme->setData(int(Operation::PrepareIconTheme));
|
||||
|
||||
m_iconTheme.registerAction(ui->actionAddDocuments, ":/pdfdocpage/resources/open.svg");
|
||||
m_iconTheme.registerAction(ui->actionClose, ":/pdfdocpage/resources/close.svg");
|
||||
m_iconTheme.registerAction(ui->actionCloneSelection, ":/pdfdocpage/resources/clone-selection.svg");
|
||||
m_iconTheme.registerAction(ui->actionRemoveSelection, ":/pdfdocpage/resources/remove-selection.svg");
|
||||
m_iconTheme.registerAction(ui->actionRestoreRemovedItems, ":/pdfdocpage/resources/restore-removed-items.svg");
|
||||
m_iconTheme.registerAction(ui->actionInsert_PDF, ":/pdfdocpage/resources/insert-page-from-pdf.svg");
|
||||
m_iconTheme.registerAction(ui->actionInsert_Image, ":/pdfdocpage/resources/insert-image.svg");
|
||||
m_iconTheme.registerAction(ui->actionInsert_Empty_Page, ":/pdfdocpage/resources/insert-empty-page.svg");
|
||||
m_iconTheme.registerAction(ui->actionCut, ":/pdfdocpage/resources/cut.svg");
|
||||
m_iconTheme.registerAction(ui->actionCopy, ":/pdfdocpage/resources/copy.svg");
|
||||
m_iconTheme.registerAction(ui->actionPaste, ":/pdfdocpage/resources/paste.svg");
|
||||
m_iconTheme.registerAction(ui->actionReplaceSelection, ":/pdfdocpage/resources/replace-selection.svg");
|
||||
m_iconTheme.registerAction(ui->actionSelect_None, ":/pdfdocpage/resources/select-none.svg");
|
||||
m_iconTheme.registerAction(ui->actionSelect_All, ":/pdfdocpage/resources/select-all.svg");
|
||||
m_iconTheme.registerAction(ui->actionSelect_Even, ":/pdfdocpage/resources/select-even.svg");
|
||||
m_iconTheme.registerAction(ui->actionSelect_Odd, ":/pdfdocpage/resources/select-odd.svg");
|
||||
m_iconTheme.registerAction(ui->actionSelect_Portrait, ":/pdfdocpage/resources/select-portrait.svg");
|
||||
m_iconTheme.registerAction(ui->actionSelect_Landscape, ":/pdfdocpage/resources/select-landscape.svg");
|
||||
m_iconTheme.registerAction(ui->actionRotate_Right, ":/pdfdocpage/resources/rotate-right.svg");
|
||||
m_iconTheme.registerAction(ui->actionRotate_Left, ":/pdfdocpage/resources/rotate-left.svg");
|
||||
m_iconTheme.registerAction(ui->actionZoom_In, ":/pdfdocpage/resources/zoom-in.svg");
|
||||
m_iconTheme.registerAction(ui->actionZoom_Out, ":/pdfdocpage/resources/zoom-out.svg");
|
||||
m_iconTheme.registerAction(ui->actionGet_Source, ":/pdfdocpage/resources/get-source.svg");
|
||||
m_iconTheme.registerAction(ui->actionAbout, ":/pdfdocpage/resources/about.svg");
|
||||
m_iconTheme.registerAction(ui->actionUnited_Document, ":/pdfdocpage/resources/make-united-document.svg");
|
||||
m_iconTheme.registerAction(ui->actionSeparate_to_Multiple_Documents, ":/pdfdocpage/resources/make-separated-document.svg");
|
||||
m_iconTheme.registerAction(ui->actionSeparate_to_Multiple_Documents_Grouped, ":/pdfdocpage/resources/make-separated-document-from-groups.svg");
|
||||
m_iconTheme.registerAction(ui->actionGroup, ":/pdfdocpage/resources/group.svg");
|
||||
m_iconTheme.registerAction(ui->actionUngroup, ":/pdfdocpage/resources/ungroup.svg");
|
||||
m_iconTheme.registerAction(ui->actionClear, ":/pdfdocpage/resources/clear.svg");
|
||||
m_iconTheme.registerAction(ui->actionRegroup_Even_Odd, ":/pdfdocpage/resources/regroup-even-odd.svg");
|
||||
m_iconTheme.registerAction(ui->actionRegroup_by_Page_Pairs, ":/pdfdocpage/resources/regroup-pairs.svg");
|
||||
m_iconTheme.registerAction(ui->actionRegroup_by_Bookmarks, ":/pdfdocpage/resources/regroup-bookmarks.svg");
|
||||
m_iconTheme.registerAction(ui->actionRegroup_by_Alternating_Pages, ":/pdfdocpage/resources/regroup-alternating.svg");
|
||||
m_iconTheme.registerAction(ui->actionRegroup_by_Alternating_Pages_Reversed_Order, ":/pdfdocpage/resources/regroup-alternating-reversed.svg");
|
||||
m_iconTheme.registerAction(ui->actionInvert_Selection, ":/pdfdocpage/resources/invert-selection.svg");
|
||||
m_iconTheme.registerAction(ui->actionUndo, ":/pdfdocpage/resources/undo.svg");
|
||||
m_iconTheme.registerAction(ui->actionRedo, ":/pdfdocpage/resources/redo.svg");
|
||||
|
||||
m_iconTheme.setDirectory("pdfdocpage_theme");
|
||||
m_iconTheme.setPrefix(":/pdfdocpage/resources/");
|
||||
m_iconTheme.loadTheme();
|
||||
|
||||
QToolBar* mainToolbar = addToolBar(tr("Main"));
|
||||
mainToolbar->setObjectName("main_toolbar");
|
||||
mainToolbar->addAction(ui->actionAddDocuments);
|
||||
mainToolbar->addSeparator();
|
||||
mainToolbar->addActions({ ui->actionCloneSelection, ui->actionRemoveSelection });
|
||||
mainToolbar->addSeparator();
|
||||
mainToolbar->addActions({ ui->actionUndo, ui->actionRedo });
|
||||
mainToolbar->addSeparator();
|
||||
mainToolbar->addActions({ ui->actionCut, ui->actionCopy, ui->actionPaste });
|
||||
mainToolbar->addSeparator();
|
||||
mainToolbar->addActions({ ui->actionGroup, ui->actionUngroup });
|
||||
QToolBar* insertToolbar = addToolBar(tr("Insert"));
|
||||
insertToolbar->setObjectName("insert_toolbar");
|
||||
insertToolbar->addActions({ ui->actionInsert_PDF, ui->actionInsert_Image, ui->actionInsert_Empty_Page });
|
||||
QToolBar* selectToolbar = addToolBar(tr("Select"));
|
||||
selectToolbar->setObjectName("select_toolbar");
|
||||
selectToolbar->addActions({ ui->actionSelect_None, ui->actionSelect_All, ui->actionSelect_Even, ui->actionSelect_Odd, ui->actionSelect_Portrait, ui->actionSelect_Landscape, ui->actionInvert_Selection });
|
||||
QToolBar* regroupToolbar = addToolBar(tr("Regroup"));
|
||||
regroupToolbar->setObjectName("regroup_toolbar");
|
||||
regroupToolbar->addActions({ ui->actionRegroup_Even_Odd, ui->actionRegroup_by_Page_Pairs, ui->actionRegroup_by_Bookmarks, ui->actionRegroup_by_Alternating_Pages, ui->actionRegroup_by_Alternating_Pages_Reversed_Order });
|
||||
QToolBar* zoomToolbar = addToolBar(tr("Zoom"));
|
||||
zoomToolbar->setObjectName("zoom_toolbar");
|
||||
zoomToolbar->addActions({ ui->actionZoom_In, ui->actionZoom_Out });
|
||||
QToolBar* makeToolbar = addToolBar(tr("Make"));
|
||||
makeToolbar->setObjectName("make_toolbar");
|
||||
makeToolbar->addActions({ ui->actionUnited_Document, ui->actionSeparate_to_Multiple_Documents, ui->actionSeparate_to_Multiple_Documents_Grouped });
|
||||
|
||||
QSize iconSize = pdf::PDFWidgetUtils::scaleDPI(this, QSize(24, 24));
|
||||
auto toolbars = findChildren<QToolBar*>();
|
||||
for (QToolBar* toolbar : toolbars)
|
||||
{
|
||||
toolbar->setIconSize(iconSize);
|
||||
ui->menuToolbars->addAction(toolbar->toggleViewAction());
|
||||
}
|
||||
|
||||
connect(&m_mapper, &QSignalMapper::mappedInt, this, &MainWindow::onMappedActionTriggered);
|
||||
connect(ui->documentItemsView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &MainWindow::updateActions);
|
||||
|
||||
QList<QAction*> actions = findChildren<QAction*>();
|
||||
for (QAction* action : actions)
|
||||
{
|
||||
QVariant actionData = action->data();
|
||||
if (actionData.isValid())
|
||||
{
|
||||
connect(action, &QAction::triggered, &m_mapper, QOverload<>::of(&QSignalMapper::map));
|
||||
m_mapper.setMapping(action, actionData.toInt());
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize pixmap cache size
|
||||
const int depth = 4; // 4 bytes (ARGB)
|
||||
const int reserveSize = 2; // Caching of two screens
|
||||
QSize size = QGuiApplication::primaryScreen()->availableVirtualSize();
|
||||
int bytes = size.width() * size.height() * depth * reserveSize;
|
||||
int kBytes = bytes / 1024;
|
||||
QPixmapCache::setCacheLimit(kBytes);
|
||||
|
||||
loadSettings();
|
||||
updateActions();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
saveSettings();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
QSize MainWindow::getMinPageImageSize() const
|
||||
{
|
||||
return pdf::PDFWidgetUtils::scaleDPI(this, QSize(40, 40));
|
||||
}
|
||||
|
||||
QSize MainWindow::getDefaultPageImageSize() const
|
||||
{
|
||||
return pdf::PDFWidgetUtils::scaleDPI(this, QSize(100, 100));
|
||||
}
|
||||
|
||||
QSize MainWindow::getMaxPageImageSize() const
|
||||
{
|
||||
return pdf::PDFWidgetUtils::scaleDPI(this, QSize(250, 250));
|
||||
}
|
||||
|
||||
void MainWindow::on_actionClose_triggered()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAddDocuments_triggered()
|
||||
{
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select PDF document(s)"), m_settings.directory, tr("PDF document (*.pdf)"));
|
||||
if (!fileNames.isEmpty())
|
||||
{
|
||||
for (const QString& fileName : fileNames)
|
||||
{
|
||||
if (!insertDocument(fileName, QModelIndex()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onMappedActionTriggered(int actionId)
|
||||
{
|
||||
performOperation(static_cast<Operation>(actionId));
|
||||
}
|
||||
|
||||
void MainWindow::updateActions()
|
||||
{
|
||||
QList<QAction*> actions = findChildren<QAction*>();
|
||||
for (QAction* action : actions)
|
||||
{
|
||||
QVariant actionData = action->data();
|
||||
if (actionData.isValid())
|
||||
{
|
||||
action->setEnabled(canPerformOperation(static_cast<Operation>(actionData.toInt())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::loadSettings()
|
||||
{
|
||||
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName());
|
||||
settings.beginGroup("MainWindow");
|
||||
QByteArray geometry = settings.value("geometry", QByteArray()).toByteArray();
|
||||
if (geometry.isEmpty())
|
||||
{
|
||||
QRect availableGeometry = QApplication::primaryScreen()->availableGeometry();
|
||||
QRect windowRect(0, 0, availableGeometry.width() / 2, availableGeometry.height() / 2);
|
||||
windowRect = windowRect.translated(availableGeometry.center() - windowRect.center());
|
||||
setGeometry(windowRect);
|
||||
}
|
||||
else
|
||||
{
|
||||
restoreGeometry(geometry);
|
||||
}
|
||||
|
||||
QByteArray state = settings.value("windowState", QByteArray()).toByteArray();
|
||||
if (!state.isEmpty())
|
||||
{
|
||||
restoreState(state);
|
||||
}
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup("Settings");
|
||||
m_settings.directory = settings.value("directory").toString();
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
void MainWindow::saveSettings()
|
||||
{
|
||||
QSettings settings(QSettings::IniFormat, QSettings::UserScope, QCoreApplication::organizationName(), QCoreApplication::applicationName());
|
||||
settings.beginGroup("MainWindow");
|
||||
settings.setValue("geometry", saveGeometry());
|
||||
settings.setValue("windowState", saveState());
|
||||
settings.endGroup();
|
||||
|
||||
settings.beginGroup("Settings");
|
||||
settings.setValue("directory", m_settings.directory);
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
bool MainWindow::insertDocument(const QString& fileName, const QModelIndex& insertIndex)
|
||||
{
|
||||
bool isDocumentInserted = true;
|
||||
|
||||
QFileInfo fileInfo(fileName);
|
||||
|
||||
auto queryPassword = [this, &fileInfo](bool* ok)
|
||||
{
|
||||
*ok = false;
|
||||
return QInputDialog::getText(this, tr("Encrypted document"), tr("Enter password to access document '%1'").arg(fileInfo.fileName()), QLineEdit::Password, QString(), ok);
|
||||
};
|
||||
|
||||
// Mark current directory as this
|
||||
m_settings.directory = fileInfo.dir().absolutePath();
|
||||
|
||||
// Try to open a new document
|
||||
pdf::PDFDocumentReader reader(nullptr, qMove(queryPassword), true, false);
|
||||
pdf::PDFDocument document = reader.readFromFile(fileName);
|
||||
|
||||
QString errorMessage = reader.getErrorMessage();
|
||||
pdf::PDFDocumentReader::Result result = reader.getReadingResult();
|
||||
if (result == pdf::PDFDocumentReader::Result::OK)
|
||||
{
|
||||
const pdf::PDFSecurityHandler* securityHandler = document.getStorage().getSecurityHandler();
|
||||
if (securityHandler->isAllowed(pdf::PDFSecurityHandler::Permission::Assemble) ||
|
||||
securityHandler->isAllowed(pdf::PDFSecurityHandler::Permission::Modify))
|
||||
{
|
||||
m_model->insertDocument(fileName, qMove(document), insertIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
isDocumentInserted = false;
|
||||
QMessageBox::critical(this, tr("Error"), tr("Document security doesn't permit to organize pages."));
|
||||
}
|
||||
}
|
||||
else if (result == pdf::PDFDocumentReader::Result::Failed)
|
||||
{
|
||||
isDocumentInserted = false;
|
||||
QMessageBox::critical(this, tr("Error"), errorMessage);
|
||||
}
|
||||
else if (result == pdf::PDFDocumentReader::Result::Cancelled)
|
||||
{
|
||||
isDocumentInserted = false;
|
||||
}
|
||||
|
||||
updateActions();
|
||||
return isDocumentInserted;
|
||||
}
|
||||
|
||||
bool MainWindow::canPerformOperation(Operation operation) const
|
||||
{
|
||||
QModelIndexList selection = ui->documentItemsView->selectionModel()->selection().indexes();
|
||||
const bool isSelected = !selection.isEmpty();
|
||||
const bool isMultiSelected = selection.size() > 1;
|
||||
const bool isModelEmpty = m_model->rowCount(QModelIndex()) == 0;
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case Operation::Clear:
|
||||
return true;
|
||||
|
||||
case Operation::CloneSelection:
|
||||
case Operation::RemoveSelection:
|
||||
case Operation::ReplaceSelection:
|
||||
return isSelected;
|
||||
|
||||
case Operation::RestoreRemovedItems:
|
||||
return !m_model->isTrashBinEmpty();
|
||||
|
||||
case Operation::Undo:
|
||||
return m_model->canUndo();
|
||||
|
||||
case Operation::Redo:
|
||||
return m_model->canRedo();
|
||||
|
||||
case Operation::Cut:
|
||||
case Operation::Copy:
|
||||
return isSelected;
|
||||
|
||||
case Operation::Paste:
|
||||
{
|
||||
const QMimeData* mimeData = QApplication::clipboard()->mimeData();
|
||||
return mimeData && mimeData->hasFormat(PageItemModel::getMimeDataType());
|
||||
}
|
||||
|
||||
case Operation::RotateLeft:
|
||||
case Operation::RotateRight:
|
||||
return isSelected;
|
||||
|
||||
case Operation::Group:
|
||||
return isMultiSelected;
|
||||
case Operation::Ungroup:
|
||||
return m_model->isGrouped(selection);
|
||||
|
||||
case Operation::SelectNone:
|
||||
return isSelected;
|
||||
|
||||
case Operation::SelectAll:
|
||||
case Operation::SelectEven:
|
||||
case Operation::SelectOdd:
|
||||
case Operation::SelectPortrait:
|
||||
case Operation::SelectLandscape:
|
||||
return !isModelEmpty;
|
||||
|
||||
case Operation::ZoomIn:
|
||||
return m_delegate->getPageImageSize() != getMaxPageImageSize();
|
||||
|
||||
case Operation::ZoomOut:
|
||||
return m_delegate->getPageImageSize() != getMinPageImageSize();
|
||||
|
||||
case Operation::Unite:
|
||||
case Operation::Separate:
|
||||
case Operation::SeparateGrouped:
|
||||
return !isModelEmpty;
|
||||
|
||||
case Operation::InsertImage:
|
||||
case Operation::InsertEmptyPage:
|
||||
case Operation::InsertPDF:
|
||||
case Operation::GetSource:
|
||||
case Operation::About:
|
||||
case Operation::PrepareIconTheme:
|
||||
return true;
|
||||
|
||||
case Operation::InvertSelection:
|
||||
return !isModelEmpty;
|
||||
|
||||
case Operation::RegroupEvenOdd:
|
||||
{
|
||||
PageItemModel::SelectionInfo info = m_model->getSelectionInfo(selection);
|
||||
return info.isDocumentOnly();
|
||||
}
|
||||
|
||||
case Operation::RegroupPaired:
|
||||
return !isModelEmpty && !selection.isEmpty();
|
||||
|
||||
case Operation::RegroupBookmarks:
|
||||
{
|
||||
PageItemModel::SelectionInfo info = m_model->getSelectionInfo(selection);
|
||||
return info.isSingleDocument();
|
||||
}
|
||||
|
||||
case Operation::RegroupAlternatingPages:
|
||||
case Operation::RegroupAlternatingPagesReversed:
|
||||
{
|
||||
PageItemModel::SelectionInfo info = m_model->getSelectionInfo(selection);
|
||||
return info.isTwoDocuments();
|
||||
}
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MainWindow::performOperation(Operation operation)
|
||||
{
|
||||
switch (operation)
|
||||
{
|
||||
case Operation::Clear:
|
||||
{
|
||||
m_model->clear();
|
||||
QPixmapCache::clear();
|
||||
break;
|
||||
}
|
||||
case Operation::CloneSelection:
|
||||
{
|
||||
m_model->cloneSelection(ui->documentItemsView->selectionModel()->selection().indexes());
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::RemoveSelection:
|
||||
{
|
||||
m_model->removeSelection(ui->documentItemsView->selectionModel()->selection().indexes());
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::RestoreRemovedItems:
|
||||
{
|
||||
QModelIndexList restoredItemIndices = m_model->restoreRemovedItems();
|
||||
QItemSelection itemSelection;
|
||||
for (const QModelIndex& index : restoredItemIndices)
|
||||
{
|
||||
itemSelection.select(index, index);
|
||||
}
|
||||
ui->documentItemsView->selectionModel()->select(itemSelection, QItemSelectionModel::ClearAndSelect);
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::Undo:
|
||||
{
|
||||
m_model->undo();
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::Redo:
|
||||
{
|
||||
m_model->redo();
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::Cut:
|
||||
case Operation::Copy:
|
||||
{
|
||||
QModelIndexList indices = ui->documentItemsView->selectionModel()->selection().indexes();
|
||||
|
||||
if (indices.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (QMimeData* mimeData = m_model->mimeData(indices))
|
||||
{
|
||||
QApplication::clipboard()->setMimeData(mimeData);
|
||||
}
|
||||
|
||||
ui->documentItemsView->clearSelection();
|
||||
m_dropAction = (operation == Operation::Cut) ? Qt::MoveAction : Qt::CopyAction;
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::Paste:
|
||||
{
|
||||
QModelIndexList indices = ui->documentItemsView->selectionModel()->selection().indexes();
|
||||
|
||||
int insertRow = m_model->rowCount(QModelIndex()) - 1;
|
||||
if (!indices.isEmpty())
|
||||
{
|
||||
insertRow = indices.back().row();
|
||||
}
|
||||
|
||||
QModelIndex insertIndex = m_model->index(insertRow, 0, QModelIndex());
|
||||
const QMimeData* mimeData = QApplication::clipboard()->mimeData();
|
||||
if (m_model->canDropMimeData(mimeData, m_dropAction, -1, -1, insertIndex))
|
||||
{
|
||||
m_model->dropMimeData(mimeData, m_dropAction, -1, -1, insertIndex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::Group:
|
||||
m_model->group(ui->documentItemsView->selectionModel()->selection().indexes());
|
||||
break;
|
||||
|
||||
case Operation::Ungroup:
|
||||
m_model->ungroup(ui->documentItemsView->selectionModel()->selection().indexes());
|
||||
break;
|
||||
|
||||
case Operation::SelectNone:
|
||||
ui->documentItemsView->clearSelection();
|
||||
break;
|
||||
|
||||
case Operation::SelectAll:
|
||||
ui->documentItemsView->selectAll();
|
||||
break;
|
||||
|
||||
case Operation::SelectEven:
|
||||
ui->documentItemsView->selectionModel()->select(m_model->getSelectionEven(), QItemSelectionModel::ClearAndSelect);
|
||||
break;
|
||||
|
||||
case Operation::SelectOdd:
|
||||
ui->documentItemsView->selectionModel()->select(m_model->getSelectionOdd(), QItemSelectionModel::ClearAndSelect);
|
||||
break;
|
||||
|
||||
case Operation::SelectPortrait:
|
||||
ui->documentItemsView->selectionModel()->select(m_model->getSelectionPortrait(), QItemSelectionModel::ClearAndSelect);
|
||||
break;
|
||||
|
||||
case Operation::SelectLandscape:
|
||||
ui->documentItemsView->selectionModel()->select(m_model->getSelectionLandscape(), QItemSelectionModel::ClearAndSelect);
|
||||
break;
|
||||
|
||||
case Operation::ZoomIn:
|
||||
{
|
||||
QSize pageImageSize = m_delegate->getPageImageSize();
|
||||
pageImageSize *= 1.2;
|
||||
pageImageSize = pageImageSize.boundedTo(getMaxPageImageSize());
|
||||
|
||||
if (pageImageSize != m_delegate->getPageImageSize())
|
||||
{
|
||||
m_delegate->setPageImageSize(pageImageSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::ZoomOut:
|
||||
{
|
||||
QSize pageImageSize = m_delegate->getPageImageSize();
|
||||
pageImageSize /= 1.2;
|
||||
pageImageSize = pageImageSize.expandedTo(getMinPageImageSize());
|
||||
|
||||
if (pageImageSize != m_delegate->getPageImageSize())
|
||||
{
|
||||
m_delegate->setPageImageSize(pageImageSize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::RotateLeft:
|
||||
m_model->rotateLeft(ui->documentItemsView->selectionModel()->selection().indexes());
|
||||
break;
|
||||
|
||||
case Operation::RotateRight:
|
||||
m_model->rotateRight(ui->documentItemsView->selectionModel()->selection().indexes());
|
||||
break;
|
||||
|
||||
case Operation::GetSource:
|
||||
QDesktopServices::openUrl(QUrl("https://github.com/JakubMelka/PDF4QT"));
|
||||
break;
|
||||
|
||||
case Operation::InsertEmptyPage:
|
||||
m_model->insertEmptyPage(ui->documentItemsView->selectionModel()->selection().indexes());
|
||||
break;
|
||||
|
||||
case Operation::About:
|
||||
{
|
||||
PDFAboutDialog aboutDialog(this);
|
||||
aboutDialog.exec();
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::PrepareIconTheme:
|
||||
m_iconTheme.prepareTheme();
|
||||
break;
|
||||
|
||||
case Operation::Unite:
|
||||
case Operation::Separate:
|
||||
case Operation::SeparateGrouped:
|
||||
{
|
||||
PageItemModel::AssembleMode assembleMode = PageItemModel::AssembleMode::Unite;
|
||||
|
||||
switch (operation)
|
||||
{
|
||||
case Operation::Unite:
|
||||
assembleMode = PageItemModel::AssembleMode::Unite;
|
||||
break;
|
||||
|
||||
case Operation::Separate:
|
||||
assembleMode = PageItemModel::AssembleMode::Separate;
|
||||
break;
|
||||
|
||||
case Operation::SeparateGrouped:
|
||||
assembleMode = PageItemModel::AssembleMode::SeparateGrouped;
|
||||
break;
|
||||
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
|
||||
std::vector<std::vector<pdf::PDFDocumentManipulator::AssembledPage>> assembledDocuments = m_model->getAssembledPages(assembleMode);
|
||||
|
||||
// Check we have something to process
|
||||
if (assembledDocuments.empty())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("No documents to assemble."));
|
||||
break;
|
||||
}
|
||||
|
||||
AssembleOutputSettingsDialog dialog(m_settings.directory, this);
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
pdf::PDFDocumentManipulator manipulator;
|
||||
|
||||
// Add documents and images
|
||||
for (const auto& documentItem : m_model->getDocuments())
|
||||
{
|
||||
manipulator.addDocument(documentItem.first, &documentItem.second.document);
|
||||
}
|
||||
for (const auto& imageItem : m_model->getImages())
|
||||
{
|
||||
manipulator.addImage(imageItem.first, imageItem.second.image);
|
||||
}
|
||||
|
||||
// Jakub Melka: create assembled documents
|
||||
pdf::PDFOperationResult result(true);
|
||||
std::vector<std::pair<QString, pdf::PDFDocument>> assembledDocumentStorage;
|
||||
|
||||
int sourceDocumentIndex = 1;
|
||||
int assembledDocumentIndex = 1;
|
||||
int sourcePageIndex = 1;
|
||||
int documentCount = int(m_model->getDocuments().size());
|
||||
|
||||
QString directory = dialog.getDirectory();
|
||||
QString fileNameTemplate = dialog.getFileName();
|
||||
const bool isOverwriteEnabled = dialog.isOverwriteFiles();
|
||||
pdf::PDFDocumentManipulator::OutlineMode outlineMode = dialog.getOutlineMode();
|
||||
manipulator.setOutlineMode(outlineMode);
|
||||
|
||||
if (!directory.endsWith('/'))
|
||||
{
|
||||
directory += "/";
|
||||
}
|
||||
|
||||
auto replaceInString = [](QString& templateString, QChar character, int number)
|
||||
{
|
||||
int index = templateString.indexOf(character, 0, Qt::CaseSensitive);
|
||||
if (index != -1)
|
||||
{
|
||||
int lastIndex = templateString.lastIndexOf(character, -1, Qt::CaseSensitive);
|
||||
int count = lastIndex - index + 1;
|
||||
|
||||
QString textNumber = QString::number(number);
|
||||
textNumber = textNumber.rightJustified(count, '0', false);
|
||||
|
||||
templateString.remove(index, count);
|
||||
templateString.insert(index, textNumber);
|
||||
}
|
||||
};
|
||||
|
||||
for (const std::vector<pdf::PDFDocumentManipulator::AssembledPage>& assembledPages : assembledDocuments)
|
||||
{
|
||||
pdf::PDFOperationResult currentResult = manipulator.assemble(assembledPages);
|
||||
if (!currentResult && result)
|
||||
{
|
||||
result = currentResult;
|
||||
break;
|
||||
}
|
||||
|
||||
pdf::PDFDocumentManipulator::AssembledPage samplePage = assembledPages.front();
|
||||
sourceDocumentIndex = samplePage.documentIndex == -1 ? documentCount + samplePage.imageIndex : samplePage.documentIndex;
|
||||
sourcePageIndex = qMax(int(samplePage.pageIndex + 1), 1);
|
||||
|
||||
QString fileName = fileNameTemplate;
|
||||
|
||||
replaceInString(fileName, '#', assembledDocumentIndex);
|
||||
replaceInString(fileName, '@', sourcePageIndex);
|
||||
replaceInString(fileName, '%', sourceDocumentIndex);
|
||||
|
||||
if (!fileName.endsWith(".pdf"))
|
||||
{
|
||||
fileName += ".pdf";
|
||||
}
|
||||
fileName.prepend(directory);
|
||||
|
||||
assembledDocumentStorage.emplace_back(std::make_pair(std::move(fileName), manipulator.takeAssembledDocument()));
|
||||
++assembledDocumentIndex;
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), result.getErrorMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
// Now, try to save files
|
||||
for (const auto& assembledDocumentItem : assembledDocumentStorage)
|
||||
{
|
||||
QString filename = assembledDocumentItem.first;
|
||||
const pdf::PDFDocument* document = &assembledDocumentItem.second;
|
||||
|
||||
const bool isDocumentFileAlreadyExisting = QFile::exists(filename);
|
||||
if (!isOverwriteEnabled && isDocumentFileAlreadyExisting)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Document with given filename already exists."));
|
||||
return;
|
||||
}
|
||||
|
||||
pdf::PDFDocumentWriter writer(nullptr);
|
||||
pdf::PDFOperationResult writeResult = writer.write(filename, document, isDocumentFileAlreadyExisting);
|
||||
|
||||
if (!writeResult)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), writeResult.getErrorMessage());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::InsertImage:
|
||||
{
|
||||
QStringList filters;
|
||||
for (const QByteArray& imageFormat : QImageReader::supportedImageFormats())
|
||||
{
|
||||
filters << QString::fromLatin1(imageFormat).toLower();
|
||||
}
|
||||
QString filter = tr("Images (*.%1)").arg(filters.join(" *."));
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select Image(s)"), m_settings.directory, filter, nullptr);
|
||||
|
||||
if (!fileNames.isEmpty())
|
||||
{
|
||||
QModelIndexList indexes = ui->documentItemsView->selectionModel()->selection().indexes();
|
||||
QModelIndex insertIndex = !indexes.isEmpty() ? indexes.front() : QModelIndex();
|
||||
|
||||
for (const QString& fileName : fileNames)
|
||||
{
|
||||
m_model->insertImage(fileName, insertIndex);
|
||||
insertIndex = insertIndex.sibling(insertIndex.row() + 1, insertIndex.column());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::InsertPDF:
|
||||
{
|
||||
QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Select PDF document(s)"), m_settings.directory, tr("PDF document (*.pdf)"));
|
||||
|
||||
if (!fileNames.isEmpty())
|
||||
{
|
||||
QModelIndexList indexes = ui->documentItemsView->selectionModel()->selection().indexes();
|
||||
QModelIndex insertIndex = !indexes.isEmpty() ? indexes.front() : QModelIndex();
|
||||
|
||||
for (const QString& fileName : fileNames)
|
||||
{
|
||||
if (!insertDocument(fileName, insertIndex))
|
||||
{
|
||||
break;
|
||||
}
|
||||
insertIndex = insertIndex.sibling(insertIndex.row() + 1, insertIndex.column());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::ReplaceSelection:
|
||||
{
|
||||
QModelIndexList indexes = ui->documentItemsView->selectionModel()->selection().indexes();
|
||||
|
||||
if (indexes.isEmpty())
|
||||
{
|
||||
// Jakub Melka: we have nothing to do, selection is empty
|
||||
return;
|
||||
}
|
||||
|
||||
QString fileName = QFileDialog::getOpenFileName(this, tr("Select PDF document"), m_settings.directory, tr("PDF document (*.pdf)"));
|
||||
if (!fileName.isEmpty())
|
||||
{
|
||||
insertDocument(fileName, indexes.back());
|
||||
m_model->removeSelection(indexes);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::InvertSelection:
|
||||
{
|
||||
QModelIndex rootIndex = ui->documentItemsView->rootIndex();
|
||||
|
||||
if (rootIndex.isValid())
|
||||
{
|
||||
QModelIndex firstIndex = rootIndex.model()->index(0, 0, rootIndex);
|
||||
QModelIndex lastIndex = rootIndex.model()->index(rootIndex.model()->rowCount() - 1, 0, rootIndex);
|
||||
QItemSelection selection(firstIndex, lastIndex);
|
||||
|
||||
ui->documentItemsView->selectionModel()->select(selection, QItemSelectionModel::Toggle);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::RegroupEvenOdd:
|
||||
{
|
||||
QModelIndexList indexes = ui->documentItemsView->selectionModel()->selection().indexes();
|
||||
m_model->regroupEvenOdd(indexes);
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::RegroupPaired:
|
||||
{
|
||||
QModelIndexList indexes = ui->documentItemsView->selectionModel()->selection().indexes();
|
||||
m_model->regroupPaired(indexes);
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::RegroupBookmarks:
|
||||
{
|
||||
QModelIndexList indexes = ui->documentItemsView->selectionModel()->selection().indexes();
|
||||
|
||||
if (!indexes.isEmpty())
|
||||
{
|
||||
PageItemModel::SelectionInfo selectionInfo = m_model->getSelectionInfo(indexes);
|
||||
const std::map<int, DocumentItem>& documents = m_model->getDocuments();
|
||||
|
||||
auto it = documents.find(selectionInfo.firstDocumentIndex);
|
||||
if (it != documents.end())
|
||||
{
|
||||
const pdf::PDFDocument* document = &it->second.document;
|
||||
SelectBookmarksToRegroupDialog dialog(document, this);
|
||||
|
||||
if (dialog.exec() == SelectBookmarksToRegroupDialog::Accepted)
|
||||
{
|
||||
std::vector<pdf::PDFInteger> breakPageIndices;
|
||||
std::vector<const pdf::PDFOutlineItem*> outlineItems = dialog.getSelectedOutlineItems();
|
||||
|
||||
// Jakub Melka: Resolve outline items. Try to find an index
|
||||
// of page of each outline item.
|
||||
for (const pdf::PDFOutlineItem* item : outlineItems)
|
||||
{
|
||||
const pdf::PDFAction* action = item->getAction();
|
||||
const pdf::PDFActionGoTo* actionGoto = dynamic_cast<const pdf::PDFActionGoTo*>(action);
|
||||
if (actionGoto)
|
||||
{
|
||||
pdf::PDFDestination destination = actionGoto->getDestination();
|
||||
|
||||
if (destination.getDestinationType() == pdf::DestinationType::Named)
|
||||
{
|
||||
if (const pdf::PDFDestination* targetDestination = document->getCatalog()->getNamedDestination(destination.getName()))
|
||||
{
|
||||
destination = *targetDestination;
|
||||
}
|
||||
else
|
||||
{
|
||||
destination = pdf::PDFDestination();
|
||||
}
|
||||
}
|
||||
|
||||
if (destination.isValid())
|
||||
{
|
||||
const size_t pageIndex = document->getCatalog()->getPageIndexFromPageReference(destination.getPageReference());
|
||||
if (pageIndex != pdf::PDFCatalog::INVALID_PAGE_INDEX)
|
||||
{
|
||||
breakPageIndices.push_back(pageIndex + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(breakPageIndices.begin(), breakPageIndices.end());
|
||||
breakPageIndices.erase(std::unique(breakPageIndices.begin(), breakPageIndices.end()), breakPageIndices.end());
|
||||
|
||||
m_model->regroupBookmarks(indexes, breakPageIndices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::RegroupAlternatingPages:
|
||||
{
|
||||
QModelIndexList indexes = ui->documentItemsView->selectionModel()->selection().indexes();
|
||||
m_model->regroupAlternatingPages(indexes, false);
|
||||
break;
|
||||
}
|
||||
|
||||
case Operation::RegroupAlternatingPagesReversed:
|
||||
{
|
||||
QModelIndexList indexes = ui->documentItemsView->selectionModel()->selection().indexes();
|
||||
m_model->regroupAlternatingPages(indexes, true);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updateActions();
|
||||
}
|
||||
|
||||
} // namespace pdfdocpage
|
|
@ -1,131 +0,0 @@
|
|||
// Copyright (C) 2021 Jakub Melka
|
||||
//
|
||||
// This file is part of PDF4QT.
|
||||
//
|
||||
// PDF4QT is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// with the written consent of the copyright owner, any later version.
|
||||
//
|
||||
// PDF4QT is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDF4QT. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFDOCPAGEORGANIZER_MAINWINDOW_H
|
||||
#define PDFDOCPAGEORGANIZER_MAINWINDOW_H
|
||||
|
||||
#include "pdficontheme.h"
|
||||
|
||||
#include "pageitemmodel.h"
|
||||
#include "pageitemdelegate.h"
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QSignalMapper>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
namespace pdfdocpage
|
||||
{
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget* parent);
|
||||
virtual ~MainWindow() override;
|
||||
|
||||
QSize getMinPageImageSize() const;
|
||||
QSize getDefaultPageImageSize() const;
|
||||
QSize getMaxPageImageSize() const;
|
||||
|
||||
enum class Operation
|
||||
{
|
||||
Clear,
|
||||
CloneSelection,
|
||||
RemoveSelection,
|
||||
ReplaceSelection,
|
||||
RestoreRemovedItems,
|
||||
|
||||
Undo,
|
||||
Redo,
|
||||
|
||||
Cut,
|
||||
Copy,
|
||||
Paste,
|
||||
|
||||
RotateLeft,
|
||||
RotateRight,
|
||||
|
||||
Group,
|
||||
Ungroup,
|
||||
|
||||
SelectNone,
|
||||
SelectAll,
|
||||
SelectEven,
|
||||
SelectOdd,
|
||||
SelectPortrait,
|
||||
SelectLandscape,
|
||||
InvertSelection,
|
||||
|
||||
ZoomIn,
|
||||
ZoomOut,
|
||||
|
||||
Unite,
|
||||
Separate,
|
||||
SeparateGrouped,
|
||||
|
||||
InsertImage,
|
||||
InsertEmptyPage,
|
||||
InsertPDF,
|
||||
|
||||
RegroupEvenOdd,
|
||||
RegroupPaired,
|
||||
RegroupBookmarks,
|
||||
RegroupAlternatingPages,
|
||||
RegroupAlternatingPagesReversed,
|
||||
|
||||
GetSource,
|
||||
About,
|
||||
PrepareIconTheme
|
||||
};
|
||||
|
||||
private slots:
|
||||
void on_actionClose_triggered();
|
||||
void on_actionAddDocuments_triggered();
|
||||
void onMappedActionTriggered(int actionId);
|
||||
void updateActions();
|
||||
|
||||
private:
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
bool insertDocument(const QString& fileName, const QModelIndex& insertIndex);
|
||||
|
||||
bool canPerformOperation(Operation operation) const;
|
||||
void performOperation(Operation operation);
|
||||
|
||||
struct Settings
|
||||
{
|
||||
QString directory;
|
||||
};
|
||||
|
||||
Ui::MainWindow* ui;
|
||||
|
||||
pdf::PDFIconTheme m_iconTheme;
|
||||
PageItemModel* m_model;
|
||||
PageItemDelegate* m_delegate;
|
||||
Settings m_settings;
|
||||
QSignalMapper m_mapper;
|
||||
Qt::DropAction m_dropAction;
|
||||
};
|
||||
|
||||
} // namespace pdfdocpage
|
||||
|
||||
#endif // PDFDOCPAGEORGANIZER_MAINWINDOW_H
|