├── .clang-format
├── .github
└── workflows
│ └── build.yml
├── .gitignore
├── .vscode
└── settings.json
├── CMakeLists.txt
├── README.md
├── UNLICENSE
├── resources
├── CMakeLists.txt
├── br.eng.silas.qpdftools.desktop
├── br.eng.silas.qpdftools.metainfo.xml
├── br.eng.silas.qpdftools.svg
├── fallback-icons
│ ├── fallback-icons-dark
│ │ ├── edit-cut.svg
│ │ ├── edit-group.svg
│ │ ├── go-down.svg
│ │ ├── go-previous.svg
│ │ ├── go-up.svg
│ │ ├── object-rotate-left.svg
│ │ ├── object-rotate-right.svg
│ │ ├── value-decrease.svg
│ │ ├── value-increase.svg
│ │ └── zoom-2-to-1.svg
│ ├── fallback-icons-light
│ │ ├── edit-cut.svg
│ │ ├── edit-group.svg
│ │ ├── go-down.svg
│ │ ├── go-previous.svg
│ │ ├── go-up.svg
│ │ ├── object-rotate-left.svg
│ │ ├── object-rotate-right.svg
│ │ ├── value-decrease.svg
│ │ ├── value-increase.svg
│ │ └── zoom-2-to-1.svg
│ └── fallback-icons.qrc
├── generateIcons.sh
├── icons
│ ├── 128-apps-br.eng.silas.qpdftools.png
│ ├── 16-apps-br.eng.silas.qpdftools.png
│ ├── 192-apps-br.eng.silas.qpdftools.png
│ ├── 22-apps-br.eng.silas.qpdftools.png
│ ├── 24-apps-br.eng.silas.qpdftools.png
│ ├── 256-apps-br.eng.silas.qpdftools.png
│ ├── 32-apps-br.eng.silas.qpdftools.png
│ ├── 36-apps-br.eng.silas.qpdftools.png
│ ├── 48-apps-br.eng.silas.qpdftools.png
│ ├── 512-apps-br.eng.silas.qpdftools.png
│ ├── 64-apps-br.eng.silas.qpdftools.png
│ ├── 72-apps-br.eng.silas.qpdftools.png
│ ├── 96-apps-br.eng.silas.qpdftools.png
│ └── sc-apps-br.eng.silas.qpdftools.svg
└── screenshots
│ ├── compress-screen.png
│ ├── menu-screen.png
│ └── merge-screen.png
└── src
├── CMakeLists.txt
├── api
├── externalSoftware.cpp
├── externalSoftware.hpp
├── ghostscript.cpp
├── ghostscript.hpp
├── qpdf.cpp
└── qpdf.hpp
├── interface
├── mainwindow.cpp
├── mainwindow.hpp
├── mainwindow.ui
├── pages
│ ├── 0-menu
│ │ ├── menu.cpp
│ │ ├── menu.hpp
│ │ └── menu.ui
│ ├── 1-compress
│ │ ├── compress.cpp
│ │ ├── compress.hpp
│ │ └── compress.ui
│ ├── 2-split
│ │ ├── split.cpp
│ │ ├── split.hpp
│ │ └── split.ui
│ ├── 3-merge
│ │ ├── merge.cpp
│ │ ├── merge.hpp
│ │ └── merge.ui
│ └── 4-rotate
│ │ ├── rotate.cpp
│ │ ├── rotate.hpp
│ │ └── rotate.ui
└── utils
│ ├── fileDialog.cpp
│ └── fileDialog.hpp
├── languages
└── qpdftools_pt_BR.ts
└── main.cpp
/.clang-format:
--------------------------------------------------------------------------------
1 | BasedOnStyle: LLVM
2 | ColumnLimit: 100
3 |
4 | ContinuationIndentWidth: 2
5 | AlignAfterOpenBracket: DontAlign
6 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: build
2 | on: push
3 | jobs:
4 | build:
5 | runs-on: ubuntu-latest
6 | steps:
7 | - name: Setup flatpak and Flathub
8 | run: |
9 | sudo apt update
10 | sudo apt install flatpak flatpak-builder
11 | sudo flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
12 | - name: Pull Qpdf Tools Code
13 | uses: actions/checkout@v4
14 | - name: Pull and setup manifest
15 | run: |
16 | curl https://raw.githubusercontent.com/flathub/br.eng.silas.qpdftools/master/br.eng.silas.qpdftools.yml > tmp.yml
17 | head -n -3 tmp.yml > br.eng.silas.qpdftools.yml
18 | echo " - type: dir" >> br.eng.silas.qpdftools.yml
19 | echo " path: ." >> br.eng.silas.qpdftools.yml
20 | - name: Build and install qpdftools flatpak
21 | run: sudo flatpak-builder --install-deps-from=flathub --install build-dir ./br.eng.silas.qpdftools.yml --force-clean
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.user*
2 | *.tar.gz
3 |
4 | # flatpak
5 | .flatpak-builder
6 | build-dir
7 | builddir
8 | repo
9 |
10 | # cmake
11 | build/
12 | .qt/
13 | .cache/
14 | CMakeFiles/
15 | Makefile
16 | prefix.sh
17 | CMakeCache.txt
18 | cmake_install.cmake
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.associations": { "*.ts": "xml", "*.ui": "xml", "*.svg": "xml" },
3 |
4 | "editor.formatOnSave": true,
5 | "editor.indentSize": 2,
6 | "[xml]": {
7 | "editor.detectIndentation": true,
8 | "editor.indentSize": 1,
9 | "editor.tabSize": 1
10 | },
11 | "cSpell.words": [
12 | "APPDIR",
13 | "archlinux",
14 | "AUTOMOC",
15 | "AUTORCC",
16 | "autotools",
17 | "AUTOUIC",
18 | "BINDIR",
19 | "bugtracker",
20 | "builddir",
21 | "buildsystem",
22 | "dbus",
23 | "DCMAKE",
24 | "debhelper",
25 | "debuild",
26 | "devscripts",
27 | "Dont",
28 | "dpkg",
29 | "dput",
30 | "flatpak",
31 | "freedesktop",
32 | "ghaction",
33 | "hapakaien",
34 | "hsizetype",
35 | "iconset",
36 | "launchable",
37 | "libqt",
38 | "METAINFODIR",
39 | "namcap",
40 | "NOPAUSE",
41 | "notr",
42 | "PDFSETTINGS",
43 | "pdfwrite",
44 | "Pixmap",
45 | "pkgdir",
46 | "pointsize",
47 | "prepress",
48 | "qresource",
49 | "qtbase",
50 | "rbtn",
51 | "sizepolicy",
52 | "sourcelanguage",
53 | "stdset",
54 | "tbtn",
55 | "updpkgsums",
56 | "vsizetype",
57 | "wayland",
58 | "yuezk"
59 | ]
60 | }
61 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.16)
2 | project(qpdftools VERSION 3.1.2)
3 |
4 | set(CMAKE_INCLUDE_CURRENT_DIR ON)
5 | set(CMAKE_AUTOUIC ON)
6 | set(CMAKE_AUTOMOC ON)
7 | set(CMAKE_AUTORCC ON)
8 | set(CMAKE_CXX_STANDARD 17)
9 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
10 |
11 | add_subdirectory(resources)
12 | add_subdirectory(src)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
Qpdf Tools
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | > Se installation info in the project [wiki](https://github.com/silash35/qpdftools/wiki).
11 |
12 | Qpdf Tools is an easy-to-use Qt interface for [Ghostscript](https://www.ghostscript.com/) and [QPDF](https://github.com/qpdf/qpdf), which makes it possible for normal users to manage their PDFs.
13 |
14 |
15 |
16 |
17 |
18 | With Qpdf Tools, you can easily compress, split, merge and even rotate your pdf documents.
19 |
20 | Go to the project [wiki](https://github.com/silash35/qpdftools/wiki) for more information
21 |
--------------------------------------------------------------------------------
/UNLICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/resources/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Add ECM Modules
2 | find_package(ECM REQUIRED NO_MODULE)
3 | set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
4 | include(ECMInstallIcons)
5 | include(KDEInstallDirs)
6 |
7 | set(ICONS
8 | icons/16-apps-br.eng.silas.qpdftools.png
9 | icons/22-apps-br.eng.silas.qpdftools.png
10 | icons/24-apps-br.eng.silas.qpdftools.png
11 | icons/32-apps-br.eng.silas.qpdftools.png
12 | icons/36-apps-br.eng.silas.qpdftools.png
13 | icons/48-apps-br.eng.silas.qpdftools.png
14 | icons/64-apps-br.eng.silas.qpdftools.png
15 | icons/72-apps-br.eng.silas.qpdftools.png
16 | icons/96-apps-br.eng.silas.qpdftools.png
17 | icons/128-apps-br.eng.silas.qpdftools.png
18 | icons/192-apps-br.eng.silas.qpdftools.png
19 | icons/256-apps-br.eng.silas.qpdftools.png
20 | icons/512-apps-br.eng.silas.qpdftools.png
21 | icons/sc-apps-br.eng.silas.qpdftools.svg
22 | )
23 |
24 | if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
25 | ecm_install_icons(ICONS ${ICONS}
26 | DESTINATION ${KDE_INSTALL_ICONDIR} THEME hicolor
27 | )
28 |
29 | install(PROGRAMS br.eng.silas.qpdftools.desktop DESTINATION ${KDE_INSTALL_APPDIR})
30 | install(FILES br.eng.silas.qpdftools.metainfo.xml DESTINATION ${KDE_INSTALL_METAINFODIR})
31 | endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
32 |
--------------------------------------------------------------------------------
/resources/br.eng.silas.qpdftools.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 |
3 | Name=Qpdf Tools
4 | Exec=qpdftools
5 | Comment=A easy-to-use Qt interface for Ghostscript and QPDF
6 | Icon=br.eng.silas.qpdftools
7 | Type=Application
8 | Terminal=false
9 | StartupNotify=true
10 | Categories=Office;Qt;Utility;
11 | Name[pt_BR]=Qpdf Tools
12 |
--------------------------------------------------------------------------------
/resources/br.eng.silas.qpdftools.metainfo.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | br.eng.silas.qpdftools
4 |
5 | Qpdf Tools
6 | Tool for managing PDFs
7 | Silas Henrique
8 |
9 | CC0-1.0
10 | Unlicense
11 |
12 |
13 | Qpdf Tools is an Qt interface for Ghostscript and QPDF.
14 | Qpdf Tools makes possible for normal users to manage their PDFs.
15 | With Qpdf Tools, you can easily compress, split, merge and even rotate your pdf documents.
16 |
17 |
18 |
19 | pointing
20 | keyboard
21 | touch
22 |
23 |
24 | https://github.com/silash35/qpdftools
25 | https://github.com/silash35/qpdftools/issues
26 | https://github.com/silash35/qpdftools
27 |
28 |
29 | br.eng.silas.qpdftools.desktop
30 |
31 |
32 | #e9b2b2
33 | #511717
34 |
35 |
36 |
37 |
38 | https://github.com/silash35/qpdftools/raw/master/resources/screenshots/menu-screen.png?raw=true
39 | Menu screen of Qpdf Tools
40 |
41 |
42 | https://github.com/silash35/qpdftools/raw/master/resources/screenshots/merge-screen.png?raw=true
43 | Merge PDFs screen of Qpdf Tools
44 |
45 |
46 | https://github.com/silash35/qpdftools/raw/master/resources/screenshots/compress-screen.png?raw=true
47 | Compress PDF screen of Qpdf Tools
48 |
49 |
50 |
51 |
52 |
53 | https://github.com/silash35/qpdftools/releases/tag/v3.1.2
54 |
55 | Fix some bugs
56 |
57 | Fix file corruption when input file is the same of output
58 | Fix app icons on new breeze theme
59 | Update screenshots
60 |
61 |
62 |
63 |
64 | https://github.com/silash35/qpdftools/releases/tag/v3.1.1
65 |
66 | Fix icon size
67 |
68 | Set the svg icon size to 128px
69 | Fix QObject warning
70 | Update screenshots
71 |
72 |
73 |
74 |
75 | https://github.com/silash35/qpdftools/releases/tag/v3.1.0
76 |
77 | New App Icon
78 |
79 | Update the app icon, following KDE guidelines
80 | Make some small refinements on the user experience
81 |
82 |
83 |
84 |
85 | https://github.com/silash35/qpdftools/releases/tag/v3.0.1
86 |
87 | Fix issue of generating invalid.pdf file
88 |
89 |
90 |
91 | https://github.com/silash35/qpdftools/releases/tag/v3.0.0
92 |
93 | Upgrade to Qt6
94 |
95 | Fully upgrade to Qt6
96 | Improve the appearance of the menu screen.
97 | Refactor the code, making maintenance easier.
98 | And many other improvements
99 |
100 |
101 |
102 |
103 |
104 |
--------------------------------------------------------------------------------
/resources/br.eng.silas.qpdftools.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-dark/edit-cut.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-dark/edit-group.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-dark/go-down.svg:
--------------------------------------------------------------------------------
1 |
3 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-dark/go-previous.svg:
--------------------------------------------------------------------------------
1 |
3 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-dark/go-up.svg:
--------------------------------------------------------------------------------
1 |
3 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-dark/object-rotate-left.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-dark/object-rotate-right.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-dark/value-decrease.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-dark/value-increase.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-dark/zoom-2-to-1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-light/edit-cut.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-light/edit-group.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-light/go-down.svg:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-light/go-previous.svg:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-light/go-up.svg:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-light/object-rotate-left.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-light/object-rotate-right.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-light/value-decrease.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-light/value-increase.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons-light/zoom-2-to-1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/resources/fallback-icons/fallback-icons.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | fallback-icons-dark/edit-cut.svg
4 | fallback-icons-dark/edit-group.svg
5 | fallback-icons-dark/go-down.svg
6 | fallback-icons-dark/go-previous.svg
7 | fallback-icons-dark/go-up.svg
8 | fallback-icons-dark/value-increase.svg
9 | fallback-icons-dark/value-decrease.svg
10 | fallback-icons-dark/object-rotate-left.svg
11 | fallback-icons-dark/object-rotate-right.svg
12 | fallback-icons-dark/zoom-2-to-1.svg
13 |
14 | fallback-icons-light/edit-cut.svg
15 | fallback-icons-light/edit-group.svg
16 | fallback-icons-light/go-down.svg
17 | fallback-icons-light/go-previous.svg
18 | fallback-icons-light/go-up.svg
19 | fallback-icons-light/value-increase.svg
20 | fallback-icons-light/value-decrease.svg
21 | fallback-icons-light/object-rotate-left.svg
22 | fallback-icons-light/object-rotate-right.svg
23 | fallback-icons-light/zoom-2-to-1.svg
24 |
25 |
26 |
--------------------------------------------------------------------------------
/resources/generateIcons.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | printf "Cleaning icons folder"
4 | printf "\n"
5 | rm -rf ./icons
6 | mkdir ./icons
7 |
8 | printf "Generating Icons"
9 | printf "\n"
10 | for x in 16 22 24 32 36 48 64 72 96 128 192 256 512
11 | do
12 | inkscape -o icons/${x}-apps-br.eng.silas.qpdftools.png -w ${x} br.eng.silas.qpdftools.svg
13 | done
14 |
15 | printf "Copying scalable icon"
16 | printf "\n"
17 | cp ./br.eng.silas.qpdftools.svg ./icons/sc-apps-br.eng.silas.qpdftools.svg
18 |
19 | printf "Finished"
20 | printf "\n"
21 |
--------------------------------------------------------------------------------
/resources/icons/128-apps-br.eng.silas.qpdftools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silash35/qpdftools/a2faf6674aa37962079d6297e3a81dcfb59ef20f/resources/icons/128-apps-br.eng.silas.qpdftools.png
--------------------------------------------------------------------------------
/resources/icons/16-apps-br.eng.silas.qpdftools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silash35/qpdftools/a2faf6674aa37962079d6297e3a81dcfb59ef20f/resources/icons/16-apps-br.eng.silas.qpdftools.png
--------------------------------------------------------------------------------
/resources/icons/192-apps-br.eng.silas.qpdftools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silash35/qpdftools/a2faf6674aa37962079d6297e3a81dcfb59ef20f/resources/icons/192-apps-br.eng.silas.qpdftools.png
--------------------------------------------------------------------------------
/resources/icons/22-apps-br.eng.silas.qpdftools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silash35/qpdftools/a2faf6674aa37962079d6297e3a81dcfb59ef20f/resources/icons/22-apps-br.eng.silas.qpdftools.png
--------------------------------------------------------------------------------
/resources/icons/24-apps-br.eng.silas.qpdftools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silash35/qpdftools/a2faf6674aa37962079d6297e3a81dcfb59ef20f/resources/icons/24-apps-br.eng.silas.qpdftools.png
--------------------------------------------------------------------------------
/resources/icons/256-apps-br.eng.silas.qpdftools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silash35/qpdftools/a2faf6674aa37962079d6297e3a81dcfb59ef20f/resources/icons/256-apps-br.eng.silas.qpdftools.png
--------------------------------------------------------------------------------
/resources/icons/32-apps-br.eng.silas.qpdftools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silash35/qpdftools/a2faf6674aa37962079d6297e3a81dcfb59ef20f/resources/icons/32-apps-br.eng.silas.qpdftools.png
--------------------------------------------------------------------------------
/resources/icons/36-apps-br.eng.silas.qpdftools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silash35/qpdftools/a2faf6674aa37962079d6297e3a81dcfb59ef20f/resources/icons/36-apps-br.eng.silas.qpdftools.png
--------------------------------------------------------------------------------
/resources/icons/48-apps-br.eng.silas.qpdftools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silash35/qpdftools/a2faf6674aa37962079d6297e3a81dcfb59ef20f/resources/icons/48-apps-br.eng.silas.qpdftools.png
--------------------------------------------------------------------------------
/resources/icons/512-apps-br.eng.silas.qpdftools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silash35/qpdftools/a2faf6674aa37962079d6297e3a81dcfb59ef20f/resources/icons/512-apps-br.eng.silas.qpdftools.png
--------------------------------------------------------------------------------
/resources/icons/64-apps-br.eng.silas.qpdftools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silash35/qpdftools/a2faf6674aa37962079d6297e3a81dcfb59ef20f/resources/icons/64-apps-br.eng.silas.qpdftools.png
--------------------------------------------------------------------------------
/resources/icons/72-apps-br.eng.silas.qpdftools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silash35/qpdftools/a2faf6674aa37962079d6297e3a81dcfb59ef20f/resources/icons/72-apps-br.eng.silas.qpdftools.png
--------------------------------------------------------------------------------
/resources/icons/96-apps-br.eng.silas.qpdftools.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silash35/qpdftools/a2faf6674aa37962079d6297e3a81dcfb59ef20f/resources/icons/96-apps-br.eng.silas.qpdftools.png
--------------------------------------------------------------------------------
/resources/icons/sc-apps-br.eng.silas.qpdftools.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/resources/screenshots/compress-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silash35/qpdftools/a2faf6674aa37962079d6297e3a81dcfb59ef20f/resources/screenshots/compress-screen.png
--------------------------------------------------------------------------------
/resources/screenshots/menu-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silash35/qpdftools/a2faf6674aa37962079d6297e3a81dcfb59ef20f/resources/screenshots/menu-screen.png
--------------------------------------------------------------------------------
/resources/screenshots/merge-screen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/silash35/qpdftools/a2faf6674aa37962079d6297e3a81dcfb59ef20f/resources/screenshots/merge-screen.png
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | find_package(ECM REQUIRED NO_MODULE)
2 | set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
3 | include(KDEInstallDirs)
4 |
5 | # Add Qt
6 | find_package(Qt6 REQUIRED COMPONENTS Widgets Concurrent LinguistTools)
7 |
8 | set(SRC
9 | main.cpp
10 |
11 | ../resources/fallback-icons/fallback-icons.qrc
12 |
13 | api/externalSoftware.cpp
14 | api/ghostscript.cpp
15 | api/qpdf.cpp
16 |
17 | interface/mainwindow.ui
18 | interface/mainwindow.cpp
19 |
20 | interface/utils/fileDialog.cpp
21 |
22 | interface/pages/0-menu/menu.ui
23 | interface/pages/0-menu/menu.cpp
24 | interface/pages/1-compress/compress.ui
25 | interface/pages/1-compress/compress.cpp
26 | interface/pages/2-split/split.ui
27 | interface/pages/2-split/split.cpp
28 | interface/pages/3-merge/merge.ui
29 | interface/pages/3-merge/merge.cpp
30 | interface/pages/4-rotate/rotate.ui
31 | interface/pages/4-rotate/rotate.cpp
32 | )
33 | add_executable(qpdftools
34 | ${SRC}
35 | )
36 |
37 | set(TS_FILES languages/qpdftools_pt_BR.ts)
38 | qt6_add_translations(qpdftools TS_FILES ${TS_FILES})
39 |
40 | target_link_libraries(qpdftools
41 | PRIVATE
42 | Qt6::Core
43 | Qt6::Concurrent
44 | Qt6::Widgets
45 | )
46 |
47 | if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
48 | install(TARGETS qpdftools DESTINATION ${KDE_INSTALL_BINDIR})
49 | endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
50 |
--------------------------------------------------------------------------------
/src/api/externalSoftware.cpp:
--------------------------------------------------------------------------------
1 | #include "externalSoftware.hpp"
2 |
3 | ExternalSoftware::ExternalSoftware(QString name, QString command)
4 | : softwareName(name), softwareCommand(command) {}
5 |
6 | void ExternalSoftware::run(const QStringList &arguments, const QString &dir) {
7 | QProcess process;
8 |
9 | // Set working directory
10 | if (dir != "default") {
11 | process.setWorkingDirectory(dir);
12 | qInfo() << "Using working directory: " << dir;
13 | }
14 |
15 | // Start process
16 | qInfo() << "Executing " << softwareName << " with the arguments:" << arguments;
17 | process.start(softwareCommand, arguments, QIODevice::ReadWrite);
18 |
19 | process.closeWriteChannel();
20 |
21 | // Wait for process to finish
22 | process.waitForFinished(120 * 1000); // Increase wait time to 2 minutes, for large files
23 |
24 | // Check for errors
25 | QString error = process.readAllStandardError();
26 | if (!error.isEmpty()) {
27 | qCritical() << "Error in " + softwareName + ": " + error;
28 | throw "Error in " + softwareName + ": " + error;
29 | }
30 |
31 | qInfo() << "Finished executing " + softwareName << "\n";
32 | }
33 |
--------------------------------------------------------------------------------
/src/api/externalSoftware.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 |
7 | class ExternalSoftware {
8 | protected:
9 | QString softwareName;
10 | QString softwareCommand;
11 |
12 | void run(const QStringList &arguments, const QString &dir = "default");
13 |
14 | public:
15 | ExternalSoftware(QString name, QString command);
16 | };
17 |
--------------------------------------------------------------------------------
/src/api/ghostscript.cpp:
--------------------------------------------------------------------------------
1 | #include "ghostscript.hpp"
2 |
3 | Ghostscript::Ghostscript() : ExternalSoftware("Ghostscript", "gs") {}
4 |
5 | void Ghostscript::compressPDF(const QString &input, const QString &output, CompressionMode mode) {
6 | // Create a temp file if input and output are the same. Prevents file corruption
7 | QString gsOutput = (input == output) ? QDir::tempPath() + "/temp_output.pdf" : output;
8 |
9 | // gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/mode -dNOPAUSE -dBATCH
10 | // -sOutputFile=gsOutput.pdf input.pdf
11 | QStringList arguments = {"-sDEVICE=pdfwrite", "-dCompatibilityLevel=1.4"};
12 |
13 | if (mode == screen) {
14 | arguments << "-dPDFSETTINGS=/screen";
15 | } else if (mode == ebook) {
16 | arguments << "-dPDFSETTINGS=/ebook";
17 | } else if (mode == printer) {
18 | arguments << "-dPDFSETTINGS=/printer";
19 | } else if (mode == prepress) {
20 | arguments << "-dPDFSETTINGS=/prepress";
21 | }
22 |
23 | arguments << "-dNOPAUSE"
24 | << "-dBATCH" << "-sOutputFile=" + gsOutput << input;
25 |
26 | run(arguments);
27 |
28 | // Move temp file to the right place if needed
29 | if (gsOutput != output) {
30 | QFile::remove(output);
31 | QFile::rename(gsOutput, output);
32 | }
33 | }
34 |
35 | void Ghostscript::generateThumbnail(const QString &input, const QString &output) {
36 | // gs -q -o output.jpg -sDEVICE=jpeg -dLastPage=1 -dUseCropBox input.pdf
37 | QStringList arguments = {
38 | "-q", "-o", output, "-sDEVICE=jpeg", "-dLastPage=1", "-dUseCropBox", input};
39 |
40 | run(arguments);
41 | }
42 |
43 | Ghostscript ghostscript;
44 |
--------------------------------------------------------------------------------
/src/api/ghostscript.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "externalSoftware.hpp"
4 |
5 | #include
6 | #include
7 |
8 | class Ghostscript : public ExternalSoftware {
9 | public:
10 | Ghostscript();
11 |
12 | enum CompressionMode { screen, ebook, printer, prepress };
13 |
14 | void compressPDF(const QString &input, const QString &output, CompressionMode mode);
15 | void generateThumbnail(const QString &input, const QString &output);
16 | };
17 |
18 | extern Ghostscript ghostscript;
19 |
--------------------------------------------------------------------------------
/src/api/qpdf.cpp:
--------------------------------------------------------------------------------
1 | #include "qpdf.hpp"
2 |
3 | Qpdf::Qpdf() : ExternalSoftware("qpdf", "qpdf") {}
4 |
5 | void Qpdf::splitPDF(const QString &input, const QString &outputFolder) {
6 | QString output = QFileInfo(input).completeBaseName() + ".pdf";
7 |
8 | // qpdf input.pdf output.pdf --split-pages
9 | QStringList arguments = {input, output, "--split-pages"};
10 |
11 | run(arguments, outputFolder);
12 | }
13 |
14 | void Qpdf::splitPDF(const QString &input, const QString &output, int firstPage, int lastPage) {
15 | // qpdf input.pdf --pages . firstPage-lastPage -- output.pdf
16 | QStringList arguments = {
17 | input, "--pages", ".", QString::number(firstPage) + "-" + QString::number(lastPage)};
18 |
19 | if (input == output) {
20 | arguments << "--" << "--replace-input";
21 | } else {
22 | arguments << "--" << output;
23 | }
24 |
25 | run(arguments);
26 | }
27 |
28 | void Qpdf::mergePDF(const QStringList &inputs, const QString &output) {
29 | // Create a temp file if input and output are the same. Prevents file corruption
30 | QString qpdfOutput = (inputs.contains(output)) ? QDir::tempPath() + "/temp_output.pdf" : output;
31 |
32 | // qpdf --empty --pages inputs[0].pdf inputs[1].pdf -- qpdfOutput.pdf
33 | QStringList arguments = {"--empty", "--pages"};
34 | arguments.append(inputs);
35 | arguments << "--" << qpdfOutput;
36 |
37 | run(arguments);
38 |
39 | // Move temp file to the right place if needed
40 | if (qpdfOutput != output) {
41 | QFile::remove(output);
42 | QFile::rename(qpdfOutput, output);
43 | }
44 | }
45 |
46 | void Qpdf::rotatePDF(const QString &input, const QString &output, int angle) {
47 | // qpdf in.pdf out.pdf --rotate=angle
48 | QStringList arguments = {input};
49 |
50 | if (input == output) {
51 | arguments << "--replace-input";
52 | } else {
53 | arguments << output;
54 | }
55 |
56 | arguments << "--rotate=" + QString::number(angle);
57 |
58 | run(arguments);
59 | }
60 |
61 | Qpdf qpdf;
--------------------------------------------------------------------------------
/src/api/qpdf.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "externalSoftware.hpp"
4 |
5 | #include
6 | #include
7 |
8 | class Qpdf : public ExternalSoftware {
9 | public:
10 | Qpdf();
11 |
12 | void splitPDF(const QString &input, const QString &outputFolder);
13 | void splitPDF(const QString &input, const QString &output, int firstPage, int lastPage);
14 |
15 | void mergePDF(const QStringList &inputs, const QString &output);
16 |
17 | void rotatePDF(const QString &input, const QString &output, int angle);
18 | };
19 |
20 | extern Qpdf qpdf;
21 |
--------------------------------------------------------------------------------
/src/interface/mainwindow.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.hpp"
2 | #include "ui_mainwindow.h"
3 |
4 | MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
5 | // Main
6 | ui->setupUi(this);
7 |
8 | MenuPage *menuPage = new MenuPage(this);
9 | ui->stackedWidget->addWidget(menuPage);
10 | connect(menuPage, &MenuPage::setPage, this, &MainWindow::setPage);
11 |
12 | CompressPage *compressPage = new CompressPage(this);
13 | ui->stackedWidget->addWidget(compressPage);
14 | connect(compressPage, &CompressPage::setPage, this, &MainWindow::setPage);
15 | connect(compressPage, &CompressPage::runAsyncFunction, this, &MainWindow::runAsyncFunction);
16 |
17 | SplitPage *splitPage = new SplitPage(this);
18 | ui->stackedWidget->addWidget(splitPage);
19 | connect(splitPage, &SplitPage::setPage, this, &MainWindow::setPage);
20 | connect(splitPage, &SplitPage::runAsyncFunction, this, &MainWindow::runAsyncFunction);
21 |
22 | MergePage *mergePage = new MergePage(this);
23 | ui->stackedWidget->addWidget(mergePage);
24 | connect(mergePage, &MergePage::setPage, this, &MainWindow::setPage);
25 | connect(mergePage, &MergePage::runAsyncFunction, this, &MainWindow::runAsyncFunction);
26 |
27 | RotatePage *rotatePage = new RotatePage(this);
28 | ui->stackedWidget->addWidget(rotatePage);
29 | connect(rotatePage, &RotatePage::setPage, this, &MainWindow::setPage);
30 | connect(rotatePage, &RotatePage::runAsyncFunction, this, &MainWindow::runAsyncFunction);
31 |
32 | connect(this, &MainWindow::showMessageSignal, this, &MainWindow::showMessageSlot);
33 | }
34 |
35 | MainWindow::~MainWindow() { delete ui; }
36 |
37 | // Public Slots
38 | void MainWindow::showMessageSlot(const QString &message, int timeout) {
39 | ui->statusBar->showMessage(message, timeout);
40 | }
41 |
42 | void MainWindow::setPage(int newPage) { ui->stackedWidget->setCurrentIndex(newPage); }
43 |
44 | void MainWindow::runAsyncFunction(std::function asyncFunction) {
45 | ui->statusBar->showMessage(tr("Processing..."));
46 |
47 | QFuture future =
48 | QtConcurrent::run(asyncFunction)
49 | .then([this] { emit showMessageSignal(tr("Success!"), 5000); })
50 | .onFailed(qApp,
51 | [this](char *error) {
52 | QMessageBox::warning(this, tr("ERROR"), error);
53 | emit showMessageSignal(tr("Failed"), 5000);
54 | })
55 | .onFailed(qApp, [this]() {
56 | QMessageBox::warning(this, tr("ERROR"),
57 | tr("An unknown error has occurred. Read the terminal output for more information"));
58 | emit showMessageSignal(tr("Failed"), 5000);
59 | });
60 | }
61 |
--------------------------------------------------------------------------------
/src/interface/mainwindow.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "pages/0-menu/menu.hpp"
9 | #include "pages/1-compress/compress.hpp"
10 | #include "pages/2-split/split.hpp"
11 | #include "pages/3-merge/merge.hpp"
12 | #include "pages/4-rotate/rotate.hpp"
13 |
14 | namespace Ui {
15 | class MainWindow;
16 | }
17 |
18 | class MainWindow : public QMainWindow {
19 | Q_OBJECT
20 | public:
21 | MainWindow(QWidget *parent = nullptr);
22 | ~MainWindow();
23 |
24 | public slots:
25 | void setPage(int newPage);
26 | void runAsyncFunction(std::function function);
27 | void showMessageSlot(const QString &message, int timeout = 0);
28 |
29 | signals:
30 | void showMessageSignal(const QString &message, int timeout = 0);
31 |
32 | private:
33 | Ui::MainWindow *ui;
34 | };
35 |
--------------------------------------------------------------------------------
/src/interface/mainwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 576
10 | 384
11 |
12 |
13 |
14 |
15 | .icon24 {
16 | icon-size: 24px;
17 | }
18 | .icon32 {
19 | icon-size: 32px;
20 | }
21 |
22 |
23 |
24 | Qpdf Tools
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/interface/pages/0-menu/menu.cpp:
--------------------------------------------------------------------------------
1 | #include "menu.hpp"
2 | #include "ui_menu.h"
3 |
4 | MenuPage::MenuPage(QWidget *parent) : QWidget(parent), ui(new Ui::MenuPage) { ui->setupUi(this); }
5 |
6 | MenuPage::~MenuPage() { delete ui; }
7 |
8 | void MenuPage::on_btn_compress_clicked() { emit setPage(1); }
9 |
10 | void MenuPage::on_btn_split_clicked() { emit setPage(2); }
11 |
12 | void MenuPage::on_btn_merge_clicked() { emit setPage(3); }
13 |
14 | void MenuPage::on_btn_rotate_clicked() { emit setPage(4); }
15 |
--------------------------------------------------------------------------------
/src/interface/pages/0-menu/menu.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 |
5 | namespace Ui {
6 | class MenuPage;
7 | }
8 |
9 | class MenuPage : public QWidget {
10 | Q_OBJECT
11 |
12 | public:
13 | explicit MenuPage(QWidget *parent = nullptr);
14 | ~MenuPage();
15 |
16 | signals:
17 | void setPage(int newPage);
18 |
19 | private slots:
20 | void on_btn_compress_clicked();
21 |
22 | void on_btn_split_clicked();
23 |
24 | void on_btn_merge_clicked();
25 |
26 | void on_btn_rotate_clicked();
27 |
28 | private:
29 | Ui::MenuPage *ui;
30 | };
31 |
--------------------------------------------------------------------------------
/src/interface/pages/0-menu/menu.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MenuPage
4 |
5 |
6 |
7 | QLabel {
8 | font-weight: bold;
9 | }
10 | QPushButton {
11 | font-size: 11pt;
12 | icon-size: 32px;
13 | }
14 |
15 |
16 |
17 | -
18 |
19 |
20 | 8
21 |
22 | -
23 |
24 |
25 | Qpdf Tools
26 |
27 |
28 |
29 | 20
30 |
31 |
32 |
33 | Qt::AlignCenter
34 |
35 |
36 |
37 | -
38 |
39 |
40 | Tools for manage PDFs
41 |
42 |
43 |
44 | 16
45 |
46 |
47 |
48 | Qt::AlignCenter
49 |
50 |
51 |
52 |
53 |
54 | -
55 |
56 |
57 | 12
58 |
59 |
60 | 4
61 |
62 |
63 | 4
64 |
65 | -
66 |
67 |
68 |
69 |
70 |
71 | Compress a PDF file
72 |
73 |
74 |
75 |
76 |
77 |
78 | -
79 |
80 |
81 |
82 |
83 |
84 | Split a PDF file
85 |
86 |
87 |
88 |
89 |
90 |
91 | -
92 |
93 |
94 |
95 |
96 |
97 | Rotate a PDF file
98 |
99 |
100 |
101 |
102 |
103 |
104 | -
105 |
106 |
107 |
108 |
109 |
110 | Merge PDF files
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/src/interface/pages/1-compress/compress.cpp:
--------------------------------------------------------------------------------
1 | #include "compress.hpp"
2 | #include "ui_compress.h"
3 |
4 | #include "api/ghostscript.hpp"
5 | #include "interface/utils/fileDialog.hpp"
6 |
7 | CompressPage::CompressPage(QWidget *parent) : QWidget(parent), ui(new Ui::CompressPage) {
8 | ui->setupUi(this);
9 | }
10 |
11 | CompressPage::~CompressPage() { delete ui; }
12 |
13 | void CompressPage::on_tbtn_return_clicked() { emit setPage(0); }
14 |
15 | void CompressPage::on_btn_selectFile_clicked() {
16 | ui->ln_file->setText(fileDialog.getOpenFileName(this));
17 | ui->ln_file->setFocus();
18 | }
19 |
20 | void CompressPage::on_tbtn_pdfCompress_clicked() {
21 | QString input = ui->ln_file->text();
22 | if (!QFile::exists(input)) {
23 | QMessageBox::warning(this, tr("Warning"), tr("You need to select a valide PDF file"));
24 | return;
25 | }
26 |
27 | Ghostscript::CompressionMode mode;
28 |
29 | if (ui->rbtn_screen->isChecked()) {
30 | mode = Ghostscript::screen;
31 | } else if (ui->rbtn_ebook->isChecked()) {
32 | mode = Ghostscript::ebook;
33 | } else if (ui->rbtn_printer->isChecked()) {
34 | mode = Ghostscript::printer;
35 | } else if (ui->rbtn_prepress->isChecked()) {
36 | mode = Ghostscript::prepress;
37 | } else {
38 | QMessageBox::warning(this, tr("Warning"), tr("You need to select a compression mode"));
39 | return;
40 | }
41 |
42 | QString output = fileDialog.getSaveFileName(this);
43 | if (output.isEmpty()) {
44 | return;
45 | }
46 |
47 | emit runAsyncFunction([input, output, mode] { ghostscript.compressPDF(input, output, mode); });
48 | }
49 |
--------------------------------------------------------------------------------
/src/interface/pages/1-compress/compress.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | namespace Ui {
7 | class CompressPage;
8 | }
9 |
10 | class CompressPage : public QWidget {
11 | Q_OBJECT
12 |
13 | public:
14 | explicit CompressPage(QWidget *parent = nullptr);
15 | ~CompressPage();
16 |
17 | signals:
18 | void setPage(int newPage);
19 | void runAsyncFunction(std::function asyncFunction);
20 |
21 | private slots:
22 | void on_tbtn_return_clicked();
23 |
24 | void on_btn_selectFile_clicked();
25 |
26 | void on_tbtn_pdfCompress_clicked();
27 |
28 | private:
29 | Ui::CompressPage *ui;
30 | };
31 |
--------------------------------------------------------------------------------
/src/interface/pages/1-compress/compress.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | CompressPage
4 |
5 |
6 | -
7 |
8 |
9 | Return
10 |
11 |
12 |
13 |
14 |
15 | Esc
16 |
17 |
18 |
19 | -
20 |
21 | -
22 |
23 |
24 | Select PDF
25 |
26 |
27 |
28 | -
29 |
30 |
31 |
32 |
33 | -
34 |
35 |
36 | Select the compression mode:
37 |
38 |
39 | -
40 |
41 |
42 | Super low resolution (Screen Optimized)
43 |
44 |
45 |
46 | -
47 |
48 |
49 | Low resolution (For Ebooks)
50 |
51 |
52 |
53 | -
54 |
55 |
56 | Normal resolution (For printing)
57 |
58 |
59 |
60 | -
61 |
62 |
63 | High resolution
64 |
65 |
66 |
67 |
68 |
69 |
70 | -
71 |
72 |
73 | Compress PDF
74 |
75 |
76 | icon32
77 |
78 |
79 | Qt::ToolButtonTextUnderIcon
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/src/interface/pages/2-split/split.cpp:
--------------------------------------------------------------------------------
1 | #include "split.hpp"
2 | #include "ui_split.h"
3 |
4 | SplitPage::SplitPage(QWidget *parent) : QWidget(parent), ui(new Ui::SplitPage) {
5 | ui->setupUi(this);
6 | }
7 |
8 | SplitPage::~SplitPage() { delete ui; }
9 |
10 | void SplitPage::on_tbtn_return_clicked() { emit setPage(0); }
11 |
12 | void SplitPage::on_btn_selectFile_clicked() {
13 | ui->ln_file->setText(fileDialog.getOpenFileName(this));
14 | ui->ln_file->setFocus();
15 | }
16 |
17 | void SplitPage::on_rbtn_extractAll_clicked() {
18 | ui->label_2->hide();
19 | ui->label->hide();
20 | ui->spinBox_fistPage->hide();
21 | ui->spinBox_lastPage->hide();
22 | }
23 |
24 | void SplitPage::on_rbtn_splitRange_clicked() {
25 | ui->label_2->show();
26 | ui->label->show();
27 | ui->spinBox_fistPage->show();
28 | ui->spinBox_lastPage->show();
29 | }
30 |
31 | void SplitPage::on_spinBox_fistPage_valueChanged(int arg1) {
32 | ui->spinBox_lastPage->setMinimum(arg1);
33 | }
34 |
35 | void SplitPage::on_tbtn_pdfSplit_clicked() {
36 | QString input = ui->ln_file->text();
37 | if (!QFile::exists(input)) {
38 | QMessageBox::warning(this, tr("Warning"), tr("You need to select a valide PDF file"));
39 | return;
40 | }
41 |
42 | if (ui->rbtn_extractAll->isChecked()) {
43 | QString outputFolder = QFileDialog::getExistingDirectory(this, tr("Select Output Folder"));
44 | if (outputFolder == "") {
45 | return;
46 | }
47 |
48 | emit runAsyncFunction([input, outputFolder] { qpdf.splitPDF(input, outputFolder); });
49 |
50 | } else if (ui->rbtn_splitRange->isChecked()) {
51 | QString output = fileDialog.getSaveFileName(this);
52 | if (output.isEmpty()) {
53 | return;
54 | }
55 |
56 | int firstPage = ui->spinBox_fistPage->value();
57 | int lastPage = ui->spinBox_lastPage->value();
58 |
59 | emit runAsyncFunction(
60 | [input, output, firstPage, lastPage] { qpdf.splitPDF(input, output, firstPage, lastPage); });
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/interface/pages/2-split/split.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include "api/qpdf.hpp"
7 | #include "interface/utils/fileDialog.hpp"
8 |
9 | namespace Ui {
10 | class SplitPage;
11 | }
12 |
13 | class SplitPage : public QWidget {
14 | Q_OBJECT
15 |
16 | public:
17 | explicit SplitPage(QWidget *parent = nullptr);
18 | ~SplitPage();
19 |
20 | signals:
21 | void setPage(int newPage);
22 | void runAsyncFunction(std::function asyncFunction);
23 |
24 | private slots:
25 | void on_tbtn_return_clicked();
26 |
27 | void on_btn_selectFile_clicked();
28 |
29 | void on_rbtn_extractAll_clicked();
30 |
31 | void on_rbtn_splitRange_clicked();
32 |
33 | void on_spinBox_fistPage_valueChanged(int arg1);
34 |
35 | void on_tbtn_pdfSplit_clicked();
36 |
37 | private:
38 | Ui::SplitPage *ui;
39 | };
40 |
--------------------------------------------------------------------------------
/src/interface/pages/2-split/split.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | SplitPage
4 |
5 |
6 | -
7 |
8 |
9 | Return
10 |
11 |
12 |
13 |
14 |
15 | Esc
16 |
17 |
18 |
19 | -
20 |
21 | -
22 |
23 |
24 | Select PDF
25 |
26 |
27 |
28 | -
29 |
30 |
31 |
32 |
33 | -
34 |
35 | -
36 |
37 |
38 | Split by range
39 |
40 |
41 | true
42 |
43 |
44 |
45 | -
46 |
47 |
48 | Extract all pages
49 |
50 |
51 |
52 |
53 |
54 | -
55 |
56 | -
57 |
58 | -
59 |
60 |
61 | From page:
62 |
63 |
64 |
65 | -
66 |
67 |
68 | 1
69 |
70 |
71 | 999999999
72 |
73 |
74 |
75 |
76 |
77 | -
78 |
79 | -
80 |
81 |
82 | To page:
83 |
84 |
85 |
86 | -
87 |
88 |
89 | 1
90 |
91 |
92 | 999999999
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | -
101 |
102 |
103 | Qt::Vertical
104 |
105 |
106 | QSizePolicy::Expanding
107 |
108 |
109 |
110 | -
111 |
112 |
113 | Split PDF
114 |
115 |
116 | icon32
117 |
118 |
119 | Qt::ToolButtonTextUnderIcon
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
--------------------------------------------------------------------------------
/src/interface/pages/3-merge/merge.cpp:
--------------------------------------------------------------------------------
1 | #include "merge.hpp"
2 | #include "ui_merge.h"
3 |
4 | MergePage::MergePage(QWidget *parent) : QWidget(parent), ui(new Ui::MergePage) {
5 | ui->setupUi(this);
6 | }
7 |
8 | MergePage::~MergePage() { delete ui; }
9 |
10 | void MergePage::on_tbtn_return_clicked() { emit setPage(0); }
11 |
12 | void MergePage::on_btn_Madd_clicked() {
13 | QStringList files = fileDialog.getOpenFileNames(this);
14 | ui->list_toMerge->addItems(files);
15 | }
16 |
17 | void MergePage::on_btn_Mrm_clicked() {
18 | if ((ui->list_toMerge->currentRow() >= 0) and (ui->list_toMerge->count() > 0)) {
19 | delete ui->list_toMerge->takeItem(ui->list_toMerge->row(ui->list_toMerge->currentItem()));
20 | }
21 | }
22 |
23 | void MergePage::on_btn_Mup_clicked() {
24 | int currentRow = ui->list_toMerge->currentRow();
25 |
26 | if (currentRow > 0) {
27 | QString aux = ui->list_toMerge->item(currentRow - 1)->text();
28 |
29 | ui->list_toMerge->item(currentRow - 1)->setText(ui->list_toMerge->item(currentRow)->text());
30 | ui->list_toMerge->item(currentRow)->setText(aux);
31 |
32 | ui->list_toMerge->setCurrentRow(currentRow - 1);
33 | }
34 |
35 | ui->list_toMerge->update();
36 | }
37 |
38 | void MergePage::on_btn_Mdown_clicked() {
39 | int currentRow = ui->list_toMerge->currentRow();
40 |
41 | if ((currentRow >= 0) and (ui->list_toMerge->count() > 0) and
42 | (ui->list_toMerge->count() != (currentRow + 1))) {
43 | QString aux = ui->list_toMerge->item(currentRow + 1)->text();
44 |
45 | ui->list_toMerge->item(currentRow + 1)->setText(ui->list_toMerge->item(currentRow)->text());
46 | ui->list_toMerge->item(currentRow)->setText(aux);
47 |
48 | ui->list_toMerge->setCurrentRow(currentRow + 1);
49 | }
50 |
51 | ui->list_toMerge->update();
52 | }
53 |
54 | void MergePage::on_tbtn_pdfMerge_clicked() {
55 | if (ui->list_toMerge->count() <= 1) {
56 | QMessageBox::warning(
57 | this, tr("Warning"), tr("You need to add two or more files to be able to merge them"));
58 | return;
59 | }
60 |
61 | QString output = fileDialog.getSaveFileName(this);
62 | if (output.isEmpty()) {
63 | return;
64 | }
65 |
66 | QStringList inputs;
67 | for (int i = 0; i < ui->list_toMerge->count(); ++i)
68 | inputs << ui->list_toMerge->item(i)->text();
69 |
70 | emit runAsyncFunction([inputs, output] { qpdf.mergePDF(inputs, output); });
71 | }
--------------------------------------------------------------------------------
/src/interface/pages/3-merge/merge.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include "api/qpdf.hpp"
7 | #include "interface/utils/fileDialog.hpp"
8 |
9 | namespace Ui {
10 | class MergePage;
11 | }
12 |
13 | class MergePage : public QWidget {
14 | Q_OBJECT
15 |
16 | public:
17 | explicit MergePage(QWidget *parent = nullptr);
18 | ~MergePage();
19 |
20 | signals:
21 | void setPage(int newPage);
22 | void runAsyncFunction(std::function asyncFunction);
23 |
24 | private slots:
25 | void on_tbtn_return_clicked();
26 |
27 | void on_btn_Madd_clicked();
28 |
29 | void on_btn_Mrm_clicked();
30 |
31 | void on_btn_Mup_clicked();
32 |
33 | void on_btn_Mdown_clicked();
34 |
35 | void on_tbtn_pdfMerge_clicked();
36 |
37 | private:
38 | Ui::MergePage *ui;
39 | };
40 |
--------------------------------------------------------------------------------
/src/interface/pages/3-merge/merge.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MergePage
4 |
5 |
6 | -
7 |
8 |
9 | Return
10 |
11 |
12 |
13 |
14 |
15 | Esc
16 |
17 |
18 |
19 | -
20 |
21 |
22 | -
23 |
24 | -
25 |
26 |
27 | Add a PDF file
28 |
29 |
30 |
31 |
32 |
33 | icon24
34 |
35 |
36 |
37 | -
38 |
39 |
40 | Remove a PDF file
41 |
42 |
43 |
44 |
45 |
46 | icon24
47 |
48 |
49 |
50 | -
51 |
52 |
53 | Qt::Horizontal
54 |
55 |
56 |
57 | -
58 |
59 |
60 | Change merge order (move selected item up)
61 |
62 |
63 |
64 |
65 |
66 | icon24
67 |
68 |
69 |
70 | -
71 |
72 |
73 | Change merge order (move selected item down)
74 |
75 |
76 |
77 |
78 |
79 | icon24
80 |
81 |
82 |
83 |
84 |
85 | -
86 |
87 |
88 | Merge PDFs
89 |
90 |
91 | icon32
92 |
93 |
94 | Qt::ToolButtonTextUnderIcon
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/src/interface/pages/4-rotate/rotate.cpp:
--------------------------------------------------------------------------------
1 | #include "rotate.hpp"
2 | #include "ui_rotate.h"
3 |
4 | RotatePage::RotatePage(QWidget *parent) : QWidget(parent), ui(new Ui::RotatePage) {
5 | ui->setupUi(this);
6 |
7 | ui->btn_left->hide();
8 | ui->btn_right->hide();
9 | ui->label_pdfCover->hide();
10 | }
11 |
12 | RotatePage::~RotatePage() { delete ui; }
13 |
14 | void RotatePage::on_tbtn_return_clicked() { emit setPage(0); }
15 |
16 | void RotatePage::on_btn_selectFile_clicked() {
17 | ui->ln_file->setText(fileDialog.getOpenFileName(this));
18 | ui->ln_file->setFocus();
19 | }
20 |
21 | void RotatePage::on_ln_file_textChanged(const QString &pdfPath) {
22 | rotate = 0;
23 |
24 | if (QFile::exists(pdfPath)) {
25 | ui->btn_left->show();
26 | ui->btn_right->show();
27 | ui->label_pdfCover->show();
28 |
29 | QtConcurrent::run([this, pdfPath] {
30 | ghostscript.generateThumbnail(pdfPath, pdfCoverPath);
31 | QPixmap pdfCover(pdfCoverPath);
32 | ui->label_pdfCover->setPixmap(pdfCover.scaled(300, 300, Qt::KeepAspectRatio));
33 | }).onFailed(qApp, [this]() {
34 | QMessageBox::warning(this, tr("ERROR"), tr("Failed to generate thumbnail"));
35 | });
36 |
37 | } else {
38 | ui->btn_left->hide();
39 | ui->btn_right->hide();
40 | ui->label_pdfCover->hide();
41 | }
42 | }
43 |
44 | void RotatePage::on_btn_left_clicked() {
45 | if (rotate <= 0) {
46 | rotate = 360;
47 | }
48 |
49 | rotate -= 90;
50 | QTransform rote;
51 | rote = rote.rotate(rotate);
52 |
53 | QPixmap pdfCover(pdfCoverPath);
54 | pdfCover = QPixmap(pdfCover.transformed(rote));
55 | ui->label_pdfCover->setPixmap(pdfCover.scaled(300, 300, Qt::KeepAspectRatio));
56 | }
57 |
58 | void RotatePage::on_btn_right_clicked() {
59 | if (rotate >= 360) {
60 | rotate = 0;
61 | }
62 |
63 | rotate += 90;
64 | QTransform rote;
65 | rote = rote.rotate(rotate);
66 |
67 | QPixmap pdfCover(pdfCoverPath);
68 | pdfCover = QPixmap(pdfCover.transformed(rote));
69 | ui->label_pdfCover->setPixmap(pdfCover.scaled(300, 300, Qt::KeepAspectRatio));
70 | }
71 |
72 | void RotatePage::on_tbtn_pdfRotate_clicked() {
73 | if (!QFile::exists(ui->ln_file->text())) {
74 | QMessageBox::warning(this, tr("Warning"), tr("You need to select a valide PDF file"));
75 | return;
76 | }
77 |
78 | QString output = fileDialog.getSaveFileName(this);
79 | if (output.isEmpty()) {
80 | return;
81 | }
82 | QString input = ui->ln_file->text();
83 | int angle = rotate;
84 |
85 | emit runAsyncFunction([input, output, angle] { qpdf.rotatePDF(input, output, angle); });
86 | }
87 |
--------------------------------------------------------------------------------
/src/interface/pages/4-rotate/rotate.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include "api/ghostscript.hpp"
9 | #include "api/qpdf.hpp"
10 | #include "interface/utils/fileDialog.hpp"
11 |
12 | namespace Ui {
13 | class RotatePage;
14 | }
15 |
16 | class RotatePage : public QWidget {
17 | Q_OBJECT
18 |
19 | public:
20 | explicit RotatePage(QWidget *parent = nullptr);
21 | ~RotatePage();
22 |
23 | signals:
24 | void setPage(int newPage);
25 | void runAsyncFunction(std::function asyncFunction);
26 |
27 | private slots:
28 | void on_tbtn_return_clicked();
29 |
30 | void on_btn_selectFile_clicked();
31 |
32 | void on_ln_file_textChanged(const QString &arg1);
33 |
34 | void on_btn_left_clicked();
35 |
36 | void on_btn_right_clicked();
37 |
38 | void on_tbtn_pdfRotate_clicked();
39 |
40 | private:
41 | Ui::RotatePage *ui;
42 | int rotate{0};
43 |
44 | QString pdfCoverPath = QDir::tempPath() + "/pdfCover.jpeg";
45 | };
46 |
--------------------------------------------------------------------------------
/src/interface/pages/4-rotate/rotate.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | RotatePage
4 |
5 |
6 | -
7 |
8 |
9 | Return
10 |
11 |
12 |
13 |
14 |
15 | Esc
16 |
17 |
18 |
19 | -
20 |
21 | -
22 |
23 |
24 | Select PDF
25 |
26 |
27 |
28 | -
29 |
30 |
31 |
32 |
33 | -
34 |
35 | -
36 |
37 |
38 | Qt::Horizontal
39 |
40 |
41 |
42 | -
43 |
44 | -
45 |
46 |
47 | -
48 |
49 | -
50 |
51 |
52 | Left
53 |
54 |
55 | Rotate the PDF 90 degrees to the left
56 |
57 |
58 |
59 |
60 |
61 | icon24
62 |
63 |
64 |
65 | -
66 |
67 |
68 | Right
69 |
70 |
71 | Rotate the PDF 90 degrees to the right
72 |
73 |
74 |
75 |
76 |
77 | icon24
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | -
86 |
87 |
88 | Qt::Horizontal
89 |
90 |
91 |
92 |
93 |
94 | -
95 |
96 |
97 | Qt::Vertical
98 |
99 |
100 |
101 | -
102 |
103 |
104 | Rotate PDF
105 |
106 |
107 | icon32
108 |
109 |
110 | Qt::ToolButtonTextUnderIcon
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/src/interface/utils/fileDialog.cpp:
--------------------------------------------------------------------------------
1 | #include "fileDialog.hpp"
2 |
3 | FileDialog::FileDialog(QString filter, QString extension) : filter(filter), extension(extension) {}
4 |
5 | // Private Methods
6 |
7 | bool FileDialog::directoryIsValid(const QString &dir) {
8 | QDir qDir(dir);
9 | return qDir.exists();
10 | }
11 |
12 | void FileDialog::setLastDirectory(const QString &dir) {
13 | if (directoryIsValid(dir)) {
14 | lastDirectory = dir;
15 | }
16 | }
17 |
18 | void FileDialog::setLastDirectoryByFile(const QString &file) {
19 | setLastDirectory(QFileInfo(file).absoluteDir().absolutePath());
20 | }
21 |
22 | // Public Methods
23 |
24 | QString FileDialog::getOpenFileName(QWidget *parent) {
25 | QString file =
26 | QFileDialog::getOpenFileName(parent, tr("Select the PDF file"), lastDirectory, filter);
27 |
28 | if (!file.isEmpty()) {
29 | setLastDirectoryByFile(file);
30 | }
31 | return file;
32 | }
33 |
34 | QString FileDialog::getSaveFileName(QWidget *parent) {
35 | QString file = QFileDialog::getSaveFileName(parent, tr("Save file"), lastDirectory, filter);
36 |
37 | if (!file.isEmpty()) {
38 | if (!file.endsWith(extension)) {
39 | file.append(extension);
40 | }
41 | setLastDirectoryByFile(file);
42 | }
43 |
44 | return file;
45 | }
46 |
47 | QStringList FileDialog::getOpenFileNames(QWidget *parent) {
48 | QStringList files =
49 | QFileDialog::getOpenFileNames(parent, tr("Select the PDF files"), lastDirectory, filter);
50 | QStringList validFiles;
51 |
52 | for (int i = 0; i < files.count(); ++i) {
53 | qInfo() << i << ": " << files[i];
54 | if (QFile::exists(files[i])) {
55 | validFiles.push_back(files[i]);
56 | }
57 | }
58 |
59 | if (!validFiles.isEmpty()) {
60 | setLastDirectoryByFile(validFiles.last());
61 | }
62 |
63 | return validFiles;
64 | }
65 |
66 | // Initialize only allowing PDF files
67 | FileDialog fileDialog("PDF - Portable Document Format (*.pdf *.PDF)", ".pdf");
--------------------------------------------------------------------------------
/src/interface/utils/fileDialog.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | class FileDialog : public QObject {
9 | Q_OBJECT
10 |
11 | private:
12 | QString filter; // What type of files are allowed
13 | QString extension;
14 |
15 | // Keep track of the last directory opened,
16 | // so the user does not have to select the same directory every time
17 | QString lastDirectory = QDir::homePath();
18 |
19 | bool directoryIsValid(const QString &dir);
20 |
21 | void setLastDirectory(const QString &dir);
22 | void setLastDirectoryByFile(const QString &file);
23 |
24 | public:
25 | FileDialog(QString filter, QString extension);
26 |
27 | QString getOpenFileName(QWidget *parent);
28 | QString getSaveFileName(QWidget *parent);
29 | QStringList getOpenFileNames(QWidget *parent);
30 | };
31 |
32 | extern FileDialog fileDialog;
33 |
--------------------------------------------------------------------------------
/src/languages/qpdftools_pt_BR.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CompressPage
6 |
7 |
8 | Return
9 | Voltar
10 |
11 |
12 |
13 | Select PDF
14 | Selecionar PDF
15 |
16 |
17 |
18 | Select the compression mode:
19 | Selecione o modo de compressão:
20 |
21 |
22 |
23 | Super low resolution (Screen Optimized)
24 | Super baixa resolução (Otimizado para tela)
25 |
26 |
27 |
28 | Low resolution (For Ebooks)
29 | Baixa resolução (Para Ebooks)
30 |
31 |
32 |
33 | Normal resolution (For printing)
34 | Resolução normal (Para Impressão)
35 |
36 |
37 |
38 | High resolution
39 | Alta resolução
40 |
41 |
42 |
43 | Compress PDF
44 | Comprimir PDF
45 |
46 |
47 |
48 |
49 | Warning
50 | Atenção
51 |
52 |
53 |
54 | You need to select a valide PDF file
55 | Você precisa selecionar um arquivo PDF válido
56 |
57 |
58 |
59 | You need to select a compression mode
60 | Você precisa selecionar um modo de compressão
61 |
62 |
63 |
64 | FileDialog
65 |
66 |
67 | Select the PDF file
68 | Selecione o arquivo PDF
69 |
70 |
71 |
72 | Save file
73 | Salvar Arquivo
74 |
75 |
76 |
77 | Select the PDF files
78 | Selecione os arquivos PDF
79 |
80 |
81 |
82 | MainWindow
83 |
84 |
85 | Processing...
86 | Processando...
87 |
88 |
89 |
90 |
91 | ERROR
92 | ERRO
93 |
94 |
95 |
96 |
97 | Failed
98 | Falhou
99 |
100 |
101 |
102 | An unknown error has occurred. Read the terminal output for more information
103 | Um erro desconhecido ocorreu. Leia a saída do terminal para mais informações
104 |
105 |
106 |
107 | Success!
108 | Sucesso!
109 |
110 |
111 |
112 | MenuPage
113 |
114 |
115 | Tools for manage PDFs
116 | Ferramentas para Gerenciar PDFs
117 |
118 |
119 |
120 | Compress a PDF file
121 | Comprimir arquivo PDF
122 |
123 |
124 |
125 | Split a PDF file
126 | Dividir um arquivo PDF
127 |
128 |
129 |
130 | Rotate a PDF file
131 | Rotacionar arquivo PDF
132 |
133 |
134 |
135 | Merge PDF files
136 | Juntar arquivos PDF
137 |
138 |
139 |
140 | MergePage
141 |
142 |
143 | Return
144 | Voltar
145 |
146 |
147 |
148 | Add a PDF file
149 | Adicionar arquivo PDF
150 |
151 |
152 |
153 | Remove a PDF file
154 | Remover arquivo PDF
155 |
156 |
157 |
158 | Change merge order (move selected item up)
159 | Alterar ordem dos PDFs (Mover item selecionado para cima)
160 |
161 |
162 |
163 | Change merge order (move selected item down)
164 | Alterar ordem dos PDFs (Mover item selecionado para baixo)
165 |
166 |
167 |
168 | Merge PDFs
169 | Juntar PDFs
170 |
171 |
172 |
173 | Warning
174 | Atenção
175 |
176 |
177 |
178 | You need to add two or more files to be able to merge them
179 | Você precisa adicionar dois ou mais arquivos para poder unir-los
180 |
181 |
182 |
183 | RotatePage
184 |
185 |
186 | Return
187 | Voltar
188 |
189 |
190 |
191 | Select PDF
192 | Selecionar PDF
193 |
194 |
195 |
196 | Left
197 | Esquerda
198 |
199 |
200 |
201 | Rotate the PDF 90 degrees to the left
202 | Girar o PDF 90 graus para a esquerda
203 |
204 |
205 |
206 | Right
207 | Direita
208 |
209 |
210 |
211 | Rotate the PDF 90 degrees to the right
212 | Girar o PDF 90 graus para a direita
213 |
214 |
215 |
216 | Rotate PDF
217 | Rotacionar PDF
218 |
219 |
220 |
221 | ERROR
222 | ERRO
223 |
224 |
225 |
226 | Failed to generate thumbnail
227 | Falha ao gerar miniatura
228 |
229 |
230 |
231 | Warning
232 | Atenção
233 |
234 |
235 |
236 | You need to select a valide PDF file
237 | Você precisa selecionar um arquivo PDF válido
238 |
239 |
240 |
241 | SplitPage
242 |
243 |
244 | Return
245 | Voltar
246 |
247 |
248 |
249 | Select PDF
250 | Selecionar PDF
251 |
252 |
253 |
254 | Split by range
255 | Dividir por intervalo
256 |
257 |
258 |
259 | Extract all pages
260 | Extrair todas as páginas
261 |
262 |
263 |
264 | From page:
265 | Da página:
266 |
267 |
268 |
269 | To page:
270 | Para página:
271 |
272 |
273 |
274 | Split PDF
275 | Dividir PDF
276 |
277 |
278 |
279 | Warning
280 | Atenção
281 |
282 |
283 |
284 | You need to select a valide PDF file
285 | Você precisa selecionar um arquivo PDF válido
286 |
287 |
288 |
289 | Select Output Folder
290 | Selecione a pasta de saída
291 |
292 |
293 |
294 |
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | #include "interface/mainwindow.hpp"
2 | #include
3 | #include
4 | #include
5 |
6 | Qt::ColorScheme getColorScheme(int windowColor, int windowTextColor);
7 |
8 | int main(int argc, char *argv[]) {
9 | QApplication app(argc, argv);
10 |
11 | QApplication::setDesktopFileName("br.eng.silas.qpdftools");
12 |
13 | // Enable fallback icons, in case the theme doesn't provide them
14 | Qt::ColorScheme colorScheme = getColorScheme(
15 | app.palette().window().color().value(), app.palette().windowText().color().value());
16 | QString fallbackIcons =
17 | colorScheme == Qt::ColorScheme::Dark ? ":fallback-icons-dark" : ":fallback-icons-light";
18 | QIcon::setFallbackSearchPaths(QIcon::fallbackSearchPaths() << fallbackIcons);
19 |
20 | // Enable Translations for other languages
21 | // Search available translations with this format :/i18n/qpdftools_pt_BR.qm
22 | QTranslator translator;
23 | if (translator.load(QLocale(), "qpdftools", "_", ":/i18n"))
24 | QCoreApplication::installTranslator(&translator);
25 |
26 | MainWindow w;
27 | w.show();
28 | return app.exec();
29 | }
30 |
31 | Qt::ColorScheme getColorScheme(int windowColor, int windowTextColor) {
32 | if (Qt::ColorScheme() != Qt::ColorScheme::Unknown)
33 | return Qt::ColorScheme();
34 |
35 | // If the system doesn't support color schemes, find if it's light or dark
36 | // by comparing the color of the background and text.
37 | // if the background is lighter than the text, it's light, otherwise it's dark
38 | if (windowColor > windowTextColor)
39 | return Qt::ColorScheme::Light;
40 |
41 | return Qt::ColorScheme::Dark;
42 | };
--------------------------------------------------------------------------------