-
Notifications
You must be signed in to change notification settings - Fork 0
/
gui_downloader.py
118 lines (89 loc) · 4.33 KB
/
gui_downloader.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import tkinter as tk
from tkinter import ttk, filedialog
import requests
import threading
import os
import shutil
from tqdm import tqdm
from ttkthemes import ThemedStyle
class Downloader:
def __init__(self):
self.saveto = ""
self.cancel_download = False
self.window = tk.Tk()
self.window.title("Python GUI Downloader")
self.window.geometry('400x350')
style = ThemedStyle(self.window)
style.set_theme("plastik")
self.url_label = ttk.Label(self.window, text='Enter URL')
self.url_label.pack(pady=10)
self.url_entry = ttk.Entry(self.window, width=40)
self.url_entry.pack(pady=5)
self.browse_button = ttk.Button(self.window, text='Browse', command=self.browse_file)
self.browse_button.pack(pady=5)
self.download_button = ttk.Button(self.window, text='Download', command=self.download)
self.download_button.pack(pady=10)
self.cancel_button = ttk.Button(self.window, text='Cancel Download', command=self.cancel_download_action, state=tk.DISABLED)
self.cancel_button.pack(pady=5)
self.progress_bar = ttk.Progressbar(self.window, orient='horizontal', length=300, mode='determinate')
self.progress_bar.pack(pady=10)
self.progress_text = tk.StringVar()
self.progress_label = ttk.Label(self.window, textvariable=self.progress_text)
self.progress_label.pack()
self.window.protocol("WM_DELETE_WINDOW", self.on_close)
self.window.mainloop()
def browse_file(self):
saveto = filedialog.asksaveasfilename(initialfile=self.url_entry.get().split('/')[-1].split('?')[0])
if saveto:
self.saveto = saveto
def download(self):
url = self.url_entry.get()
if not url:
return
if not self.saveto:
self.progress_text.set("Error: Select a valid save location")
return
self.download_button.configure(state=tk.DISABLED)
self.cancel_button.configure(state=tk.NORMAL)
self.progress_bar['value'] = 0
self.progress_text.set("Downloading...")
self.cancel_download = False
threading.Thread(target=self.start_download, args=(url,)).start()
def start_download(self, url):
try:
response = requests.get(url, stream=True)
response.raise_for_status()
total_size_in_bytes = int(response.headers.get("content-length", 0))
block_size = 1024 * 1024 # 1MB
self.progress_bar['maximum'] = total_size_in_bytes
self.progress_bar['value'] = 0
downloaded_size = 0
with open(self.saveto + '.crdownload', 'wb') as f, tqdm.wrapattr(f, "write", unit="B", unit_scale=True, unit_divisor=1024, miniters=1, total=total_size_in_bytes) as f_tqdm:
for data in response.iter_content(block_size):
if self.cancel_download:
break
f_tqdm.write(data)
downloaded_size += len(data)
self.progress_bar['value'] = downloaded_size
progress_percent = int((downloaded_size / total_size_in_bytes) * 100)
self.progress_text.set(f"Downloading... {progress_percent}%")
self.window.update()
if not self.cancel_download:
self.progress_text.set("Download Complete")
f.close() # Close the file object before renaming
shutil.move(self.saveto + ".crdownload", self.saveto) # Remove .crdownload extension
else:
self.progress_text.set("Download Canceled")
os.remove(self.saveto + ".crdownload") # Remove .crdownload file
except requests.exceptions.RequestException:
self.progress_text.set("Error: Failed to download")
finally:
self.download_button.configure(state=tk.NORMAL)
self.cancel_button.configure(state=tk.DISABLED)
def cancel_download_action(self):
self.cancel_download = True
def on_close(self):
if self.cancel_button['state'] == tk.NORMAL:
self.cancel_download_action()
self.window.destroy()
Downloader()