Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import os
- import tkinter as tk
- from tkinter import ttk
- from tkinter import filedialog, messagebox
- import tkinter.font as tkFont
- class FileSelectorApp:
- def __init__(self, root):
- self.root = root
- self.root.title("Python Project File Selector")
- self.root.geometry("1600x1000") # Increased width for better layout
- self.root_dir = ""
- self.checked_items = set()
- # Configure the main window's grid
- self.root.columnconfigure(0, weight=1)
- self.root.columnconfigure(1, weight=3)
- self.root.rowconfigure(1, weight=1)
- # Configure Style for Treeview
- style = ttk.Style()
- style.configure("Treeview", font=("Helvetica", 12)) # Set desired font family and size
- # Optionally, you can configure headings if needed
- style.configure("Treeview.Heading", font=("Helvetica", 12, "bold"))
- # Top Frame for directory selection
- top_frame = ttk.Frame(root)
- top_frame.grid(row=0, column=0, columnspan=2, sticky="ew", padx=10, pady=5)
- top_frame.columnconfigure(1, weight=1)
- self.dir_label = ttk.Label(top_frame, text="No directory selected")
- self.dir_label.grid(row=1, column=0, padx=(0, 10), sticky="w")
- select_dir_btn = ttk.Button(top_frame, text="Select Project Root", command=self.select_directory)
- select_dir_btn.grid(row=0, column=0, sticky='w')
- # Main Frame divided into Left and Right
- main_frame = ttk.Frame(root)
- main_frame.grid(row=1, column=0, columnspan=2, sticky="nsew", padx=10, pady=5)
- main_frame.columnconfigure(0, weight=1)
- main_frame.columnconfigure(1, weight=3)
- main_frame.rowconfigure(0, weight=1)
- # Left Frame for Treeview and Copy Button
- left_frame = ttk.Frame(main_frame)
- left_frame.grid(row=0, column=0, sticky="nsew")
- left_frame.columnconfigure(0, weight=1)
- left_frame.rowconfigure(0, weight=1)
- # Treeview Frame within Left Frame
- tree_frame = ttk.Frame(left_frame)
- tree_frame.grid(row=0, column=0, sticky="nsew")
- self.tree = ttk.Treeview(tree_frame, columns=("File Name"), show='tree')
- self.tree.pack(fill=tk.BOTH, expand=True, side=tk.LEFT)
- # Scrollbar for Treeview
- tree_scrollbar = ttk.Scrollbar(tree_frame, orient="vertical", command=self.tree.yview)
- tree_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
- self.tree.configure(yscrollcommand=tree_scrollbar.set)
- # Bind click event for checkbox toggling
- self.tree.bind('<Button-1>', self.on_click)
- # Copy Button below Treeview
- copy_btn = ttk.Button(left_frame, text="Copy Selected Files", command=self.copy_files)
- copy_btn.grid(row=1, column=0, pady=5, sticky="ew")
- # Right Frame for Text Area
- right_frame = ttk.Frame(main_frame)
- right_frame.grid(row=0, column=1, sticky="nsew")
- right_frame.columnconfigure(0, weight=1)
- right_frame.rowconfigure(0, weight=1)
- # Text Area with Scrollbar
- text_frame = ttk.Frame(right_frame)
- text_frame.grid(row=0, column=0, sticky="nsew")
- self.text_area = tk.Text(text_frame, wrap="none")
- self.text_area.pack(fill=tk.BOTH, expand=True, side=tk.LEFT)
- # Vertical Scrollbar for Text Area
- text_scrollbar = ttk.Scrollbar(text_frame, orient="vertical", command=self.text_area.yview)
- text_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
- self.text_area.configure(yscrollcommand=text_scrollbar.set)
- def select_directory(self):
- dir_path = filedialog.askdirectory()
- if dir_path:
- self.root_dir = dir_path
- self.dir_label.config(text=f"Project Root: {self.root_dir}")
- self.populate_tree()
- def populate_tree(self):
- self.tree.delete(*self.tree.get_children())
- self.checked_items.clear()
- for root_dir, dirs, files in os.walk(self.root_dir):
- # Relative path from the root directory
- rel_path = os.path.relpath(root_dir, self.root_dir)
- if rel_path == ".":
- rel_path = ""
- # Modify dirs in-place to exclude certain folders
- dirs[:] = [d for d in dirs if not d.startswith('.') and d not in ['venv', '__pycache__']]
- # Sort directories and files: directories first, then files
- dirs.sort()
- files = sorted([f for f in files if not f.endswith('.pyc')])
- path_parts = rel_path.split(os.sep) if rel_path else []
- parent = ''
- # Traverse or create the path in the Treeview
- for part in path_parts:
- # Find existing parent
- found = None
- for child in self.tree.get_children(parent):
- # Remove checkbox symbols before comparison
- child_text = self.tree.item(child, 'text').strip('☐☑ ')
- if child_text == part:
- found = child
- break
- if not found:
- display_text = f"☐ {part}"
- found = self.tree.insert(parent, 'end', text=display_text, open=True) # Ensure folders are open
- parent = found
- # Insert directories first
- for directory in dirs:
- display_text = f"☐ {directory}"
- self.tree.insert(parent, 'end', text=display_text, open=True) # Ensure folders are open
- # Then insert files
- for file in files:
- display_text = f"☐ {file}"
- file_path = os.path.join(root_dir, file)
- self.tree.insert(parent, 'end', text=display_text, open=True, values=(file_path,))
- def on_click(self, event):
- region = self.tree.identify("region", event.x, event.y)
- if region != "tree":
- return
- item = self.tree.identify_row(event.y)
- if not item:
- return
- # Get current text
- current_text = self.tree.item(item, 'text')
- if current_text.startswith('☐ '):
- new_text = '☑ ' + current_text[2:]
- self.checked_items.add(item)
- elif current_text.startswith('☑ '):
- new_text = '☐ ' + current_text[2:]
- self.checked_items.discard(item)
- else:
- return # Not a selectable item
- # Update the text
- self.tree.item(item, text=new_text)
- def copy_files(self):
- # Generate structured representation of the project directory
- project_structure = self.generate_project_structure()
- combined_text = "Project Structure:\n" + project_structure + "\n\n"
- selected_files = []
- for item in self.checked_items:
- file_path = self.get_full_path(item)
- if os.path.isfile(file_path):
- selected_files.append(file_path)
- if not selected_files:
- messagebox.showwarning("No Selection", "Please select at least one file.")
- return
- for file_path in selected_files:
- rel_path = os.path.relpath(file_path, self.root_dir)
- combined_text += f"--------- {rel_path} ---------\n"
- try:
- with open(file_path, 'r', encoding='utf-8') as f:
- content = f.read()
- combined_text += content + "\n\n"
- except Exception as e:
- combined_text += f"Error reading {rel_path}: {e}\n\n"
- self.text_area.delete(1.0, tk.END)
- self.text_area.insert(tk.END, combined_text)
- def generate_project_structure(self):
- """Generates a structured representation of the project directory."""
- structure = ""
- for item in self.tree.get_children():
- structure += self._build_structure(item, 0)
- return structure
- def _build_structure(self, item, level):
- """Recursively builds the structure string."""
- indent = " " * level
- text = self.tree.item(item, 'text')[2:] # Remove checkbox symbol
- structure = ""
- if not self.tree.get_children(item): # It's a file
- structure += f"{indent}- {text}\n"
- else: # It's a directory
- structure += f"{indent}📂 {text}/\n"
- for child in self.tree.get_children(item):
- structure += self._build_structure(child, level + 1)
- return structure
- def get_full_path(self, item):
- parts = []
- while item:
- text = self.tree.item(item, 'text')
- # Remove checkbox symbol
- if text.startswith('☐ ') or text.startswith('☑ '):
- text = text[2:]
- parts.insert(0, text)
- item = self.tree.parent(item)
- return os.path.join(self.root_dir, *parts)
- if __name__ == "__main__":
- root = tk.Tk()
- app = FileSelectorApp(root)
- root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement