debugVarTool/Src/VariableSelector.py

356 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import re
import xml.etree.ElementTree as ET
from PySide2.QtWidgets import (
QDialog, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QPushButton,
QLineEdit, QLabel, QHeaderView, QCompleter, QCheckBox, QHBoxLayout, QSizePolicy
)
from PySide2.QtGui import QKeySequence, QKeyEvent
from PySide2.QtCore import Qt, QStringListModel, QSettings
import VariableTable
import setupVars
import myXML
import time
import selectTable
array_re = re.compile(r'^(\w+)\[(\d+)\]$')
class VariableSelectorDialog(QDialog):
def __init__(self, table, all_vars, structs, typedefs, xml_path=None, parent=None):
super().__init__(parent)
self.setWindowTitle("Выбор переменных")
self.setAttribute(Qt.WA_DeleteOnClose)
self.resize(1200, 500)
self.selected_names = []
self._bckspc_pressed = False # флаг подавления добавления разделителя
self.table = table
self.all_vars = all_vars
self.structs = structs
self.typedefs = typedefs
self.expanded_vars = []
self.var_map = {v['name']: v for v in all_vars}
self.node_index = {}
self.xml_path = xml_path # сохраняем путь к xml
self.manual_completion_active = False
# --- Добавляем чекбокс для автодополнения ---
self.autocomplete_checkbox = QCheckBox("Включить автодополнение")
self.autocomplete_checkbox.setChecked(True)
# Инициализируем QSettings с именем организации и приложения
self.settings = QSettings("SET", "DebugVarEdit_VarsSelector")
# Восстанавливаем сохранённое состояние чекбокса, если есть
checked = self.settings.value("autocomplete_enabled", True, type=bool)
self.autocomplete_checkbox.setChecked(checked)
# При изменении состояния чекбокса сохраняем его
self.autocomplete_checkbox.stateChanged.connect(self.save_checkbox_state)
# Кнопки между таблицами
self.btn_right = QPushButton(">")
self.btn_right.clicked.connect(self.on_move_right)
self.btn_left = QPushButton("<")
self.btn_left.clicked.connect(self.on_move_left)
# Создаем кнопки, они остаются в диалоге
self.btn_add = QPushButton("Добавить выбранные")
self.btn_delete = QPushButton("Удалить выбранные")
# Создаем экземпляр вашего готового виджета
self.vars_widget = selectTable.VariableSelectWidget(self)
self.selected_vars_widget = selectTable.VariableSelectWidget(self)
# --- Лэйауты ---
main_layout = QVBoxLayout(self) # главный вертикальный layout окна
tables_layout = QHBoxLayout() # горизонтальный layout с таблицами и кнопками
# Левая таблица
self.vars_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
tables_layout.addWidget(self.vars_widget)
# Кнопки ">" и "<" между таблицами
middle_buttons_layout = QVBoxLayout()
middle_buttons_layout.addStretch()
middle_buttons_layout.addWidget(self.btn_right)
middle_buttons_layout.addWidget(self.btn_left)
middle_buttons_layout.addStretch()
tables_layout.addLayout(middle_buttons_layout)
# Правая таблица
self.selected_vars_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
tables_layout.addWidget(self.selected_vars_widget)
# Добавляем горизонтальный layout с таблицами в главный вертикальный
main_layout.addLayout(tables_layout)
# Кнопки "Добавить выбранные" и "Удалить выбранные" под таблицами
buttons_layout = QVBoxLayout()
buttons_layout.addWidget(self.btn_add)
buttons_layout.addWidget(self.btn_delete)
main_layout.addLayout(buttons_layout)
# Важно, если окно — QDialog или QWidget, установи layout
self.setLayout(main_layout)
# Соединяем сигналы кнопок с методами диалога
self.btn_add.clicked.connect(self.on_add_clicked)
self.btn_delete.clicked.connect(self.on_delete_clicked)
# Соединяем чекбокс с методом виджета
self.autocomplete_checkbox.stateChanged.connect(self.vars_widget.set_autocomplete)
# Устанавливаем начальное состояние автодополнения в виджете
self.vars_widget.set_autocomplete(self.autocomplete_checkbox.isChecked())
self.selected_vars_widget.set_autocomplete(self.autocomplete_checkbox.isChecked())
# --- Код в конце __init__ ---
self.expanded_vars = setupVars.expand_vars(self.all_vars, self.structs, self.typedefs)
self.update_vars_widget()
def on_move_right(self):
# Устанавливаем show_var=True для всех выбранных переменных из ЛЕВОЙ таблицы
selected = self.vars_widget._get_internal_selected_var_names()
if not selected:
return
def mark_selected_show_var(data):
for var in data:
if var['name'] in selected:
var['show_var'] = 'true'
if 'children' in var:
mark_selected_show_var(var['children'])
mark_selected_show_var(self.expanded_vars)
self.update_vars_widget()
def on_move_left(self):
# Сбрасываем show_var=False для всех выбранных переменных из ПРАВОЙ таблицы
selected = self.selected_vars_widget._get_internal_selected_var_names()
if not selected:
return
def mark_selected_hide_var(data):
for var in data:
if var['name'] in selected:
var['show_var'] = 'false'
if 'children' in var:
mark_selected_hide_var(var['children'])
mark_selected_hide_var(self.expanded_vars)
self.update_vars_widget()
def update_vars_widget(self):
self.selected_vars, self.unselected_vars = setupVars.split_vars_by_show_flag(self.expanded_vars)
self.vars_widget.set_data(self.unselected_vars)
self.vars_widget.filter_tree()
self.selected_vars_widget.set_data(self.selected_vars)
self.selected_vars_widget.filter_tree()
def on_add_clicked(self):
# Получаем все переменные из правой таблицы (selected_vars_widget)
var_names = self.selected_vars_widget.get_all_var_names()
all_items = self.selected_vars_widget.get_all_items()
if not all_items:
return
def add_to_var_map_recursively(item):
name = item.text(0)
type_str = item.text(1)
if name in self.var_map:
var = self.var_map[name]
var['show_var'] = 'true'
var['enable'] = 'true'
else:
file_val = item.data(0, Qt.UserRole + 1)
extern_val = item.data(0, Qt.UserRole + 2)
static_val = item.data(0, Qt.UserRole + 3)
new_var = {
'name': name, 'type': type_str, 'show_var': 'true',
'enable': 'true', 'shortname': name, 'pt_type': '', 'iq_type': '',
'return_type': 'iq_none', 'file': file_val,
'extern': str(extern_val).lower() if extern_val else 'false',
'static': str(static_val).lower() if static_val else 'false',
}
self.all_vars.append(new_var)
self.var_map[name] = new_var
for item in all_items:
add_to_var_map_recursively(item)
self.accept()
def on_delete_clicked(self):
# Получаем все элементы (QTreeWidgetItem) из правой таблицы
all_items = self.selected_vars_widget.get_all_items()
if not all_items:
return
affected_names = []
def disable_var_recursively(item):
name = item.text(0)
if name in self.var_map:
self.var_map[name]['show_var'] = 'false'
self.var_map[name]['enable'] = 'false'
affected_names.append(name)
# Рекурсивно отключаем детей
for i in range(item.childCount()):
child = item.child(i)
disable_var_recursively(child)
for item in all_items:
disable_var_recursively(item)
# Обновляем XML и таблицу
self.update_xml_vars(affected_names, 'false', 'false')
self.update_vars_widget()
def update_xml_vars(self, names, show, enable):
"""Обновляет флаги show_var и enable в XML файле, только если у переменной нет вложенных структур."""
if not self.xml_path:
return
root, tree = myXML.safe_parse_xml(self.xml_path)
if root is None:
return
vars_section = root.find('variables')
if vars_section is None:
return
for var_elem in vars_section.findall('var'):
if var_elem.attrib.get('name') in names:
# Проверяем наличие вложенных структур или объединений
has_nested_structs = any(
var_elem.find(tag) is not None for tag in ('struct', 'union')
)
if not has_nested_structs:
def set_text(tag, value):
el = var_elem.find(tag)
if el is None:
el = ET.SubElement(var_elem, tag)
el.text = value
set_text('show_var', show)
set_text('enable', enable)
myXML.fwrite(root, self.xml_path)
def save_checkbox_state(self):
self.settings.setValue("autocomplete_enabled", self.autocomplete_checkbox.isChecked())
def keyPressEvent(self, event):
if event.key() == Qt.Key_Delete:
self.delete_selected_vars()
else:
super().keyPressEvent(event)
def delete_selected_vars(self):
selected_names = self._get_selected_var_names()
if not selected_names:
print("nothing selected")
return
# Обновляем var_map и all_vars
for name in selected_names:
if name in self.var_map:
self.var_map[name]['show_var'] = 'false'
self.var_map[name]['enable'] = 'false'
for v in self.all_vars:
if v['name'] == name:
v['show_var'] = 'false'
v['enable'] = 'false'
break
# Проверка пути к XML
if not hasattr(self, 'xml_path') or not self.xml_path:
from PySide2.QtWidgets import QMessageBox
QMessageBox.warning(self, "Ошибка", "Путь к XML не задан, невозможно обновить переменные.")
return
root, tree = myXML.safe_parse_xml(self.xml_path)
if root is None:
return
vars_section = root.find('variables')
if vars_section is None:
return
for var_elem in vars_section.findall('var'):
name = var_elem.attrib.get('name')
if name in selected_names:
def set_text(tag, value):
el = var_elem.find(tag)
if el is None:
el = ET.SubElement(var_elem, tag)
el.text = value
set_text('show_var', 'false')
set_text('enable', 'false')
myXML.fwrite(root, self.xml_path)
self.table.populate(self.all_vars, self.structs, None)
# Проверка пути к XML
if not hasattr(self, 'xml_path') or not self.xml_path:
from PySide2.QtWidgets import QMessageBox
QMessageBox.warning(self, "Ошибка", "Путь к XML не задан, невозможно удалить переменные.")
return
import xml.etree.ElementTree as ET
root, tree = myXML.safe_parse_xml(self.xml_path)
if root is None:
return
vars_section = root.find('variables')
if vars_section is None:
return
removed_any = False
for var_elem in list(vars_section.findall('var')):
name = var_elem.attrib.get('name')
if name in selected_names:
vars_section.remove(var_elem)
removed_any = True
self.var_map.pop(name, None)
# Удаляем из all_vars (глобально)
self.all_vars[:] = [v for v in self.all_vars if v['name'] not in selected_names]
# Удаляем из expanded_vars (тоже глобально)
def filter_out_selected(vars_list):
filtered = []
for v in vars_list:
if v['name'] not in selected_names:
# Рекурсивно фильтруем детей, если есть
if 'children' in v:
v = v.copy()
v['children'] = filter_out_selected(v['children'])
filtered.append(v)
return filtered
self.expanded_vars[:] = filter_out_selected(self.expanded_vars)
if removed_any:
myXML.fwrite(root, self.xml_path)
self.update_vars_widget()
def _get_selected_var_names(self):
focused = self.focusWidget()
if focused and focused is self.vars_widget.tree:
return self.vars_widget.get_selected_var_names()
elif focused and focused is self.selected_vars_widget.tree:
return self.selected_vars_widget.get_selected_var_names()
else:
return []
def save_checkbox_state(self):
self.settings.setValue("autocomplete_enabled", self.autocomplete_checkbox.isChecked())