#!/usr/bin/env python3 """ Add m_logger member variables to Qt6 class definitions. Matches Qt5 and Qt6 headers by file path, then checks for m_logger. """ import os import re import sys from pathlib import Path # Paths SCRIPT_DIR = Path(__file__).parent QT5_BASE = SCRIPT_DIR / "qt5-before/qt5-legatus-legacy" QT6_BASE = SCRIPT_DIR / "qt6-after/qt6-migrated-legatus" def find_qt5_headers_with_logger(): """Find all Qt5 headers with m_logger members""" qt5_headers = [] for header in QT5_BASE.rglob("*.h"): try: content = header.read_text(encoding='utf-8', errors='ignore') if 'm_logger' in content: rel_path = header.relative_to(QT5_BASE) qt5_headers.append(rel_path) except Exception as e: pass print(f"Found {len(qt5_headers)} Qt5 headers with m_logger") return qt5_headers def find_qt6_header(rel_path): """Find corresponding Qt6 header by relative path""" qt6_header = QT6_BASE / rel_path if qt6_header.exists(): return qt6_header # Try .hpp extension qt6_header_hpp = QT6_BASE / rel_path.with_suffix('.hpp') if qt6_header_hpp.exists(): return qt6_header_hpp # Try lowercase path qt6_header_lower = QT6_BASE / str(rel_path).lower() if qt6_header_lower.exists(): return qt6_header_lower # Try snake_case conversion for filename filename = rel_path.name snake_name = ''.join(['_' + c.lower() if c.isupper() else c for c in filename.split('.')[0]]).lstrip('_') snake_path = rel_path.parent / f"{snake_name}{rel_path.suffix}" qt6_header_snake = QT6_BASE / snake_path if qt6_header_snake.exists(): return qt6_header_snake return None def add_logger_to_header(header_path): """Add m_logger member to class definition""" try: content = header_path.read_text(encoding='utf-8') # Check if already has m_logger if 'm_logger' in content: return False, "Already has m_logger" # Find private: or protected: section (handle comments after colon) pattern = r'^(\s*)(private|protected):\s*(?:\/\/.*)?\s*\n' match = re.search(pattern, content, re.MULTILINE) if not match: # Try finding end of class with just closing brace lines = content.split('\n') for i in range(len(lines) - 1, 0, -1): if re.match(r'^\s*};\s*$', lines[i]): indent = re.match(r'^(\s*)', lines[i]).group(1) lines.insert(i, f"{indent}NGL::INGLLogger &m_logger;") new_content = '\n'.join(lines) header_path.write_text(new_content, encoding='utf-8') return True, "Added (fallback)" return False, "No private/protected section found" # Insert m_logger after the access specifier line indent = match.group(1) insert_pos = match.end() new_content = content[:insert_pos] + indent + "NGL::INGLLogger &m_logger;\n" + content[insert_pos:] header_path.write_text(new_content, encoding='utf-8') return True, "Added" except Exception as e: return False, f"Error: {str(e)}" def main(): print("=" * 80) print("Adding m_logger members to Qt6 headers") print("=" * 80) # Find Qt5 headers with m_logger qt5_headers = find_qt5_headers_with_logger() # Track results added = 0 skipped = 0 skip_reasons = {} not_found_examples = [] for rel_path in qt5_headers: # Find corresponding Qt6 header qt6_header = find_qt6_header(rel_path) if not qt6_header: skipped += 1 reason = "Header not found" skip_reasons[reason] = skip_reasons.get(reason, 0) + 1 if len(not_found_examples) < 10: not_found_examples.append(str(rel_path)) continue # Try to add logger success, message = add_logger_to_header(qt6_header) if success: added += 1 if added <= 10: print(f"ADDED: {rel_path} -> {message}") else: skipped += 1 reason = message if not message.startswith("Already") else "Already has m_logger" skip_reasons[reason] = skip_reasons.get(reason, 0) + 1 print("\n" + "=" * 80) print(f"Results: {added} headers updated, {skipped} skipped") print("\nSkip reasons:") for reason, count in sorted(skip_reasons.items(), key=lambda x: -x[1]): print(f" {reason}: {count}") if not_found_examples: print("\nHeader not found examples (first 10):") for example in not_found_examples: print(f" - {example}") print("=" * 80) if __name__ == "__main__": main()