Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
weyh committed Jul 31, 2021
0 parents commit c293dcd
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
*.pdf
__pycache__
.vscode
build/
dist/
*.spec
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2020 Bak Gergely János

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Python PDF Merger

## Usage

Simply run the `pdf_merger.py` file.

```
Usage: pdf_merger.py [options]
Options:
--version show program's version number and exit
-h, --help show this help message and exit
-o [file name], --output=[file name]
Output filename
-d, --disable_file_name_bookmarks
File names will not be added to bookmarks
-D, --no_bookmark_import
Doesn't import bookmarks from source pdfs. Has no
effect on the file name bookmarks.
```

### 3rd party package(s): `PyPDF2`
---

## License
This project is licensed under the MIT License - see the [MIT License](LICENSE) file for details.
19 changes: 19 additions & 0 deletions build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Write-Output "Building..."

pyinstaller ./pdf_merger_ui.pyw -n "PDF Merger" --onefile --win-private-assemblies -i ".\icon.ico" --workpath="./build/tmp" --distpath="./build/bin"

New-Item -ItemType Directory -Force -Path "./build/bin/lang" > $null
Copy-Item -Path "./lang/*" -Destination "./build/bin/lang"
Copy-Item -Path "./icon.ico" -Destination "./build/bin/icon.ico"
Copy-Item -Path "./LICENSE" -Destination "./build/bin/LICENSE"
Copy-Item -Path "./README.md" -Destination "./build/bin/README.md"

New-Item -ItemType Directory -Force -Path "./build/pkg" > $null
Compress-Archive -Update -Path "./build/bin/*" -DestinationPath "./build/pkg/pdf_merger.zip"

Write-Output "Cleaning..."

Remove-Item ".\*.spec"
Remove-Item ".\__pycache__" -Force -Recurse -ErrorAction SilentlyContinue

Write-Output "DONE!"
13 changes: 13 additions & 0 deletions buld.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
echo "Building..."

pyinstaller pdf_merger_ui.pyw -n "PDF Merger" --onefile --workpath="./build/tmp" --distpath="./build/bin" &&

mkdir -p './build/bin/lang' &&
cp "./lang/*" "./build/bin/lang" &&
cp "./LICENSE" "./build/bin/LICENSE" &&
cp "./README.md" "./build/bin/README.md" &&

mkdir -p './build/pkg' &&
zip './build/pkg/pdf_merger.zip' -r './build/bin' &&

echo "DONE!"
Binary file added icon.ico
Binary file not shown.
13 changes: 13 additions & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "PDF Merger",
"inputFiles": "Input files:",
"browse": "Browse",
"PDFFiles": "PDF Files",
"ALLFiles": "ALL Files",
"importBookmarks": "Keep Bookmarks",
"fileNameBookmarks": "File names as bookmarks",
"outputFile": "Output file:",
"saveAs": "Save As",
"create": "Create",
"quit": "Quit"
}
13 changes: 13 additions & 0 deletions lang/hu.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"name": "PDF Egyesítő",
"inputFiles": "Bemeneti fájlok:",
"browse": "Tallózás",
"PDFFiles": "PDF Fájlok",
"ALLFiles": "ALL Fájlok",
"importBookmarks": "Könyvejlzők megtartása",
"fileNameBookmarks": "Fájlnevek könyvjeztőként",
"outputFile": "Kimeneti fájl:",
"saveAs": "Mentés",
"create": "Létrehoz",
"quit": "Kilépés"
}
98 changes: 98 additions & 0 deletions pdf_merger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import os
import re
from optparse import OptionParser
from typing import List, Tuple
from datetime import datetime
from PyPDF2 import utils, PdfFileReader, PdfFileMerger

VERSION = "1.0.0"


def load_args() -> Tuple:
parser = OptionParser(version=VERSION)

parser.add_option("-o", "--output", dest="output_file_name", help="Output filename", metavar="[file name]",
default=f"output_{datetime.now().strftime('%Y%m%d%H%M%S')}.pdf")

parser.add_option("-d", "--disable_file_name_bookmarks", dest="file_name_bookmarks", action="store_false", default=True,
help="File names will not be added to bookmarks")

parser.add_option("-D", "--no_bookmark_import", dest="import_bookmarks", action="store_false", default=True,
help="Doesn't import bookmarks from source pdfs. Has no effect on the file name bookmarks.")

parser.add_option("-q", "--quiet", dest="quiet", action="store_true", default=False,
help="No text will be written to stdout.")

options, args = parser.parse_args()

if len(args) == 0:
parser.print_help()
exit(1)

return (options, args)


def get_selection(file_list: list) -> List[str]:
selected_files: List[str] = []

regex_a = re.compile(r"(\/|\\|^)\*.pdf$")
regex_b = re.compile(r"(\/|\\|^)\*(.\*|)$")

for file in file_list:
if regex_a.search(file): # *.pdf
dir = os.path.dirname(file)

if not dir:
dir = "./"

for f in os.listdir(dir):
if len(f) >= 4 and f[-4:] == ".pdf":
selected_files.append(os.path.join(dir, f))
elif regex_b.search(file): # *, *.*
dir = os.path.dirname(file)

if not dir:
dir = "./"

for f in os.listdir(dir):
selected_files.append(os.path.join(dir, f))
else:
selected_files.append(file)

return selected_files


def print_q(text: str, quiet: bool):
if not quiet:
print(text)


def create(_args: Tuple):
options, args = _args

valid_pdfs = []

for file in get_selection(args):
try:
pdf = PdfFileReader(open(file, "rb"))
valid_pdfs.append((pdf, os.path.basename(file).replace(".pdf", "")))
except(utils.PdfReadError):
print_q(f"\u001b[33;1m{file} is not a valid pdf. This file will be skipped!\u001b[0m", options.quiet)
except(IOError):
print_q(f"\u001b[31;1m{file} thrown an IOError. This file will be skipped!\u001b[0m", options.quiet)

pdf_merger = PdfFileMerger()
for pdf_obj, pdf_name in valid_pdfs:
if options.file_name_bookmarks:
pdf_merger.append(pdf_obj, pdf_name, import_bookmarks=options.import_bookmarks)
else:
pdf_merger.append(pdf_obj, import_bookmarks=options.import_bookmarks)

pdf_merger.write(options.output_file_name)
print_q(f"'{options.output_file_name}' file has been successfully created!", options.quiet)


if __name__ == "__main__":
create(load_args())
62 changes: 62 additions & 0 deletions pdf_merger_ui.pyw
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from collections import namedtuple
from optparse import OptionParser
from typing import Tuple
import PySimpleGUI as sg
import os
import json
import pdf_merger as pm


def load_args() -> Tuple:
parser = OptionParser(version=pm.VERSION)
parser.add_option("-l", "--lang", dest="lang", help="Language", metavar="[lang]",
default="en")

return parser.parse_args()


if __name__ == "__main__":
lang = {}
options, args = load_args()

if not os.path.isfile(f"./lang/{options.lang}.json"):
options.lang = "en"

with open(f"./lang/{options.lang}.json", encoding="utf8") as f:
lang = json.loads(f.read())

sg.theme("SystemDefaultForReal")

layout = [
[sg.Text(lang["inputFiles"])],
[sg.Input(), sg.FilesBrowse(button_text=lang["browse"],
file_types=((lang["PDFFiles"], "*.pdf"), (lang["ALLFiles"], "*.*")))],
[sg.Checkbox(lang["importBookmarks"], default=False),
sg.Checkbox(lang["fileNameBookmarks"], default=False)],
[sg.Text(lang["outputFile"])],
[sg.Input(), sg.FileSaveAs(button_text=lang["saveAs"],
file_types=((lang["PDFFiles"], "*.pdf"), (lang["ALLFiles"], "*.*")),
default_extension="pdf")],
[sg.OK(lang["create"]), sg.Quit(lang["quit"])]
]

window = sg.Window(lang["name"], layout, icon="./icon.ico")

while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == lang["quit"]:
break
if event == lang["create"] and values[lang["saveAs"]] != "" and values[lang["browse"]] != "":
tmp_args_dict = {
"output_file_name": values[lang["saveAs"]],
"file_name_bookmarks": values[2],
"import_bookmarks": values[1],
"quiet": True
}

pm.create((namedtuple("ObjectName", tmp_args_dict.keys())(*tmp_args_dict.values()),
sorted(values[lang["browse"]].split(';'))))

window.close()

0 comments on commit c293dcd

Please sign in to comment.