|
1 | | -import os, sys |
2 | | -from PySide6.QtWidgets import QMainWindow, QApplication, QPushButton, QVBoxLayout, QWidget, QFileDialog, QMessageBox |
| 1 | +import os, sys, glob, shutil |
| 2 | +from PySide6.QtWidgets import QMainWindow, QApplication, QPushButton, QWidget, QFileDialog, QMessageBox, QGridLayout |
| 3 | + |
3 | 4 |
|
4 | 5 | class MainWindow(QMainWindow): |
5 | 6 | def __init__(self): |
6 | 7 | super().__init__() |
7 | 8 |
|
8 | 9 | self.setWindowTitle("Windows Backup Application") |
9 | 10 | self.setFixedSize(800, 600) |
10 | | - |
11 | | - #Define Backup Location Variable |
12 | | - self.backup_location = "" #Set by User |
13 | | - |
| 11 | + |
| 12 | + # Define Backup Location Variable |
| 13 | + self.backup_location = "" # Set by User |
| 14 | + |
14 | 15 | central_widget = QWidget() |
15 | 16 | self.setCentralWidget(central_widget) |
16 | | - layout = QVBoxLayout() |
| 17 | + layout = QGridLayout() |
17 | 18 | central_widget.setLayout(layout) |
18 | | - |
19 | | - #Set Backup Location Button |
| 19 | + cols = 2 |
| 20 | + |
| 21 | + # Set Backup Location Button |
20 | 22 | self.backup_location_button = QPushButton("Set Backup Location", self) |
21 | 23 | self.backup_location_button.clicked.connect(self.set_backup_location) |
22 | | - layout.addWidget(self.backup_location_button) |
23 | | - |
24 | | - |
25 | | - #Create Backup Buttons |
| 24 | + layout.addWidget(self.backup_location_button, 0, 0, 1, cols) # Span top row |
| 25 | + |
| 26 | + # Create Backup Buttons |
26 | 27 | self.backup_buttons = [] |
27 | | - |
28 | 28 | self.backup_buttons.append(self.create_button("Backup Contacts", self.backup_contacts)) |
29 | 29 | self.backup_buttons.append(self.create_button("Backup Photos", self.backup_photos)) |
30 | 30 | self.backup_buttons.append(self.create_button("Backup Documents", self.backup_documents)) |
31 | 31 | self.backup_buttons.append(self.create_button("Backup Videos", self.backup_videos)) |
32 | 32 | self.backup_buttons.append(self.create_button("Backup Music", self.backup_music)) |
33 | 33 | self.backup_buttons.append(self.create_button("Backup Desktop", self.backup_desktop)) |
34 | 34 | self.backup_buttons.append(self.create_button("Backup Downloads", self.backup_downloads)) |
| 35 | + self.backup_buttons.append(self.create_button("Backup Outlook Files", self.backup_outlook_files)) |
35 | 36 |
|
36 | | - for btn in self.backup_buttons: |
37 | | - btn.setFixedSize(150, 40) # Set button size |
| 37 | + # Add buttons to grid layout |
| 38 | + for idx, btn in enumerate(self.backup_buttons): |
| 39 | + btn.setFixedSize(150, 40) |
38 | 40 | btn.setEnabled(False) |
39 | | - layout.addWidget(btn) |
| 41 | + row = 1 + idx // cols |
| 42 | + col = idx % cols |
| 43 | + layout.addWidget(btn, row, col) |
40 | 44 |
|
41 | | - |
42 | | - |
43 | 45 | def create_button(self, text, command): |
44 | 46 | btn = QPushButton(text, self) |
45 | 47 | btn.clicked.connect(command) |
46 | 48 | return btn |
47 | | - |
48 | | - |
| 49 | + |
49 | 50 | def set_backup_location(self): |
50 | 51 | folder = QFileDialog.getExistingDirectory(self, "Select Backup Location") |
51 | 52 | if folder: |
52 | 53 | self.backup_location = folder |
53 | 54 | for btn in self.backup_buttons: |
54 | 55 | btn.setEnabled(True) |
55 | | - |
56 | | - def run_backup(self, source, destination): |
| 56 | + |
| 57 | + def copy_with_glob(self, source_dir, destination_name, patterns=["*"]): |
| 58 | + """Copy files matching patterns from source_dir to backup_location/destination_name""" |
57 | 59 | if not self.backup_location: |
58 | 60 | QMessageBox.warning(self, "Error", "Please set a backup location first.") |
59 | 61 | return |
60 | | - |
61 | | - |
62 | | - destination = os.path.join(self.backup_location, os.path.basename(source)) |
| 62 | + |
| 63 | + source_dir = os.path.expanduser(source_dir) |
| 64 | + if not os.path.exists(source_dir): |
| 65 | + QMessageBox.warning(self, "Error", f"Source folder not found: {source_dir}") |
| 66 | + return |
| 67 | + |
| 68 | + destination = os.path.join(self.backup_location, destination_name) |
63 | 69 | os.makedirs(destination, exist_ok=True) |
64 | | - cmd = f'xcopy /E /I /Y "{source}" "{destination}"' |
65 | | - os.system(cmd) |
66 | | - QMessageBox.information(self, "Success", f"Backup of {os.path.basename(source)} completed.") |
67 | | - |
| 70 | + |
| 71 | + files_copied = 0 |
| 72 | + for pattern in patterns: |
| 73 | + for file_path in glob.glob(os.path.join(source_dir, pattern), recursive=True): |
| 74 | + if os.path.isfile(file_path): # only copy files, not directories |
| 75 | + try: |
| 76 | + shutil.copy2(file_path, destination) |
| 77 | + files_copied += 1 |
| 78 | + except Exception as e: |
| 79 | + QMessageBox.warning(self, "Error", f"Failed to copy {file_path}: {e}") |
| 80 | + |
| 81 | + if files_copied > 0: |
| 82 | + QMessageBox.information(self, "Success", f"Backup of {files_copied} files completed in {destination_name}.") |
| 83 | + else: |
| 84 | + QMessageBox.information(self, "Info", f"No files found in {source_dir} to backup.") |
| 85 | + |
| 86 | + # Backup Methods |
68 | 87 | def backup_contacts(self): |
69 | | - self.run_backup(os.path.expanduser("~/Contacts")) |
70 | | - |
| 88 | + self.copy_with_glob("~/Contacts", "Contacts") |
| 89 | + |
71 | 90 | def backup_photos(self): |
72 | | - self.run_backup(os.path.expanduser("~/Pictures")) |
73 | | - |
| 91 | + self.copy_with_glob("~/Pictures", "Pictures") |
| 92 | + |
74 | 93 | def backup_documents(self): |
75 | | - self.run_backup(os.path.expanduser("~/Documents")) |
76 | | - |
| 94 | + self.copy_with_glob("~/Documents", "Documents") |
| 95 | + |
77 | 96 | def backup_videos(self): |
78 | | - self.run_backup(os.path.expanduser("~/Videos")) |
79 | | - |
| 97 | + self.copy_with_glob("~/Videos", "Videos") |
| 98 | + |
80 | 99 | def backup_music(self): |
81 | | - self.run_backup(os.path.expanduser("~/Music")) |
82 | | - |
| 100 | + self.copy_with_glob("~/Music", "Music") |
| 101 | + |
83 | 102 | def backup_desktop(self): |
84 | | - self.run_backup(os.path.expanduser("~/Desktop")) |
85 | | - |
| 103 | + self.copy_with_glob("~/Desktop", "Desktop") |
| 104 | + |
86 | 105 | def backup_downloads(self): |
87 | | - self.run_backup(os.path.expanduser("~/Downloads")) |
88 | | - |
89 | | - |
90 | | - |
91 | | -if __name__ == "__main__": |
| 106 | + self.copy_with_glob("~/Downloads", "Downloads") |
| 107 | + |
| 108 | + def backup_outlook_files(self): |
| 109 | + self.copy_with_glob("~/AppData/Local/Microsoft/Outlook", "Outlook", ["*.pst", "*.ost", "*.nst"]) |
| 110 | + |
| 111 | + |
| 112 | +if __name__ == "__main__": |
92 | 113 | app = QApplication(sys.argv) |
93 | 114 | window = MainWindow() |
94 | 115 | window.show() |
95 | 116 | app.exec() |
96 | | - |
|
0 commit comments