├── .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 | }; --------------------------------------------------------------------------------