diff --git a/Src/VariableSelector.py b/Src/VariableSelector.py index 6a38630..fc0d55e 100644 --- a/Src/VariableSelector.py +++ b/Src/VariableSelector.py @@ -2,7 +2,7 @@ import re import xml.etree.ElementTree as ET from PySide2.QtWidgets import ( QDialog, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QPushButton, - QLineEdit, QLabel, QHeaderView, QCompleter, QCheckBox, QHBoxLayout + QLineEdit, QLabel, QHeaderView, QCompleter, QCheckBox, QHBoxLayout, QSizePolicy ) from PySide2.QtGui import QKeySequence, QKeyEvent from PySide2.QtCore import Qt, QStringListModel, QSettings @@ -20,7 +20,7 @@ class VariableSelectorDialog(QDialog): super().__init__(parent) self.setWindowTitle("Выбор переменных") self.setAttribute(Qt.WA_DeleteOnClose) - self.resize(600, 500) + self.resize(1200, 500) self.selected_names = [] self._bckspc_pressed = False # флаг подавления добавления разделителя self.table = table @@ -45,27 +45,55 @@ class VariableSelectorDialog(QDialog): # При изменении состояния чекбокса сохраняем его 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) - # Собираем новую, более простую компоновку - search_layout = QHBoxLayout() - search_layout.addWidget(QLabel("Поиск:")) - search_layout.addStretch() - search_layout.addWidget(self.autocomplete_checkbox) - layout = QVBoxLayout(self) - layout.addLayout(search_layout) - layout.addWidget(self.vars_widget) # Добавляем ваш виджет целиком + # --- Лэйауты --- + 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) + - button_layout = QHBoxLayout() - button_layout.addWidget(self.btn_add) - button_layout.addWidget(self.btn_delete) - layout.addLayout(button_layout) # Соединяем сигналы кнопок с методами диалога self.btn_add.clicked.connect(self.on_add_clicked) @@ -75,19 +103,60 @@ class VariableSelectorDialog(QDialog): 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.selected_vars = setupVars.filter_selected_vars(self.expanded_vars) # Передаем данные в виджет self.vars_widget.set_data(self.expanded_vars) + self.selected_vars_widget.set_data(self.selected_vars) - def on_add_clicked(self): - # 5. Получаем имена из виджета - selected_items = self.vars_widget.get_selected_items() - if not selected_items: + def on_move_right(self): + # Устанавливаем show_var=True для всех выбранных переменных из ЛЕВОЙ таблицы + selected = self.vars_widget.get_selected_var_names() + if not selected: return - for item in selected_items: + 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_selected_vars_widget() + + def on_move_left(self): + # Сбрасываем show_var=False для всех выбранных переменных из ПРАВОЙ таблицы + selected = self.selected_vars_widget.get_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_selected_vars_widget() + + def update_selected_vars_widget(self): + self.selected_vars = setupVars.filter_selected_vars(self.expanded_vars) + self.selected_vars_widget.set_data(self.selected_vars) + + + + def on_add_clicked(self): + # Получаем все переменные из правой таблицы (selected_vars_widget) + all_items = self.selected_vars_widget.get_all_items() + if not all_items: + return + + for item in all_items: name = item.text(0) type_str = item.text(1) @@ -109,26 +178,24 @@ class VariableSelectorDialog(QDialog): self.all_vars.append(new_var) self.var_map[name] = new_var - self.accept() # Используем accept() вместо done(QDialog.Accepted) + self.accept() + def on_delete_clicked(self): - # 5. Получаем имена из виджета - selected_names = self.vars_widget.get_selected_var_names() - if not selected_names: - print("nothing selected") + # Получаем все имена переменных из правой таблицы + all_names = self.selected_vars_widget.get_all_var_names() + if not all_names: return - # Обновляем var_map и all_vars - for name in selected_names: + for name in all_names: if name in self.var_map: self.var_map[name]['show_var'] = 'false' self.var_map[name]['enable'] = 'false' - self.update_xml_vars(selected_names, 'false', 'false') - self.accept() + self.update_xml_vars(all_names, 'false', 'false') + self.update_selected_vars_widget() - def update_xml_vars(self, names, show, enable): """Обновляет флаги show_var и enable в XML файле.""" if not self.xml_path: @@ -152,8 +219,6 @@ class VariableSelectorDialog(QDialog): 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() diff --git a/Src/selectTable.py b/Src/selectTable.py index 07c88fb..9a066c6 100644 --- a/Src/selectTable.py +++ b/Src/selectTable.py @@ -10,20 +10,26 @@ from PySide2.QtCore import Qt, QStringListModel def split_path(path): """ Разбивает путь на компоненты: - - 'foo[2].bar[1]->baz' → ['foo', [2]', 'bar', '[1]' 'baz'] + - 'foo[2].bar[1]->baz' → ['foo', '[2]', 'bar', '[1]', 'baz'] + Если видит '-' в конце строки (без '>' после) — обрезает этот '-' """ tokens = [] token = '' i = 0 - while i < len(path): + length = len(path) + while i < length: c = path[i] # Разделители: '->' и '.' - if c == '-' and path[i:i+2] == '->': + if c == '-' and i + 1 < length and path[i:i+2] == '->': if token: tokens.append(token) token = '' i += 2 continue + elif c == '-' and i == length - 1: + # '-' на конце строки без '>' после — просто пропускаем его + i += 1 + continue elif c == '.': if token: tokens.append(token) @@ -31,16 +37,14 @@ def split_path(path): i += 1 continue elif c == '[': - # Заканчиваем текущий токен, если есть if token: tokens.append(token) token = '' - # Собираем индекс [N] idx = '' - while i < len(path) and path[i] != ']': + while i < length and path[i] != ']': idx += path[i] i += 1 - if i < len(path) and path[i] == ']': + if i < length and path[i] == ']': idx += ']' i += 1 tokens.append(idx) @@ -52,10 +56,6 @@ def split_path(path): tokens.append(token) return tokens -def hide_all(item): - item.setHidden(True) - for i in range(item.childCount()): - hide_all(item.child(i)) # Функция парсит имя с индексами в (базовое_имя, список_индексов) def parse_name_with_indices(name): @@ -89,20 +89,18 @@ def show_matching_path(item, path_parts, level=0): node_name = item.text(0).lower() node_parts = split_path(node_name) + if 'project' in node_name: + a = 1 + if level >= len(path_parts): # Путь полностью пройден — показываем только этот узел (без раскрытия всех детей) item.setHidden(False) - # Показываем детей, которые тоже соответствуют, но на этом уровне их нет, - # поэтому детей не раскрываем - for i in range(item.childCount()): - hide_all(item.child(i)) item.setExpanded(False) return True if level >= len(node_parts): # Уровень поиска больше длины пути узла — скрываем - item.setHidden(True) - return False + item.setHidden(False) search_part = path_parts[level] node_part = node_parts[level] @@ -115,16 +113,18 @@ def show_matching_path(item, path_parts, level=0): child = item.child(i) if show_matching_path(child, path_parts, level + 1): matched_any = True - else: - hide_all(child) item.setExpanded(matched_any) return matched_any or item.childCount() == 0 elif node_part.startswith(search_part): # Неполное совпадение — показываем только этот узел, детей скрываем, не раскрываем item.setHidden(False) - for i in range(item.childCount()): - hide_all(item.child(i)) + item.setExpanded(False) + return True + + elif search_part in node_part and (level == len(path_parts)-1): + # Неполное совпадение — показываем только этот узел, детей скрываем, не раскрываем + item.setHidden(False) item.setExpanded(False) return True @@ -135,15 +135,6 @@ def show_matching_path(item, path_parts, level=0): - - - - - - - - - class VariableSelectWidget(QWidget): def __init__(self, parent=None): super().__init__(parent) @@ -204,17 +195,6 @@ class VariableSelectWidget(QWidget): """Возвращает имена выделенных переменных.""" return [item.text(0) for item in self.tree.selectedItems() if item.text(0)] - def expand_to_level(self, item, level, current_level=0): - """ - Рекурсивно раскрывает узлы до заданного уровня. - """ - if current_level < level: - item.setExpanded(True) - else: - item.setExpanded(False) - - for i in range(item.childCount()): - self.expand_to_level(item.child(i), level, current_level + 1) def populate_tree(self, vars_list=None): if vars_list is None: @@ -241,6 +221,15 @@ class VariableSelectWidget(QWidget): return fullname + def get_selected_vars(self): + selected = self.tree.selectedItems() + result = [] + for item in selected: + var = item.data(0, Qt.UserRole) + if var: + result.append(var) + return result + def add_tree_item_recursively(self, parent, var): """ Рекурсивно добавляет переменную и её дочерние поля в дерево. @@ -289,12 +278,9 @@ class VariableSelectWidget(QWidget): item.setHidden(False) # Не сбрасываем expanded, чтобы можно было раскрывать вручную else: - hide_all(item) item.setHidden(True) else: for i in range(self.tree.topLevelItemCount()): - item = self.tree.topLevelItem(i) - hide_all(item) item = self.tree.topLevelItem(i) show_matching_path(item, path_parts, 0) @@ -530,4 +516,10 @@ class VariableSelectWidget(QWidget): def set_tool(self, item, text): item.setToolTip(0, text) - item.setToolTip(1, text) \ No newline at end of file + item.setToolTip(1, text) + + def get_all_items(self): + return [self.tree.topLevelItem(i) for i in range(self.tree.topLevelItemCount())] + + def get_all_var_names(self): + return [self.tree.topLevelItem(i).text(0) for i in range(self.tree.topLevelItemCount())] \ No newline at end of file diff --git a/Src/setupVars.py b/Src/setupVars.py index 560ed86..95b4451 100644 --- a/Src/setupVars.py +++ b/Src/setupVars.py @@ -405,3 +405,19 @@ def expand_vars(vars_list, structs, typedefs): return expanded +def filter_selected_vars(expanded_vars): + selected_vars = [] + + def recurse(vars_list): + for var in vars_list: + show_var = var.get('show_var', 'false').lower() + if show_var == 'true': + selected_vars.append(var) + + # Рекурсивно обходим детей, если есть + children = var.get('children') + if children: + recurse(children) + + recurse(expanded_vars) + return selected_vars diff --git a/vars.xml b/vars.xml index 2f341af..9d10d9c 100644 --- a/vars.xml +++ b/vars.xml @@ -1,5 +1,5 @@ - + true @@ -3746,7 +3746,7 @@ false - true + false true tk2_ackcur pt_uint16 @@ -3758,7 +3758,7 @@ false - true + false true tk1_adr pt_uint16 @@ -3769,6 +3769,198 @@ false false + + false + true + ADC_sf[1][0] + pt_int16 + t_iq_none + t_iq_none + int + Src/main/adc_tools.c + false + false + + + false + true + ADC_sf[1][1] + pt_int16 + t_iq_none + t_iq_none + int + Src/main/adc_tools.c + false + false + + + false + true + ADC_sf[1][2] + pt_int16 + t_iq_none + t_iq_none + int + Src/main/adc_tools.c + false + false + + + false + true + ADC_sf[1][3] + pt_int16 + t_iq_none + t_iq_none + int + Src/main/adc_tools.c + false + false + + + false + true + ADC_sf[1][4] + pt_int16 + t_iq_none + t_iq_none + int + Src/main/adc_tools.c + false + false + + + false + true + ADC_sf[1][5] + pt_int16 + t_iq_none + t_iq_none + int + Src/main/adc_tools.c + false + false + + + false + true + ADC_sf[1][6] + pt_int16 + t_iq_none + t_iq_none + int + Src/main/adc_tools.c + false + false + + + false + true + ADC_sf[1][7] + pt_int16 + t_iq_none + t_iq_none + int + Src/main/adc_tools.c + false + false + + + false + true + ADC_sf[1][8] + pt_int16 + t_iq_none + t_iq_none + int + Src/main/adc_tools.c + false + false + + + false + true + ADC_sf[1][9] + pt_int16 + t_iq_none + t_iq_none + int + Src/main/adc_tools.c + false + false + + + false + true + ADC_sf[1][10] + pt_int16 + t_iq_none + t_iq_none + int + Src/main/adc_tools.c + false + false + + + false + true + ADC_sf[1][11] + pt_int16 + t_iq_none + t_iq_none + int + Src/main/adc_tools.c + false + false + + + false + true + ADC_sf[1][12] + pt_int16 + t_iq_none + t_iq_none + int + Src/main/adc_tools.c + false + false + + + false + true + ADC_sf[1][13] + pt_int16 + t_iq_none + t_iq_none + int + Src/main/adc_tools.c + false + false + + + false + true + ADC_sf[1][14] + pt_int16 + t_iq_none + t_iq_none + int + Src/main/adc_tools.c + false + false + + + false + true + ADC_sf[1][15] + pt_int16 + t_iq_none + t_iq_none + int + Src/main/adc_tools.c + false + false + Src/main/vector.h