|
@@ -0,0 +1,444 @@
|
|
|
|
|
+import tkinter as tk
|
|
|
|
|
+
|
|
|
|
|
+class SquareWindow:
|
|
|
|
|
+ def __init__(self, config, path_info=None, path_mapping=None):
|
|
|
|
|
+ # Configuration: [(parent_number, count), ...]
|
|
|
|
|
+ # (None, 11) means draw 11 squares inside square #0 (the main square)
|
|
|
|
|
+ # (2, 7) means draw 7 squares inside square #2
|
|
|
|
|
+ # path_info: Optional dict mapping square numbers to file/folder names
|
|
|
|
|
+ # path_mapping: Optional dict mapping square numbers to file paths
|
|
|
|
|
+ self.config = config
|
|
|
|
|
+ self.path_info = path_info if path_info is not None else {}
|
|
|
|
|
+ self.number_to_path = path_mapping if path_mapping is not None else {}
|
|
|
|
|
+
|
|
|
|
|
+ # Set window size to 1000x1000 pixels (needed for calculate_squares)
|
|
|
|
|
+ self.window_size = 1000
|
|
|
|
|
+
|
|
|
|
|
+ # Calculate squares based on config
|
|
|
|
|
+ self.squares = self.calculate_squares()
|
|
|
|
|
+
|
|
|
|
|
+ # Create the main window
|
|
|
|
|
+ self.root = tk.Tk()
|
|
|
|
|
+ self.root.title("Square Window")
|
|
|
|
|
+
|
|
|
|
|
+ self.root.geometry(f"{self.window_size}x{self.window_size}")
|
|
|
|
|
+
|
|
|
|
|
+ # Create a canvas to draw on
|
|
|
|
|
+ self.canvas = tk.Canvas(self.root, width=self.window_size, height=self.window_size, bg="white")
|
|
|
|
|
+ self.canvas.pack(fill=tk.BOTH, expand=True)
|
|
|
|
|
+
|
|
|
|
|
+ # Property to store square information: {number: (x, y, size, parent_number)}
|
|
|
|
|
+ self.square_positions = {}
|
|
|
|
|
+
|
|
|
|
|
+ # Store original colors for flashing effect
|
|
|
|
|
+ self.original_colors = {}
|
|
|
|
|
+
|
|
|
|
|
+ # Draw all squares based on the calculated squares dictionary
|
|
|
|
|
+ for number, (x, y, size, parent_number) in self.squares.items():
|
|
|
|
|
+ self.draw_square_at_location(x, y, size, number, parent_number)
|
|
|
|
|
+
|
|
|
|
|
+ # Print the square positions dictionary
|
|
|
|
|
+ output_content = f"Square positions: {self.square_positions}"
|
|
|
|
|
+ print(output_content)
|
|
|
|
|
+
|
|
|
|
|
+ # Save the output to print.log file
|
|
|
|
|
+ with open("print.log", "w", encoding="utf-8") as f:
|
|
|
|
|
+ f.write(output_content)
|
|
|
|
|
+
|
|
|
|
|
+ # Initialize clipboard monitoring for file content search
|
|
|
|
|
+ self.highlighted_squares = set()
|
|
|
|
|
+ self.all_highlighted_squares = set() # Track all previously highlighted squares
|
|
|
|
|
+ self.check_clipboard_content()
|
|
|
|
|
+
|
|
|
|
|
+ def calculate_squares(self):
|
|
|
|
|
+ """
|
|
|
|
|
+ Calculate all squares based on the config.
|
|
|
|
|
+ Config format: [(parent_number, count), ...]
|
|
|
|
|
+ (None, count) means draw 'count' squares inside the main square (number 0)
|
|
|
|
|
+ (number, count) means draw 'count' squares inside square with 'number'
|
|
|
|
|
+ """
|
|
|
|
|
+ import math
|
|
|
|
|
+
|
|
|
|
|
+ # Initialize the main square (number 0)
|
|
|
|
|
+ main_square_size = int(self.window_size * 0.9) # 90% of 1000 = 900
|
|
|
|
|
+ margin = (self.window_size - main_square_size) // 2 # (1000 - 900) / 2 = 50
|
|
|
|
|
+
|
|
|
|
|
+ # Dictionary to store all squares: {number: (x, y, size, parent_number)}
|
|
|
|
|
+ squares = {}
|
|
|
|
|
+
|
|
|
|
|
+ # Add the main square (number 0)
|
|
|
|
|
+ squares[0] = (margin, margin, main_square_size, None)
|
|
|
|
|
+
|
|
|
|
|
+ # Track the next available number for new squares
|
|
|
|
|
+ next_number = 1
|
|
|
|
|
+
|
|
|
|
|
+ # Process each configuration entry
|
|
|
|
|
+ for parent_number, count in self.config:
|
|
|
|
|
+ if parent_number is None:
|
|
|
|
|
+ # Draw 'count' squares inside the main square (number 0)
|
|
|
|
|
+ parent_num = 0
|
|
|
|
|
+ else:
|
|
|
|
|
+ parent_num = parent_number
|
|
|
|
|
+
|
|
|
|
|
+ # Get the parent square's info
|
|
|
|
|
+ if parent_num in squares:
|
|
|
|
|
+ parent_x, parent_y, parent_size, _ = squares[parent_num]
|
|
|
|
|
+
|
|
|
|
|
+ # Handle case where count is 0
|
|
|
|
|
+ if count <= 0:
|
|
|
|
|
+ continue # Skip if there are no items to draw
|
|
|
|
|
+
|
|
|
|
|
+ # Calculate grid size for the child squares
|
|
|
|
|
+ n = math.ceil(math.sqrt(count)) # Number of rows/columns needed
|
|
|
|
|
+ child_size = (parent_size // n) - 2 # Size of each child square minus padding
|
|
|
|
|
+
|
|
|
|
|
+ # Calculate spacing to distribute squares evenly with gaps
|
|
|
|
|
+ total_used_space = n * child_size # Total space occupied by squares
|
|
|
|
|
+ remaining_space = parent_size - total_used_space # Remaining space for gaps
|
|
|
|
|
+ gap = remaining_space // (n + 1) # Gap between squares and margins
|
|
|
|
|
+
|
|
|
|
|
+ # Draw 'count' child squares inside the parent square
|
|
|
|
|
+ squares_drawn = 0
|
|
|
|
|
+ for i in range(n): # Rows
|
|
|
|
|
+ for j in range(n): # Columns
|
|
|
|
|
+ if squares_drawn >= count:
|
|
|
|
|
+ break
|
|
|
|
|
+
|
|
|
|
|
+ # Calculate position for each child square with proper spacing
|
|
|
|
|
+ child_x = parent_x + gap + j * (child_size + gap)
|
|
|
|
|
+ child_y = parent_y + gap + i * (child_size + gap)
|
|
|
|
|
+
|
|
|
|
|
+ # Add the child square to the dictionary
|
|
|
|
|
+ squares[next_number] = (child_x, child_y, child_size, parent_num)
|
|
|
|
|
+
|
|
|
|
|
+ next_number += 1
|
|
|
|
|
+ squares_drawn += 1
|
|
|
|
|
+ if squares_drawn >= count:
|
|
|
|
|
+ break
|
|
|
|
|
+
|
|
|
|
|
+ return squares
|
|
|
|
|
+
|
|
|
|
|
+ def draw_square_at_location(self, x, y, size, number, parent_number):
|
|
|
|
|
+ """
|
|
|
|
|
+ Draw a square at a specific location with a number in the center.
|
|
|
|
|
+
|
|
|
|
|
+ Args:
|
|
|
|
|
+ x: X coordinate of the top-left corner
|
|
|
|
|
+ y: Y coordinate of the top-left corner
|
|
|
|
|
+ size: Size of the square (width and height)
|
|
|
|
|
+ number: Number to display in the center
|
|
|
|
|
+ parent_number: The number of the parent square (None if no parent)
|
|
|
|
|
+ """
|
|
|
|
|
+ # Get the name associated with this square number if available
|
|
|
|
|
+ name = self.path_info.get(number, str(number))
|
|
|
|
|
+ # Calculate the level of the square (how deep it is in the hierarchy)
|
|
|
|
|
+ level = self.get_square_level(number)
|
|
|
|
|
+
|
|
|
|
|
+ # Define light colors for different levels (with transparency effect)
|
|
|
|
|
+ colors = [
|
|
|
|
|
+ "#E0E0E0", # Level 0 (light gray, main square)
|
|
|
|
|
+ "#FFCCCC", # Level 1 (light red)
|
|
|
|
|
+ "#CCE5FF", # Level 2 (light blue)
|
|
|
|
|
+ "#CCFFCC", # Level 3 (light green)
|
|
|
|
|
+ "#E5CCFF", # Level 4 (light purple)
|
|
|
|
|
+ "#FFE5CC", # Level 5 (light orange)
|
|
|
|
|
+ "#D9CCAA", # Level 6 (light brown)
|
|
|
|
|
+ "#FFD9E5", # Level 7 (light pink)
|
|
|
|
|
+ "#FFFFCC", # Level 8 (light yellow)
|
|
|
|
|
+ "#CCFFFF" # Level 9+ (light cyan)
|
|
|
|
|
+ ]
|
|
|
|
|
+
|
|
|
|
|
+ # Select color based on level
|
|
|
|
|
+ color = colors[level] if level < len(colors) else "gray"
|
|
|
|
|
+
|
|
|
|
|
+ # Draw the square with light colored fill (simulating transparency) and darker outline
|
|
|
|
|
+ outline_color = color.replace("#", "") # Get hex color without #
|
|
|
|
|
+ # Darken the outline color by reducing RGB values
|
|
|
|
|
+ if len(outline_color) == 6:
|
|
|
|
|
+ # Convert hex to RGB, then darken
|
|
|
|
|
+ r = max(0, int(outline_color[0:2], 16) - 60)
|
|
|
|
|
+ g = max(0, int(outline_color[2:4], 16) - 60)
|
|
|
|
|
+ b = max(0, int(outline_color[4:6], 16) - 60)
|
|
|
|
|
+ dark_outline = f"#{r:02x}{g:02x}{b:02x}"
|
|
|
|
|
+ else:
|
|
|
|
|
+ dark_outline = "black" # fallback
|
|
|
|
|
+
|
|
|
|
|
+ # Store the original color for flashing
|
|
|
|
|
+ self.original_colors[number] = color
|
|
|
|
|
+
|
|
|
|
|
+ # Create a semi-transparent effect using stipple pattern
|
|
|
|
|
+ # This creates a checkerboard-like pattern that simulates transparency
|
|
|
|
|
+ rect_id = self.canvas.create_rectangle(x, y, x + size, y + size, outline=dark_outline, fill=color, width=1, stipple='gray50')
|
|
|
|
|
+
|
|
|
|
|
+ # Tag the rectangle with the number for easy identification
|
|
|
|
|
+ self.canvas.addtag_withtag(f"square_{number}", rect_id)
|
|
|
|
|
+
|
|
|
|
|
+ # Draw a line segment at the bottom edge of the square (inside the square) only if size >= 50
|
|
|
|
|
+ if size >= 50:
|
|
|
|
|
+ line_y = y + size - 20 # Just above the bottom edge of the square
|
|
|
|
|
+ self.canvas.create_line(x, line_y, x + size, line_y, fill="black", width=1)
|
|
|
|
|
+
|
|
|
|
|
+ # Draw the name between the square and the line
|
|
|
|
|
+ name_y = y + size - 10 # Position the name between square and line
|
|
|
|
|
+ self.canvas.create_text(x + size // 2, name_y, text=name, fill="black", font=("Arial", 8))
|
|
|
|
|
+
|
|
|
|
|
+ # Record the square's position information
|
|
|
|
|
+ self.square_positions[number] = (x, y, size, parent_number)
|
|
|
|
|
+
|
|
|
|
|
+ def get_square_level(self, number):
|
|
|
|
|
+ """
|
|
|
|
|
+ Calculate the level of a square in the hierarchy.
|
|
|
|
|
+ Level 0: Main square (number 0)
|
|
|
|
|
+ Level 1: Direct children of main square
|
|
|
|
|
+ Level 2: Children of level 1 squares
|
|
|
|
|
+ etc.
|
|
|
|
|
+ """
|
|
|
|
|
+ if number == 0:
|
|
|
|
|
+ return 0
|
|
|
|
|
+
|
|
|
|
|
+ level = 1 # Start at level 1 since we're past the main square
|
|
|
|
|
+ current_parent = self.squares[number][3] # Get parent number from (x, y, size, parent_number)
|
|
|
|
|
+
|
|
|
|
|
+ while current_parent is not None:
|
|
|
|
|
+ level += 1
|
|
|
|
|
+ if current_parent == 0:
|
|
|
|
|
+ break
|
|
|
|
|
+ current_parent = self.squares[current_parent][3] # Get parent's parent
|
|
|
|
|
+
|
|
|
|
|
+ return level
|
|
|
|
|
+
|
|
|
|
|
+ def check_clipboard_content(self):
|
|
|
|
|
+ """Check clipboard content and highlight matching files"""
|
|
|
|
|
+ try:
|
|
|
|
|
+ # Get clipboard content
|
|
|
|
|
+ clipboard_content = self.root.clipboard_get()
|
|
|
|
|
+
|
|
|
|
|
+ # Find all files that contain the clipboard content
|
|
|
|
|
+ matching_squares = set()
|
|
|
|
|
+ if clipboard_content and len(clipboard_content.strip()) > 0:
|
|
|
|
|
+ matching_squares = self.search_files_for_content(clipboard_content)
|
|
|
|
|
+
|
|
|
|
|
+ # Update highlighted squares
|
|
|
|
|
+ old_highlighted = self.highlighted_squares.copy()
|
|
|
|
|
+ self.highlighted_squares = matching_squares
|
|
|
|
|
+
|
|
|
|
|
+ # If there are changes, update the highlighted squares
|
|
|
|
|
+ if old_highlighted != self.highlighted_squares:
|
|
|
|
|
+ # Update the colors of highlighted squares
|
|
|
|
|
+ self.update_highlighted_squares()
|
|
|
|
|
+
|
|
|
|
|
+ except tk.TclError:
|
|
|
|
|
+ # Clipboard is empty or contains non-text data
|
|
|
|
|
+ old_highlighted = self.highlighted_squares.copy()
|
|
|
|
|
+ self.highlighted_squares = set()
|
|
|
|
|
+
|
|
|
|
|
+ # Restore colors of previously highlighted squares
|
|
|
|
|
+ for square_num in old_highlighted:
|
|
|
|
|
+ self.restore_square_color(square_num)
|
|
|
|
|
+
|
|
|
|
|
+ # Schedule next check
|
|
|
|
|
+ self.root.after(1000, self.check_clipboard_content) # Check every second
|
|
|
|
|
+
|
|
|
|
|
+ def restore_square_color(self, square_num):
|
|
|
|
|
+ """Restore the original color of a square"""
|
|
|
|
|
+ if square_num in self.squares:
|
|
|
|
|
+ x, y, size, parent_number = self.squares[square_num]
|
|
|
|
|
+
|
|
|
|
|
+ # Find the rectangle item for this square
|
|
|
|
|
+ tags = f"square_{square_num}"
|
|
|
|
|
+ items = self.canvas.find_withtag(tags)
|
|
|
|
|
+
|
|
|
|
|
+ # Restore original color
|
|
|
|
|
+ original_color = self.original_colors.get(square_num, "#FFFFFF")
|
|
|
|
|
+ for item in items:
|
|
|
|
|
+ if "rectangle" in str(self.canvas.type(item)):
|
|
|
|
|
+ self.canvas.itemconfig(item, fill=original_color)
|
|
|
|
|
+
|
|
|
|
|
+ def stop_flashing(self):
|
|
|
|
|
+ """Stop the highlighting (placeholder function)"""
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+ def search_files_for_content(self, search_content):
|
|
|
|
|
+ """Search all text files for the given content and return matching square numbers"""
|
|
|
|
|
+ import os
|
|
|
|
|
+
|
|
|
|
|
+ matching_squares = set()
|
|
|
|
|
+
|
|
|
|
|
+ # Only search files (not directories) that contain the search content
|
|
|
|
|
+ if hasattr(self, 'number_to_path'):
|
|
|
|
|
+ for number, path in self.number_to_path.items():
|
|
|
|
|
+ # Double-check that this is a file, not a directory
|
|
|
|
|
+ # Using both isfile() and not isdir() for extra safety
|
|
|
|
|
+ # Double-check that this is a file, not a directory
|
|
|
|
|
+ # Using both isfile() and not isdir() for extra safety
|
|
|
|
|
+ if os.path.isfile(path) and not os.path.isdir(path):
|
|
|
|
|
+ try:
|
|
|
|
|
+ # Try to read the file as text
|
|
|
|
|
+ with open(path, 'r', encoding='utf-8', errors='ignore') as f:
|
|
|
|
|
+ content = f.read()
|
|
|
|
|
+ if search_content.lower() in content.lower():
|
|
|
|
|
+ matching_squares.add(number)
|
|
|
|
|
+ except Exception:
|
|
|
|
|
+ # If we can't read the file, skip it
|
|
|
|
|
+ continue
|
|
|
|
|
+
|
|
|
|
|
+ return matching_squares
|
|
|
|
|
+
|
|
|
|
|
+ def update_highlighted_squares(self):
|
|
|
|
|
+ """Update the color of highlighted squares to red"""
|
|
|
|
|
+ # First, restore all previously highlighted squares to their original color
|
|
|
|
|
+ for square_num in self.all_highlighted_squares:
|
|
|
|
|
+ if square_num in self.squares:
|
|
|
|
|
+ x, y, size, parent_number = self.squares[square_num]
|
|
|
|
|
+
|
|
|
|
|
+ # Find the rectangle item for this square
|
|
|
|
|
+ tags = f"square_{square_num}"
|
|
|
|
|
+ items = self.canvas.find_withtag(tags)
|
|
|
|
|
+
|
|
|
|
|
+ # Restore original color
|
|
|
|
|
+ original_color = self.original_colors.get(square_num, "#FFFFFF")
|
|
|
|
|
+ for item in items:
|
|
|
|
|
+ if "rectangle" in str(self.canvas.type(item)):
|
|
|
|
|
+ self.canvas.itemconfig(item, fill=original_color)
|
|
|
|
|
+
|
|
|
|
|
+ # Now highlight the new matching squares in red
|
|
|
|
|
+ for square_num in self.highlighted_squares:
|
|
|
|
|
+ if square_num in self.squares:
|
|
|
|
|
+ x, y, size, parent_number = self.squares[square_num]
|
|
|
|
|
+
|
|
|
|
|
+ # Find the rectangle item for this square
|
|
|
|
|
+ tags = f"square_{square_num}"
|
|
|
|
|
+ items = self.canvas.find_withtag(tags)
|
|
|
|
|
+
|
|
|
|
|
+ # Change color to red
|
|
|
|
|
+ for item in items:
|
|
|
|
|
+ if "rectangle" in str(self.canvas.type(item)):
|
|
|
|
|
+ self.canvas.itemconfig(item, fill="red")
|
|
|
|
|
+
|
|
|
|
|
+ # Update the set of all highlighted squares
|
|
|
|
|
+ self.all_highlighted_squares = self.highlighted_squares.copy()
|
|
|
|
|
+
|
|
|
|
|
+ def find_square_items_by_position(self, x, y, size):
|
|
|
|
|
+ """Find canvas item IDs that correspond to a square at the given position"""
|
|
|
|
|
+ # Find items by coordinates
|
|
|
|
|
+ items = []
|
|
|
|
|
+ overlapping = self.canvas.find_overlapping(x, y, x + size, y + size)
|
|
|
|
|
+
|
|
|
|
|
+ for item in overlapping:
|
|
|
|
|
+ # Check if this item is part of a square we drew
|
|
|
|
|
+ tags = self.canvas.gettags(item)
|
|
|
|
|
+ if any('square' in tag.lower() for tag in tags) or len(tags) == 0: # Assume squares have no special tags or 'square' in tag
|
|
|
|
|
+ items.append(item)
|
|
|
|
|
+
|
|
|
|
|
+ return items
|
|
|
|
|
+
|
|
|
|
|
+ def run(self):
|
|
|
|
|
+ self.root.mainloop()
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def folder_to_config(folder_path, skip_folder=[]):
|
|
|
|
|
+ """
|
|
|
|
|
+ 根据文件夹路径生成配置列表,表示每个文件夹下的子项数量。
|
|
|
|
|
+
|
|
|
|
|
+ Args:
|
|
|
|
|
+ folder_path: 要分析的根文件夹路径
|
|
|
|
|
+ skip_folder: 不需要遍历的文件夹名称列表
|
|
|
|
|
+
|
|
|
|
|
+ Returns:
|
|
|
|
|
+ tuple: (config_list, path_info_dict, path_mapping_dict)
|
|
|
|
|
+ config_list: 包含(父级编号, 子项数量)元组的列表
|
|
|
|
|
+ (None, n) 表示根目录下有n个子项
|
|
|
|
|
+ path_info_dict: 映射编号到文件/文件夹名称的字典
|
|
|
|
|
+ path_mapping_dict: 映射编号到完整文件路径的字典
|
|
|
|
|
+ """
|
|
|
|
|
+ import os
|
|
|
|
|
+
|
|
|
|
|
+ # 存储路径到编号的映射
|
|
|
|
|
+ path_to_number = {}
|
|
|
|
|
+ number_to_name = {}
|
|
|
|
|
+ number_to_path = {} # 新增:编号到路径的映射
|
|
|
|
|
+
|
|
|
|
|
+ # 首先为根目录分配编号
|
|
|
|
|
+ path_to_number[folder_path] = 0
|
|
|
|
|
+ number_to_name[0] = os.path.basename(folder_path)
|
|
|
|
|
+ number_to_path[0] = folder_path # 添加路径映射
|
|
|
|
|
+
|
|
|
|
|
+ # 使用栈进行迭代式深度优先遍历,确保正确处理父子关系
|
|
|
|
|
+ stack = [folder_path]
|
|
|
|
|
+
|
|
|
|
|
+ while stack:
|
|
|
|
|
+ current_path = stack.pop()
|
|
|
|
|
+
|
|
|
|
|
+ try:
|
|
|
|
|
+ items = os.listdir(current_path)
|
|
|
|
|
+
|
|
|
|
|
+ # 获取当前目录的直接子项(过滤掉需要跳过的目录)
|
|
|
|
|
+ direct_children = []
|
|
|
|
|
+ for item in items:
|
|
|
|
|
+ item_path = os.path.join(current_path, item)
|
|
|
|
|
+
|
|
|
|
|
+ # 检查是否是需要跳过的目录
|
|
|
|
|
+ if os.path.isdir(item_path) and os.path.basename(item_path) in skip_folder:
|
|
|
|
|
+ continue
|
|
|
|
|
+
|
|
|
|
|
+ direct_children.append(item_path)
|
|
|
|
|
+
|
|
|
|
|
+ # 为所有直接子项分配编号
|
|
|
|
|
+ for item_path in direct_children:
|
|
|
|
|
+ if item_path not in path_to_number:
|
|
|
|
|
+ number = len(path_to_number)
|
|
|
|
|
+ path_to_number[item_path] = number
|
|
|
|
|
+ number_to_name[number] = os.path.basename(item_path)
|
|
|
|
|
+ number_to_path[number] = item_path # 添加路径映射
|
|
|
|
|
+
|
|
|
|
|
+ # 如果是目录且不在跳过列表中,加入栈中待处理
|
|
|
|
|
+ if os.path.isdir(item_path):
|
|
|
|
|
+ stack.append(item_path)
|
|
|
|
|
+
|
|
|
|
|
+ except PermissionError:
|
|
|
|
|
+ # 如果没有权限访问某个文件夹,则跳过
|
|
|
|
|
+ continue
|
|
|
|
|
+
|
|
|
|
|
+ # 构建结果 - 计算每个目录的直接子项数量
|
|
|
|
|
+ result = []
|
|
|
|
|
+
|
|
|
|
|
+ # 添加根目录信息
|
|
|
|
|
+ root_items = []
|
|
|
|
|
+ try:
|
|
|
|
|
+ items = os.listdir(folder_path)
|
|
|
|
|
+ for item in items:
|
|
|
|
|
+ item_path = os.path.join(folder_path, item)
|
|
|
|
|
+ if not (os.path.isdir(item_path) and os.path.basename(item_path) in skip_folder):
|
|
|
|
|
+ root_items.append(item_path)
|
|
|
|
|
+ except PermissionError:
|
|
|
|
|
+ pass
|
|
|
|
|
+
|
|
|
|
|
+ result.append((None, len(root_items))) # 根目录用None表示
|
|
|
|
|
+
|
|
|
|
|
+ # 为每个目录添加信息(除了根目录)
|
|
|
|
|
+ for path in path_to_number:
|
|
|
|
|
+ if path != folder_path and os.path.isdir(path): # 排除根目录,只处理子目录
|
|
|
|
|
+ try:
|
|
|
|
|
+ items = os.listdir(path)
|
|
|
|
|
+ # 计算当前目录的直接子项数量(过滤掉需要跳过的目录)
|
|
|
|
|
+ child_count = 0
|
|
|
|
|
+ for item in items:
|
|
|
|
|
+ item_path = os.path.join(path, item)
|
|
|
|
|
+ if not (os.path.isdir(item_path) and os.path.basename(item_path) in skip_folder):
|
|
|
|
|
+ child_count += 1
|
|
|
|
|
+
|
|
|
|
|
+ parent_number = path_to_number[path]
|
|
|
|
|
+ result.append((parent_number, child_count))
|
|
|
|
|
+ except PermissionError:
|
|
|
|
|
+ # 如果无法访问目录,子项数量为0
|
|
|
|
|
+ parent_number = path_to_number[path]
|
|
|
|
|
+ result.append((parent_number, 0))
|
|
|
|
|
+
|
|
|
|
|
+ return result, number_to_name, number_to_path
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+if __name__ == "__main__":
|
|
|
|
|
+ config, path_info, path_mapping = folder_to_config(r"E:\agricultural_research_platform", skip_folder=["automatedDeployment", "node_modules", ".vscode", ".git", "images"])
|
|
|
|
|
+ print(config)
|
|
|
|
|
+ app = SquareWindow(config, path_info, path_mapping)
|
|
|
|
|
+ app.run()
|