Modificar ecu_ascii_analyzer.py
This commit is contained in:
@ -2,6 +2,8 @@ import tkinter as tk
|
|||||||
from tkinter import filedialog, scrolledtext, ttk, messagebox
|
from tkinter import filedialog, scrolledtext, ttk, messagebox
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
|
import shutil # Nova importação para operações de ficheiro (cópia)
|
||||||
|
from datetime import datetime # Nova importação para timestamp
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
|
|
||||||
# Importações dos novos módulos de padrões
|
# Importações dos novos módulos de padrões
|
||||||
@ -16,6 +18,13 @@ from Data.bmw_ecu_group_handler import load_bmw_ecu_list # Nova importação par
|
|||||||
# from patterns.bmw_patterns import PATTERNS_BMW
|
# from patterns.bmw_patterns import PATTERNS_BMW
|
||||||
# etc.
|
# etc.
|
||||||
|
|
||||||
|
def sanitize_name(name):
|
||||||
|
"""Remove caracteres inválidos de uma string para usar como nome de ficheiro/pasta."""
|
||||||
|
# Remove ou substitui caracteres que são tipicamente problemáticos em nomes de ficheiro/pasta
|
||||||
|
name = re.sub(r'[\/*?"<>|:]', '_', name)
|
||||||
|
name = name.replace('\n', '_').replace('\r', '_')
|
||||||
|
return name[:100] # Limita o comprimento para evitar nomes excessivamente longos
|
||||||
|
|
||||||
# --- Constantes Globais ---
|
# --- Constantes Globais ---
|
||||||
BRAND_NAMES = ['VAG', 'LandRover/Jaguar', 'BMW', 'Mercedes', 'Renault/Dacia', 'Peugeot/Citroen', 'Opel', 'Fiat/Lancia/Alfa', 'Ford']
|
BRAND_NAMES = ['VAG', 'LandRover/Jaguar', 'BMW', 'Mercedes', 'Renault/Dacia', 'Peugeot/Citroen', 'Opel', 'Fiat/Lancia/Alfa', 'Ford']
|
||||||
|
|
||||||
@ -496,9 +505,13 @@ def create_main_window():
|
|||||||
global_progress_label = progress_label
|
global_progress_label = progress_label
|
||||||
|
|
||||||
brand_buttons_frame = ttk.Frame(root)
|
brand_buttons_frame = ttk.Frame(root)
|
||||||
brand_buttons_frame.pack(pady=5, padx=10, fill=tk.X)
|
brand_buttons_frame.pack(pady=5, padx=5, fill=tk.X)
|
||||||
global_brand_buttons_frame = brand_buttons_frame
|
global_brand_buttons_frame = brand_buttons_frame
|
||||||
|
|
||||||
|
# Botão Global File Organizer
|
||||||
|
file_organizer_button = ttk.Button(root, text="File Organizer", command=initiate_bmw_file_organizer)
|
||||||
|
file_organizer_button.pack(pady=5, padx=10, fill=tk.X)
|
||||||
|
|
||||||
category_buttons_frame = ttk.Frame(root)
|
category_buttons_frame = ttk.Frame(root)
|
||||||
category_buttons_frame.pack(pady=5, padx=10, fill=tk.X)
|
category_buttons_frame.pack(pady=5, padx=10, fill=tk.X)
|
||||||
global_category_buttons_frame = category_buttons_frame
|
global_category_buttons_frame = category_buttons_frame
|
||||||
@ -510,5 +523,124 @@ def create_main_window():
|
|||||||
clear_ui_state() # Limpa a UI antes de iniciar
|
clear_ui_state() # Limpa a UI antes de iniciar
|
||||||
root.mainloop()
|
root.mainloop()
|
||||||
|
|
||||||
|
def process_folder_for_bmw_organization(source_folder, base_destination_folder, progress_callback=None):
|
||||||
|
"""Processa uma pasta, analisa ficheiros BMW e organiza-os em subpastas nomeadas."""
|
||||||
|
processed_files = 0
|
||||||
|
failed_files = 0
|
||||||
|
total_files = sum([len(files) for r, d, files in os.walk(source_folder)])
|
||||||
|
current_file_count = 0
|
||||||
|
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback(0, total_files, "Iniciando organização...")
|
||||||
|
|
||||||
|
for root, _, files in os.walk(source_folder):
|
||||||
|
for filename in files:
|
||||||
|
current_file_count += 1
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback(current_file_count, total_files, f"Processando: {filename}")
|
||||||
|
|
||||||
|
file_path = os.path.join(root, filename)
|
||||||
|
try:
|
||||||
|
ascii_content = read_file_content(file_path)
|
||||||
|
if not ascii_content:
|
||||||
|
print(f"Não foi possível ler o conteúdo ASCII de: {filename}")
|
||||||
|
failed_files += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Realiza uma análise inicial para 'Ecu Family' e 'Possible Software Number'
|
||||||
|
initial_patterns = {key: PATTERNS_COMMON[key] for key in INITIAL_ANALYSIS_PATTERNS_KEYS if key in PATTERNS_COMMON}
|
||||||
|
analysis_results = analyze_ascii_patterns_from_file(ascii_content, initial_patterns)
|
||||||
|
|
||||||
|
ecu_family_data = analysis_results.get('Ecu Family', {})
|
||||||
|
sw_number_data = analysis_results.get('Possible Software Number', {})
|
||||||
|
|
||||||
|
# Pega o primeiro (ou mais comum) Ecu Family e Software Number
|
||||||
|
# Pode ser necessário refinar esta lógica para escolher o "melhor" se houver múltiplos
|
||||||
|
main_ecu_family = next(iter(ecu_family_data.keys()), "UnknownECU")
|
||||||
|
main_sw_number = next(iter(sw_number_data.keys()), "UnknownSW")
|
||||||
|
|
||||||
|
# Sanitiza os nomes para criar nomes de pasta válidos
|
||||||
|
s_ecu_family = sanitize_name(main_ecu_family)
|
||||||
|
s_sw_number = sanitize_name(main_sw_number)
|
||||||
|
s_filename = sanitize_name(os.path.splitext(filename)[0]) # Nome do ficheiro sem extensão
|
||||||
|
|
||||||
|
# Cria o nome da pasta da família da ECU
|
||||||
|
ecu_family_folder_name = s_ecu_family
|
||||||
|
ecu_family_path = os.path.join(base_destination_folder, ecu_family_folder_name)
|
||||||
|
os.makedirs(ecu_family_path, exist_ok=True)
|
||||||
|
|
||||||
|
# Cria o nome da subpasta de destino final dentro da pasta da família da ECU
|
||||||
|
# Ex: BMW_EDC17C41_10SW012345_NomeOriginalDoFicheiro
|
||||||
|
subfolder_name = f"BMW_{s_ecu_family}_{s_sw_number}_{s_filename}"
|
||||||
|
destination_subfolder = os.path.join(ecu_family_path, subfolder_name)
|
||||||
|
|
||||||
|
os.makedirs(destination_subfolder, exist_ok=True)
|
||||||
|
|
||||||
|
# Copia o ficheiro original
|
||||||
|
shutil.copy2(file_path, os.path.join(destination_subfolder, filename))
|
||||||
|
|
||||||
|
# Cria o ficheiro de texto com os dados recolhidos
|
||||||
|
info_file_path = os.path.join(destination_subfolder, f"info_{s_filename}.txt")
|
||||||
|
with open(info_file_path, 'w', encoding='utf-8') as info_f:
|
||||||
|
info_f.write(f"Ficheiro Original: {filename}\n")
|
||||||
|
info_f.write(f"Caminho Original: {file_path}\n")
|
||||||
|
info_f.write(f"Data da Análise: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")
|
||||||
|
info_f.write(f"Ecu Family Encontrada: {main_ecu_family}\n")
|
||||||
|
if ecu_family_data:
|
||||||
|
for ecu, count in ecu_family_data.items():
|
||||||
|
info_f.write(f" - {ecu} (Contagem: {count})\n")
|
||||||
|
info_f.write(f"\nSoftware Number Encontrado: {main_sw_number}\n")
|
||||||
|
if sw_number_data:
|
||||||
|
for sw, count in sw_number_data.items():
|
||||||
|
info_f.write(f" - {sw} (Contagem: {count})\n")
|
||||||
|
# Adicionar mais dados se necessário
|
||||||
|
|
||||||
|
processed_files += 1
|
||||||
|
except PermissionError as e_perm:
|
||||||
|
print(f"Erro de permissão ao processar o ficheiro {filename}: {e_perm}. O ficheiro pode estar em uso.")
|
||||||
|
failed_files += 1
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Erro geral ao processar o ficheiro {filename}: {e}")
|
||||||
|
failed_files += 1
|
||||||
|
# Considerar logar o erro para um ficheiro de log
|
||||||
|
|
||||||
|
if progress_callback:
|
||||||
|
progress_callback(total_files, total_files, "Organização concluída!")
|
||||||
|
|
||||||
|
return processed_files, failed_files
|
||||||
|
|
||||||
|
def initiate_bmw_file_organizer():
|
||||||
|
source_dir = filedialog.askdirectory(title="Selecione a Pasta de Origem com Ficheiros BMW")
|
||||||
|
if not source_dir:
|
||||||
|
messagebox.showinfo("Cancelado", "Operação de organização cancelada.")
|
||||||
|
return
|
||||||
|
|
||||||
|
dest_dir = filedialog.askdirectory(title="Selecione a Pasta de Destino Base para Organização")
|
||||||
|
if not dest_dir:
|
||||||
|
messagebox.showinfo("Cancelado", "Operação de organização cancelada.")
|
||||||
|
return
|
||||||
|
|
||||||
|
if global_progress_bar and global_progress_label:
|
||||||
|
def progress_update(current, total, message):
|
||||||
|
global_progress_label.config(text=message)
|
||||||
|
if total > 0:
|
||||||
|
percentage = (current / total) * 100
|
||||||
|
global_progress_bar['value'] = percentage
|
||||||
|
else:
|
||||||
|
global_progress_bar['value'] = 0
|
||||||
|
if global_root_window: global_root_window.update_idletasks()
|
||||||
|
|
||||||
|
try:
|
||||||
|
processed, failed = process_folder_for_bmw_organization(source_dir, dest_dir, progress_update)
|
||||||
|
summary_message = f"Organização Concluída.\nFicheiros Processados com Sucesso: {processed}\nFicheiros com Falha: {failed}"
|
||||||
|
messagebox.showinfo("Concluído", summary_message)
|
||||||
|
except Exception as e:
|
||||||
|
messagebox.showerror("Erro na Organização", f"Ocorreu um erro: {e}")
|
||||||
|
if global_progress_label: global_progress_label.config(text="Erro na organização.")
|
||||||
|
if global_progress_bar: global_progress_bar['value'] = 0
|
||||||
|
else:
|
||||||
|
messagebox.showerror("Erro", "Componentes de progresso não inicializados.")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
create_main_window()
|
create_main_window()
|
||||||
Reference in New Issue
Block a user