Skip to content

Commit f7a8a5a

Browse files
author
SETYUTH
committed
Update to v2.0.0: Added Drag & Drop and Auto-Open features
1 parent 182091f commit f7a8a5a

3 files changed

Lines changed: 221 additions & 76 deletions

File tree

PDFMerger_v2.py

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
import tkinter as tk
2+
from tkinter import filedialog, messagebox
3+
from tkinterdnd2 import DND_FILES, TkinterDnD
4+
from pypdf import PdfWriter
5+
import os
6+
7+
# --- CONFIGURATION ---
8+
VERSION = "2.0.0"
9+
APP_NAME = "PDF Merger Utility"
10+
11+
12+
def show_about():
13+
"""Displays a popup with app information."""
14+
messagebox.showinfo(
15+
"About",
16+
f"{APP_NAME}\n"
17+
f"Version: {VERSION}\n\n"
18+
"A simple tool to merge PDFs in your preferred order.\n"
19+
"Licensed under MIT."
20+
)
21+
22+
# --- LOGIC ---
23+
24+
def add_files():
25+
"""Manual selection of files via button."""
26+
files = filedialog.askopenfilenames(
27+
title="Select PDF files",
28+
filetypes=[("PDF Files", "*.pdf")]
29+
)
30+
for file in files:
31+
listbox.insert(tk.END, file)
32+
33+
34+
def drop_files(event):
35+
"""Handles dragging and dropping files into the listbox."""
36+
# The event.data returns a string of filenames.
37+
# We need to clean curly braces {} which Windows adds to paths with spaces.
38+
raw_files = event.data
39+
40+
# This logic splits the dropped items into individual paths
41+
# Note: TkinterDnD can be tricky with spaces, this is a basic parser
42+
if raw_files.startswith('{'):
43+
paths = raw_files[1:-1].split('} {')
44+
else:
45+
paths = raw_files.split()
46+
47+
for path in paths:
48+
if path.lower().endswith('.pdf'):
49+
listbox.insert(tk.END, path)
50+
51+
52+
def move_up():
53+
"""Moves selected item up."""
54+
try:
55+
selection = listbox.curselection()
56+
if not selection or selection[0] == 0: return
57+
pos = selection[0]
58+
text = listbox.get(pos)
59+
listbox.delete(pos)
60+
listbox.insert(pos - 1, text)
61+
listbox.selection_set(pos - 1)
62+
except:
63+
pass
64+
65+
66+
def move_down():
67+
"""Moves selected item down."""
68+
try:
69+
selection = listbox.curselection()
70+
if not selection or selection[0] == listbox.size() - 1: return
71+
pos = selection[0]
72+
text = listbox.get(pos)
73+
listbox.delete(pos)
74+
listbox.insert(pos + 1, text)
75+
listbox.selection_set(pos + 1)
76+
except:
77+
pass
78+
79+
80+
def remove_selected():
81+
"""Removes selected item."""
82+
try:
83+
selection = listbox.curselection()
84+
if selection: listbox.delete(selection[0])
85+
except:
86+
pass
87+
88+
89+
def merge_pdfs():
90+
"""Merges files and auto-opens the folder."""
91+
files = listbox.get(0, tk.END)
92+
93+
if len(files) == 0:
94+
messagebox.showwarning("Warning", "No files to merge!")
95+
return
96+
97+
save_path = filedialog.asksaveasfilename(
98+
title="Save Merged File",
99+
defaultextension=".pdf",
100+
filetypes=[("PDF Files", "*.pdf")]
101+
)
102+
103+
if not save_path: return
104+
105+
merger = PdfWriter()
106+
try:
107+
for pdf in files:
108+
merger.append(pdf)
109+
110+
merger.write(save_path)
111+
merger.close()
112+
113+
# --- FEATURE: AUTO-OPEN FOLDER ---
114+
folder_path = os.path.dirname(save_path)
115+
os.startfile(folder_path)
116+
117+
messagebox.showinfo("Success", f"Saved to:\n{save_path}")
118+
119+
except Exception as e:
120+
messagebox.showerror("Error", f"Failed: {e}")
121+
122+
123+
# --- GUI SETUP ---
124+
# We use TkinterDnD.Tk instead of tk.Tk
125+
root = TkinterDnD.Tk()
126+
root.title(f"{APP_NAME} - v{VERSION}")
127+
root.geometry("600x450")
128+
129+
# --- ADDING A MENU BAR ---
130+
menubar = tk.Menu(root)
131+
helpmenu = tk.Menu(menubar, tearoff=0)
132+
helpmenu.add_command(label="About", command=show_about)
133+
menubar.add_cascade(label="Help", menu=helpmenu)
134+
root.config(menu=menubar)
135+
136+
# 1. Header with Instructions
137+
lbl_instruct = tk.Label(root, text="Drag & Drop PDF files here", font=("Arial", 10, "italic"), fg="gray")
138+
lbl_instruct.pack(pady=(10, 0))
139+
140+
# 2. The Listbox (With Drag & Drop Enabled)
141+
frame_list = tk.Frame(root)
142+
frame_list.pack(fill="both", expand=True, padx=15, pady=5)
143+
144+
scrollbar = tk.Scrollbar(frame_list)
145+
scrollbar.pack(side="right", fill="y")
146+
147+
listbox = tk.Listbox(frame_list, selectmode=tk.SINGLE, yscrollcommand=scrollbar.set, font=("Consolas", 9))
148+
listbox.pack(side="left", fill="both", expand=True)
149+
scrollbar.config(command=listbox.yview)
150+
151+
# ENABLE DRAG AND DROP ON LISTBOX
152+
listbox.drop_target_register(DND_FILES)
153+
listbox.dnd_bind('<<Drop>>', drop_files)
154+
155+
# 3. Control Buttons
156+
frame_controls = tk.Frame(root)
157+
frame_controls.pack(fill="x", padx=15, pady=5)
158+
159+
btn_add = tk.Button(frame_controls, text="➕ Add Manually", command=add_files)
160+
btn_add.pack(side="left")
161+
162+
btn_remove = tk.Button(frame_controls, text="❌ Remove", command=remove_selected)
163+
btn_remove.pack(side="left", padx=5)
164+
165+
btn_down = tk.Button(frame_controls, text="↓", command=move_down, width=3)
166+
btn_down.pack(side="right")
167+
168+
btn_up = tk.Button(frame_controls, text="↑", command=move_up, width=3)
169+
btn_up.pack(side="right", padx=5)
170+
171+
# 4. Merge Button
172+
btn_merge = tk.Button(root, text="MERGE NOW", command=merge_pdfs, bg="#007ACC", fg="white", font=("Arial", 11, "bold"),
173+
height=2)
174+
btn_merge.pack(fill="x", padx=15, pady=10)
175+
176+
# 5. Version Badge (Bottom Right)
177+
lbl_version = tk.Label(root, text=f"v{VERSION}", font=("Arial", 8), fg="#999")
178+
lbl_version.pack(side="bottom", anchor="se", padx=5, pady=2)
179+
180+
root.mainloop()

README.md

Lines changed: 41 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,105 +1,70 @@
11
# PDF Merger Utility
22

3-
A lightweight, user-friendly Windows desktop application built with Python to combine multiple PDF files into a single document. This tool allows users to import PDFs, reorder them manually to ensure the correct sequence, and export the final result with one click.
3+
A lightweight, user-friendly Windows desktop application built with Python to combine multiple PDF files into a single document. Version 2.0.0 introduces a modern Drag-and-Drop interface and workflow automation.
44

5-
## ✨ Features
5+
![Version](https://img.shields.io/badge/version-2.0.0-blue)
6+
![License](https://img.shields.io/badge/license-MIT-green)
67

7-
* **Batch Import:** Add multiple PDF files at once.
8-
* **Manual Reordering:** Use "Move Up" and "Move Down" buttons to organize your files exactly how you want them in the final document.
9-
* **Remove Tool:** Easily remove accidental additions from the list.
10-
* **Clean UI:** Simple, no-nonsense interface for quick tasks.
11-
* **Open Source:** Free to use, modify, and distribute under the MIT License.
8+
## ✨ New in v2.0.0
9+
* **Drag & Drop Support:** You can now drag files directly from your desktop into the app window.
10+
* **Auto-Open:** The folder containing your merged file opens automatically after processing.
11+
* **UI Improvements:** Added version badge and instructional prompts.
1212

13-
## 🚀 Getting Started
13+
## 🚀 Features
14+
* **Batch Import:** Add multiple PDF files via file browser or Drag & Drop.
15+
* **Manual Reordering:** Use "Move Up" and "Move Down" buttons to ensure the perfect page sequence.
16+
* **Smart Parsing:** Automatically handles file paths even if they contain spaces.
17+
* **Standalone Utility:** Can be built into a single `.exe` file that runs without Python installed.
1418

15-
### Prerequisites
16-
17-
To run this tool from the source code, you need:
19+
## 🛠️ Installation & Setup
1820

19-
* **Python 3.x** installed on your system.
20-
* The `pypdf` library.
21-
22-
### Installation
21+
### Prerequisites
22+
To run the source code, you need **Python 3.x** and the following libraries:
2323

24-
1. **Clone the repository:**
2524
```bash
26-
git clone https://github.com/YOUR_USERNAME/PDF-Merger-Utility.git
27-
cd PDF-Merger-Utility
28-
25+
pip install pypdf tkinterdnd2 pyinstaller
2926
```
3027

28+
### Running the App
3129

32-
2. **Install dependencies:**
3330
```bash
34-
pip install pypdf
35-
31+
python PDFMerger_v2.py
3632
```
3733

34+
## 📦 How to Build the Executable (.exe)
3835

39-
3. **Run the application:**
40-
```bash
41-
python PDFMerger.py
36+
**Important:** Because this version uses `tkinterdnd2` for drag-and-drop, the build command is different from standard Python scripts. You must use the `--collect-all` flag to include the necessary system hooks.
4237

38+
1. Open your terminal/command prompt.
39+
2. Run the following command:
40+
```bash
41+
pyinstaller --noconsole --onefile --collect-all tkinterdnd2 PDFMerger_v2.py
4342
```
4443

45-
46-
47-
---
44+
3. Your standalone application will appear in the `dist/` folder.
4845

4946
## 📖 User Guide
5047

51-
Using the PDF Merger is straightforward:
52-
53-
1. **Add Files:** Click the **Add Files...** button to select the PDFs you want to combine.
54-
2. **Organize:** * Click on a file name in the list to select it.
55-
* Click **Move Up ↑** or **Move Down ↓** to change the order. The final PDF will be merged from top to bottom.
56-
57-
58-
3. **Remove:** If you made a mistake, select the file and click **Remove Selected**.
59-
4. **Merge:** Click the green **MERGE PDFS** button. A window will pop up asking you where to save your new file and what to name it.
60-
5. **Success:** Once the process is complete, a success message will appear.
61-
62-
---
63-
64-
## 🛠️ How to Build an Executable (.exe)
65-
66-
If you want to create a standalone version that runs without Python:
67-
68-
1. Install PyInstaller: `pip install pyinstaller`
69-
2. Run: `pyinstaller --onefile --noconsole PDFMerger.py`
70-
3. Find your `PDFMerger.exe` in the `dist` folder.
71-
72-
---
48+
1. **Launch:** Open `PDFMerger Utility`.
49+
2. **Add Files:** Drag PDF files into the white box, or click **➕ Add Manually**.
50+
3. **Organize:** Select a file and use the **** or **** arrows to change the order.
51+
4. **Merge:** Click **MERGE NOW**.
52+
5. **Finish:** Choose a save location. The folder will open automatically once done.
7353

7454
## 📄 License
55+
This project is licensed under the MIT License - see the [LICENSE](https://www.google.com/search?q=LICENSE) file for details.
7556

76-
This project is licensed under the **MIT License**.
77-
78-
```text
79-
MIT License
80-
81-
Copyright (c) 2026 Yuth Set
82-
83-
Permission is hereby granted, free of charge, to any person obtaining a copy
84-
of this software and associated documentation files (the "Software"), to deal
85-
in the Software without restriction, including without limitation the rights
86-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
87-
copies of the Software, and to permit persons to whom the Software is
88-
furnished to do so, subject to the following conditions:
57+
---
8958

90-
The above copyright notice and this permission notice shall be included in all
91-
copies or substantial portions of the Software.
59+
### 🚀 Major Update: v2.0.0
9260

93-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
94-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
95-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
96-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
97-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
98-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
99-
SOFTWARE.
61+
This release focuses on User Experience (UX) improvements, making it faster and easier to merge documents.
10062

101-
```
63+
### 🆕 What's New
64+
- **Drag & Drop Support:** Completely replaced the static list view with a Drop-enabled zone. Users can now drag PDFs directly from Explorer into the app.
65+
- **Workflow Automation:** The application now automatically opens the destination folder after a successful merge, saving you the extra clicks to find your file.
66+
- **UI Polish:** Added clear instructional text and a version badge to the interface.
67+
- **Bug Fixes:** Improved file path parsing for filenames containing spaces.
10268

103-
---
104-
## Current Version
105-
**v1.0.0** (Initial Release)
69+
### 📦 How to Use
70+
Download the `PDFMerger.exe` attached below. No installation is required—just double-click and run!

dist/PDFMerger_v2.exe

15 MB
Binary file not shown.

0 commit comments

Comments
 (0)