#!/usr/bin/env python3 """ Fix Qt6 API compatibility issues in training_area_telegrams.cpp Handles two struct patterns: - Pattern A: private m_* members with getter methods (Header, BatteryState) - Pattern B: public direct members (most other structs) """ import re from pathlib import Path cpp_file = Path('/home/torsten/swy/sandbox/qt-migration-legatus/qt6-after/qt6-migrated-legatus/Lts/Proxies/TrainingAreaBase/training_area_telegrams.cpp') h_file = Path('/home/torsten/swy/sandbox/qt-migration-legatus/qt6-after/qt6-migrated-legatus/Lts/Proxies/TrainingAreaBase/training_area_telegrams.h') # Parse header to determine struct member patterns def parse_struct_members(header_content): """Returns dict: struct_name -> {'has_m_prefix': bool, 'members': list}""" structs = {} # Match struct definitions struct_pattern = r'^struct\s+(\w+)(?:\s*:[^{\n]+)?\s*\{(.*?)^\};' for match in re.finditer(struct_pattern, header_content, re.MULTILINE | re.DOTALL): struct_name = match.group(1) body = match.group(2) # Find member variables (lines with type and name, not functions) members = [] has_m_prefix = False for line in body.split('\n'): line = line.strip() # Skip empty lines, comments, functions, static, etc. if not line or line.startswith('//') or line.startswith('static') or \ line.startswith('virtual') or '(' in line or line.startswith('}'): continue # Match member variable declarations member_match = re.match(r'(?:mutable\s+)?(?:const\s+)?(\w+(?:\s*<[^>]+>)?)\s+(\w+)(?:\s*=\s*[^;]+)?;', line) if member_match: member_name = member_match.group(2) members.append(member_name) if member_name.startswith('m_'): has_m_prefix = True if members: structs[struct_name] = { 'has_m_prefix': has_m_prefix, 'members': members } return structs # Read files with open(h_file, 'r') as f: header_content = f.read() with open(cpp_file, 'r') as f: cpp_content = f.read() # Parse struct patterns structs = parse_struct_members(header_content) print(f"Found {len(structs)} structs") for name, info in list(structs.items())[:10]: print(f" {name}: m_prefix={info['has_m_prefix']}, members={info['members'][:3]}...") # Fix fromJson functions def fix_fromJson(content, structs): """Fix fromJson to assign to correct member (m_* or direct)""" for struct_name, info in structs.items(): # Pattern: get(obj, STRUCT::FIELD(), ret.field) # Need to change ret.field to ret.m_field if struct has m_prefix if info['has_m_prefix']: # Pattern A: need to add m_ prefix for member in info['members']: # Match: ret.member) where member is the getter name # Need to convert getter name to member name (e.g., equipmentNumber -> m_equipmentNumber) getter_name = member[2:] if member.startswith('m_') else member pattern = rf'(get\(obj,\s*\w+::\w+\(\),\s*ret\.){getter_name}(\))' replacement = rf'\1{member}\2' content = re.sub(pattern, replacement, content) # Pattern B: direct members, no change needed for assignment # But we should verify the member names match return content # Fix toJson functions - convert to Qt6 single-line QJsonObject{{}} syntax def fix_toJson(content, structs): """Fix toJson to use Qt6-compatible QJsonObject{{}} syntax with correct member access""" for struct_name, info in structs.items(): # Find toJson function for this struct pattern = rf'(QJsonObject\s+{struct_name}::toJson\(\)\s*const\s*\{{\s*return\s*QJsonObject)(\{{[^}}]*\}})(\s*;)' def replace_toJson(m): prefix = m.group(1) init_list = m.group(2) suffix = m.group(3) # Parse the initializer list entries entries = re.findall(r'\{([^,]+),\s*([^}]+)\}', init_list) new_entries = [] for key_expr, value_expr in entries: key_expr = key_expr.strip() value_expr = value_expr.strip() # If struct has m_prefix, use getter methods if info['has_m_prefix']: # Convert member name to getter call if value_expr.startswith('m_'): getter = value_expr[2:] # Remove m_ prefix value_expr = f'{getter}()' # else: Pattern B uses direct members, no change new_entries.append(f'{{{key_expr}, {value_expr}}}') new_init = '{' + ', '.join(new_entries) + '}' return f'{prefix}{new_init}{suffix}' content = re.sub(pattern, replace_toJson, content) return content # Apply fixes cpp_content = fix_fromJson(cpp_content, structs) cpp_content = fix_toJson(cpp_content, structs) # Write back with open(cpp_file, 'w') as f: f.write(cpp_content) print(f"\nFixed {cpp_file}")