Advertisement
Guest User

Untitled

a guest
Mar 27th, 2025
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.93 KB | None | 0 0
  1. import os
  2. import tkinter as tk
  3. from tkinter import ttk
  4. from tkinter import filedialog, messagebox
  5. import tkinter.font as tkFont
  6.  
  7.  
  8. class FileSelectorApp:
  9. def __init__(self, root):
  10. self.root = root
  11. self.root.title("Python Project File Selector")
  12. self.root.geometry("1600x1000") # Increased width for better layout
  13. self.root_dir = ""
  14. self.checked_items = set()
  15. # Configure the main window's grid
  16. self.root.columnconfigure(0, weight=1)
  17. self.root.columnconfigure(1, weight=3)
  18. self.root.rowconfigure(1, weight=1)
  19. # Configure Style for Treeview
  20. style = ttk.Style()
  21. style.configure("Treeview", font=("Helvetica", 12)) # Set desired font family and size
  22. # Optionally, you can configure headings if needed
  23. style.configure("Treeview.Heading", font=("Helvetica", 12, "bold"))
  24. # Top Frame for directory selection
  25. top_frame = ttk.Frame(root)
  26. top_frame.grid(row=0, column=0, columnspan=2, sticky="ew", padx=10, pady=5)
  27. top_frame.columnconfigure(1, weight=1)
  28. self.dir_label = ttk.Label(top_frame, text="No directory selected")
  29. self.dir_label.grid(row=1, column=0, padx=(0, 10), sticky="w")
  30. select_dir_btn = ttk.Button(top_frame, text="Select Project Root", command=self.select_directory)
  31. select_dir_btn.grid(row=0, column=0, sticky='w')
  32. # Main Frame divided into Left and Right
  33. main_frame = ttk.Frame(root)
  34. main_frame.grid(row=1, column=0, columnspan=2, sticky="nsew", padx=10, pady=5)
  35. main_frame.columnconfigure(0, weight=1)
  36. main_frame.columnconfigure(1, weight=3)
  37. main_frame.rowconfigure(0, weight=1)
  38. # Left Frame for Treeview and Copy Button
  39. left_frame = ttk.Frame(main_frame)
  40. left_frame.grid(row=0, column=0, sticky="nsew")
  41. left_frame.columnconfigure(0, weight=1)
  42. left_frame.rowconfigure(0, weight=1)
  43. # Treeview Frame within Left Frame
  44. tree_frame = ttk.Frame(left_frame)
  45. tree_frame.grid(row=0, column=0, sticky="nsew")
  46. self.tree = ttk.Treeview(tree_frame, columns=("File Name"), show='tree')
  47. self.tree.pack(fill=tk.BOTH, expand=True, side=tk.LEFT)
  48. # Scrollbar for Treeview
  49. tree_scrollbar = ttk.Scrollbar(tree_frame, orient="vertical", command=self.tree.yview)
  50. tree_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
  51. self.tree.configure(yscrollcommand=tree_scrollbar.set)
  52. # Bind click event for checkbox toggling
  53. self.tree.bind('<Button-1>', self.on_click)
  54. # Copy Button below Treeview
  55. copy_btn = ttk.Button(left_frame, text="Copy Selected Files", command=self.copy_files)
  56. copy_btn.grid(row=1, column=0, pady=5, sticky="ew")
  57. # Right Frame for Text Area
  58. right_frame = ttk.Frame(main_frame)
  59. right_frame.grid(row=0, column=1, sticky="nsew")
  60. right_frame.columnconfigure(0, weight=1)
  61. right_frame.rowconfigure(0, weight=1)
  62. # Text Area with Scrollbar
  63. text_frame = ttk.Frame(right_frame)
  64. text_frame.grid(row=0, column=0, sticky="nsew")
  65. self.text_area = tk.Text(text_frame, wrap="none")
  66. self.text_area.pack(fill=tk.BOTH, expand=True, side=tk.LEFT)
  67. # Vertical Scrollbar for Text Area
  68. text_scrollbar = ttk.Scrollbar(text_frame, orient="vertical", command=self.text_area.yview)
  69. text_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
  70. self.text_area.configure(yscrollcommand=text_scrollbar.set)
  71.  
  72. def select_directory(self):
  73. dir_path = filedialog.askdirectory()
  74. if dir_path:
  75. self.root_dir = dir_path
  76. self.dir_label.config(text=f"Project Root: {self.root_dir}")
  77. self.populate_tree()
  78.  
  79. def populate_tree(self):
  80. self.tree.delete(*self.tree.get_children())
  81. self.checked_items.clear()
  82. for root_dir, dirs, files in os.walk(self.root_dir):
  83. # Relative path from the root directory
  84. rel_path = os.path.relpath(root_dir, self.root_dir)
  85. if rel_path == ".":
  86. rel_path = ""
  87.  
  88. # Modify dirs in-place to exclude certain folders
  89. dirs[:] = [d for d in dirs if not d.startswith('.') and d not in ['venv', '__pycache__']]
  90.  
  91. # Sort directories and files: directories first, then files
  92. dirs.sort()
  93. files = sorted([f for f in files if not f.endswith('.pyc')])
  94.  
  95. path_parts = rel_path.split(os.sep) if rel_path else []
  96. parent = ''
  97.  
  98. # Traverse or create the path in the Treeview
  99. for part in path_parts:
  100. # Find existing parent
  101. found = None
  102. for child in self.tree.get_children(parent):
  103. # Remove checkbox symbols before comparison
  104. child_text = self.tree.item(child, 'text').strip('☐☑ ')
  105. if child_text == part:
  106. found = child
  107. break
  108. if not found:
  109. display_text = f"☐ {part}"
  110. found = self.tree.insert(parent, 'end', text=display_text, open=True) # Ensure folders are open
  111. parent = found
  112.  
  113. # Insert directories first
  114. for directory in dirs:
  115. display_text = f"☐ {directory}"
  116. self.tree.insert(parent, 'end', text=display_text, open=True) # Ensure folders are open
  117.  
  118. # Then insert files
  119. for file in files:
  120. display_text = f"☐ {file}"
  121. file_path = os.path.join(root_dir, file)
  122. self.tree.insert(parent, 'end', text=display_text, open=True, values=(file_path,))
  123.  
  124. def on_click(self, event):
  125. region = self.tree.identify("region", event.x, event.y)
  126. if region != "tree":
  127. return
  128. item = self.tree.identify_row(event.y)
  129. if not item:
  130. return
  131. # Get current text
  132. current_text = self.tree.item(item, 'text')
  133. if current_text.startswith('☐ '):
  134. new_text = '☑ ' + current_text[2:]
  135. self.checked_items.add(item)
  136. elif current_text.startswith('☑ '):
  137. new_text = '☐ ' + current_text[2:]
  138. self.checked_items.discard(item)
  139. else:
  140. return # Not a selectable item
  141. # Update the text
  142. self.tree.item(item, text=new_text)
  143.  
  144. def copy_files(self):
  145.  
  146. # Generate structured representation of the project directory
  147. project_structure = self.generate_project_structure()
  148. combined_text = "Project Structure:\n" + project_structure + "\n\n"
  149.  
  150. selected_files = []
  151. for item in self.checked_items:
  152. file_path = self.get_full_path(item)
  153. if os.path.isfile(file_path):
  154. selected_files.append(file_path)
  155.  
  156. if not selected_files:
  157. messagebox.showwarning("No Selection", "Please select at least one file.")
  158. return
  159.  
  160. for file_path in selected_files:
  161. rel_path = os.path.relpath(file_path, self.root_dir)
  162. combined_text += f"--------- {rel_path} ---------\n"
  163. try:
  164. with open(file_path, 'r', encoding='utf-8') as f:
  165. content = f.read()
  166. combined_text += content + "\n\n"
  167. except Exception as e:
  168. combined_text += f"Error reading {rel_path}: {e}\n\n"
  169. self.text_area.delete(1.0, tk.END)
  170. self.text_area.insert(tk.END, combined_text)
  171.  
  172. def generate_project_structure(self):
  173. """Generates a structured representation of the project directory."""
  174. structure = ""
  175. for item in self.tree.get_children():
  176. structure += self._build_structure(item, 0)
  177. return structure
  178.  
  179. def _build_structure(self, item, level):
  180. """Recursively builds the structure string."""
  181. indent = " " * level
  182. text = self.tree.item(item, 'text')[2:] # Remove checkbox symbol
  183. structure = ""
  184.  
  185. if not self.tree.get_children(item): # It's a file
  186. structure += f"{indent}- {text}\n"
  187. else: # It's a directory
  188. structure += f"{indent}📂 {text}/\n"
  189. for child in self.tree.get_children(item):
  190. structure += self._build_structure(child, level + 1)
  191.  
  192. return structure
  193.  
  194. def get_full_path(self, item):
  195. parts = []
  196. while item:
  197. text = self.tree.item(item, 'text')
  198. # Remove checkbox symbol
  199. if text.startswith('☐ ') or text.startswith('☑ '):
  200. text = text[2:]
  201. parts.insert(0, text)
  202. item = self.tree.parent(item)
  203. return os.path.join(self.root_dir, *parts)
  204.  
  205.  
  206. if __name__ == "__main__":
  207. root = tk.Tk()
  208. app = FileSelectorApp(root)
  209. root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement