import os import shutil import tkinter as tk from tkinter import ttk, messagebox, scrolledtext from pathlib import Path import threading from datetime import datetime class DesktopOrganizerGUI: def __init__(self, root): self.root = root self.root.title("Desktop Organizer - Windows 11") self.root.geometry("700x600") self.root.resizable(False, False) # Стилизация style = ttk.Style() style.theme_use('clam') # Определяне на Desktop пътя self.desktop_path = Path.home() / "Desktop" # Категории за файлове self.categories = { "Документи": [".pdf", ".doc", ".docx", ".txt", ".rtf", ".odt", ".xls", ".xlsx", ".ppt", ".pptx"], "Изображения": [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".svg", ".ico", ".webp", ".tiff"], "Видео": [".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv", ".webm"], "Музика": [".mp3", ".wav", ".flac", ".aac", ".ogg", ".wma", ".m4a"], "Архиви": [".zip", ".rar", ".7z", ".tar", ".gz", ".bz2"], "Програми": [".exe", ".msi", ".bat", ".cmd"], "Код": [".py", ".js", ".html", ".css", ".cpp", ".java", ".c", ".h", ".json", ".xml"], "Други": [] } # Системни файлове и папки за игнориране self.system_items = ["desktop.ini", "Thumbs.db", "$RECYCLE.BIN"] self.create_widgets() def create_widgets(self): # Заглавие title_frame = tk.Frame(self.root, bg="#0078D4", height=80) title_frame.pack(fill="x") title_frame.pack_propagate(False) title_label = tk.Label( title_frame, text="🧹 Desktop Organizer", font=("Segoe UI", 20, "bold"), bg="#0078D4", fg="white" ) title_label.pack(pady=20) # Основна рамка main_frame = tk.Frame(self.root, padx=20, pady=20) main_frame.pack(fill="both", expand=True) # Информация info_label = tk.Label( main_frame, text=f"📂 Desktop път: {self.desktop_path}", font=("Segoe UI", 10), justify="left", anchor="w" ) info_label.pack(fill="x", pady=(0, 10)) # Настройки рамка settings_frame = tk.LabelFrame( main_frame, text="⚙️ Настройки", font=("Segoe UI", 11, "bold"), padx=15, pady=15 ) settings_frame.pack(fill="x", pady=(0, 15)) self.keep_shortcuts = tk.BooleanVar(value=True) tk.Checkbutton( settings_frame, text="✓ Запази всички пряки пътища (.lnk)", variable=self.keep_shortcuts, font=("Segoe UI", 10) ).pack(anchor="w", pady=5) self.keep_folders = tk.BooleanVar(value=True) tk.Checkbutton( settings_frame, text="✓ Запази съществуващите папки на мястото им", variable=self.keep_folders, font=("Segoe UI", 10) ).pack(anchor="w", pady=5) self.main_folder_name = tk.StringVar(value="Организиран Desktop") folder_frame = tk.Frame(settings_frame) folder_frame.pack(fill="x", pady=5) tk.Label( folder_frame, text="📁 Име на главната папка:", font=("Segoe UI", 10) ).pack(side="left") tk.Entry( folder_frame, textvariable=self.main_folder_name, font=("Segoe UI", 10), width=30 ).pack(side="left", padx=10) # Бутони button_frame = tk.Frame(main_frame) button_frame.pack(fill="x", pady=(0, 15)) self.preview_btn = tk.Button( button_frame, text="👁️ Преглед", font=("Segoe UI", 11, "bold"), bg="#0078D4", fg="white", padx=20, pady=10, cursor="hand2", command=self.preview_organization ) self.preview_btn.pack(side="left", padx=(0, 10)) self.organize_btn = tk.Button( button_frame, text="🚀 Организирай Desktop", font=("Segoe UI", 11, "bold"), bg="#107C10", fg="white", padx=20, pady=10, cursor="hand2", command=self.start_organization ) self.organize_btn.pack(side="left") # Лог рамка log_frame = tk.LabelFrame( main_frame, text="📋 Дневник на действията", font=("Segoe UI", 11, "bold"), padx=10, pady=10 ) log_frame.pack(fill="both", expand=True) self.log_text = scrolledtext.ScrolledText( log_frame, font=("Consolas", 9), wrap=tk.WORD, height=15, state="disabled" ) self.log_text.pack(fill="both", expand=True) # Progress bar self.progress = ttk.Progressbar( main_frame, mode="indeterminate" ) self.progress.pack(fill="x", pady=(10, 0)) def log(self, message): self.log_text.config(state="normal") timestamp = datetime.now().strftime("%H:%M:%S") self.log_text.insert(tk.END, f"[{timestamp}] {message}\n") self.log_text.see(tk.END) self.log_text.config(state="disabled") self.root.update() def get_category(self, file_path): ext = file_path.suffix.lower() for category, extensions in self.categories.items(): if ext in extensions: return category return "Други" def should_ignore(self, item_path): # Игнорира системни файлове if item_path.name in self.system_items: return True # Игнорира скрити файлове if item_path.name.startswith('.'): return True return False def analyze_desktop(self): items_to_move = {} items_to_keep = [] for item in self.desktop_path.iterdir(): if self.should_ignore(item): continue # Запазва пряки пътища if self.keep_shortcuts.get() and item.suffix.lower() == ".lnk": items_to_keep.append(item.name) continue # Запазва папки if item.is_dir(): if self.keep_folders.get(): items_to_keep.append(item.name) continue else: # Папките ще бъдат преместени в главната папка if "Папки" not in items_to_move: items_to_move["Папки"] = [] items_to_move["Папки"].append(item) continue # Категоризира файлове if item.is_file(): category = self.get_category(item) if category not in items_to_move: items_to_move[category] = [] items_to_move[category].append(item) return items_to_move, items_to_keep def preview_organization(self): self.log("🔍 Анализиране на Desktop...") items_to_move, items_to_keep = self.analyze_desktop() self.log("\n✅ Файлове/папки, които ще ОСТАНАТ на Desktop:") if items_to_keep: for item in items_to_keep: self.log(f" • {item}") else: self.log(" (няма)") self.log("\n📦 Файлове, които ще бъдат ОРГАНИЗИРАНИ:") total_files = 0 for category, files in items_to_move.items(): if files: self.log(f" 📁 {category}: {len(files)} файла") total_files += len(files) self.log(f"\n📊 Общо файлове за организиране: {total_files}") self.log("=" * 60) def organize_desktop(self): try: self.log("🚀 Започване на организация...") items_to_move, items_to_keep = self.analyze_desktop() if not items_to_move: self.log("✓ Desktop-ът вече е организиран!") messagebox.showinfo("Готово", "Няма файлове за организиране!") return # Създаване на главна папка main_folder = self.desktop_path / self.main_folder_name.get() main_folder.mkdir(exist_ok=True) self.log(f"✓ Създадена главна папка: {main_folder.name}") # Преместване на файлове по категории moved_count = 0 for category, files in items_to_move.items(): if not files: continue category_folder = main_folder / category category_folder.mkdir(exist_ok=True) self.log(f"\n📁 Обработка на категория: {category}") for file_path in files: try: dest = category_folder / file_path.name # Ако файлът съществува, добави номер if dest.exists(): base = dest.stem ext = dest.suffix counter = 1 while dest.exists(): dest = category_folder / f"{base}_{counter}{ext}" counter += 1 shutil.move(str(file_path), str(dest)) self.log(f" ✓ Преместен: {file_path.name}") moved_count += 1 except Exception as e: self.log(f" ✗ Грешка при преместване на {file_path.name}: {str(e)}") self.log(f"\n🎉 Организацията завърши успешно!") self.log(f"📊 Преместени файлове: {moved_count}") self.log(f"✓ Запазени на Desktop: {len(items_to_keep)} елемента") messagebox.showinfo( "Успех!", f"Desktop-ът е организиран успешно!\n\n" f"Преместени: {moved_count} файла\n" f"Запазени: {len(items_to_keep)} елемента" ) except Exception as e: self.log(f"❌ ГРЕШКА: {str(e)}") messagebox.showerror("Грешка", f"Възникна грешка:\n{str(e)}") finally: self.progress.stop() self.organize_btn.config(state="normal") self.preview_btn.config(state="normal") def start_organization(self): result = messagebox.askyesno( "Потвърждение", "Сигурни ли сте, че искате да организирате Desktop-а?\n\n" "Препоръчваме първо да използвате 'Преглед'." ) if result: self.organize_btn.config(state="disabled") self.preview_btn.config(state="disabled") self.progress.start() self.log_text.config(state="normal") self.log_text.delete(1.0, tk.END) self.log_text.config(state="disabled") # Стартиране в отделна нишка thread = threading.Thread(target=self.organize_desktop) thread.daemon = True thread.start() if __name__ == "__main__": root = tk.Tk() app = DesktopOrganizerGUI(root) root.mainloop()