Добавлены бета-функции для считывания переменны по адресу +фиксы багов future: - в селекторе сделать две таблички для всех переменных и для выборанных - по кнопке переносить переменные из всех в выбранные - переменные из выбранных и добавлять в основную табличку - сделать отдельный класс для таблички - который будет принимать спиоск переменных для отображения
590 lines
25 KiB
Python
590 lines
25 KiB
Python
# build command
|
||
# pyinstaller --onefile --name DebugVarEdit --add-binary "build/libclang.dll;build" --distpath ./ --workpath ./build_temp --specpath ./build_temp setupVars_GUI.py
|
||
|
||
import sys
|
||
import os
|
||
import subprocess
|
||
import xml.etree.ElementTree as ET
|
||
from generateVars import type_map
|
||
from enum import IntEnum
|
||
import threading
|
||
from generateVars import run_generate
|
||
import setupVars
|
||
from VariableSelector import VariableSelectorDialog
|
||
from VariableTable import VariableTableWidget, rows
|
||
from scanVarGUI import ProcessOutputWindow
|
||
import scanVars
|
||
import myXML
|
||
import time
|
||
|
||
from PySide2.QtWidgets import (
|
||
QApplication, QWidget, QTableWidget, QTableWidgetItem,
|
||
QCheckBox, QComboBox, QLineEdit, QVBoxLayout, QHBoxLayout, QPushButton,
|
||
QCompleter, QAbstractItemView, QLabel, QMessageBox, QFileDialog, QTextEdit,
|
||
QDialog, QTreeWidget, QTreeWidgetItem, QSizePolicy, QHeaderView
|
||
)
|
||
from PySide2.QtGui import QTextCursor, QKeyEvent, QIcon, QFont
|
||
from PySide2.QtCore import Qt, QProcess, QObject, Signal, QSettings
|
||
|
||
|
||
var_edit_title = "Редактор переменных для отладки"
|
||
xml_path_title = "Путь к XML:"
|
||
proj_path_title = "Путь к проекту:"
|
||
makefile_path_title = "Пусть к makefile (относительно проекта)"
|
||
output_path_title = "Папка для debug_vars.c:"
|
||
scan_title = "Сканировать переменные"
|
||
build_title = "Сгенерировать файл"
|
||
add_vars_title = "Добавить переменные"
|
||
open_output_title = "Открыть файл"
|
||
|
||
# 3. UI: таблица с переменными
|
||
class VarEditor(QWidget):
|
||
def __init__(self):
|
||
super().__init__()
|
||
self.vars_list = []
|
||
self.structs = {}
|
||
self.typedef_map = {}
|
||
|
||
self.proj_path = None
|
||
self.xml_path = None
|
||
self.makefile_path = None
|
||
self.structs_path = None
|
||
self.output_path = None
|
||
self._updating = False # Флаг блокировки рекурсии
|
||
self._resizing = False # флаг блокировки повторного вызова
|
||
self.initUI()
|
||
|
||
def initUI(self):
|
||
self.setWindowTitle(var_edit_title)
|
||
|
||
base_path = scanVars.get_base_path()
|
||
icon_path = os.path.join(base_path, "icon.ico")
|
||
if os.path.exists(icon_path):
|
||
self.setWindowIcon(QIcon(icon_path))
|
||
|
||
# --- Поля ввода пути проекта и XML ---
|
||
|
||
# XML Output
|
||
xml_layout = QHBoxLayout()
|
||
xml_layout.addWidget(QLabel(xml_path_title))
|
||
self.xml_output_edit = QLineEdit()
|
||
self.xml_output_edit.returnPressed.connect(self.update)
|
||
self.xml_output_edit.textChanged.connect(self.__on_xml_path_changed)
|
||
xml_layout.addWidget(self.xml_output_edit)
|
||
btn_xml_browse = QPushButton("...")
|
||
btn_xml_browse.setFixedWidth(30)
|
||
xml_layout.addWidget(btn_xml_browse)
|
||
btn_xml_browse.clicked.connect(self.__browse_xml_output)
|
||
|
||
# Project Path
|
||
proj_layout = QHBoxLayout()
|
||
proj_layout.addWidget(QLabel(proj_path_title))
|
||
self.proj_path_edit = QLineEdit()
|
||
self.proj_path_edit.returnPressed.connect(self.update)
|
||
self.proj_path_edit.textChanged.connect(self.__on_proj_path_changed)
|
||
proj_layout.addWidget(self.proj_path_edit)
|
||
btn_proj_browse = QPushButton("...")
|
||
btn_proj_browse.setFixedWidth(30)
|
||
proj_layout.addWidget(btn_proj_browse)
|
||
btn_proj_browse.clicked.connect(self.__browse_proj_path)
|
||
|
||
# Makefile Path
|
||
makefile_layout = QHBoxLayout()
|
||
makefile_layout.addWidget(QLabel(makefile_path_title))
|
||
self.makefile_edit = QLineEdit()
|
||
self.makefile_edit.returnPressed.connect(self.update)
|
||
self.makefile_edit.textChanged.connect(self.__on_makefile_path_changed)
|
||
makefile_layout.addWidget(self.makefile_edit)
|
||
btn_makefile_browse = QPushButton("...")
|
||
btn_makefile_browse.setFixedWidth(30)
|
||
makefile_layout.addWidget(btn_makefile_browse)
|
||
btn_makefile_browse.clicked.connect(self.__browse_makefile)
|
||
|
||
|
||
|
||
# Source Output File/Directory
|
||
source_output_layout = QHBoxLayout()
|
||
source_output_layout.addWidget(QLabel(output_path_title))
|
||
self.source_output_edit = QLineEdit()
|
||
source_output_layout.addWidget(self.source_output_edit)
|
||
btn_source_output_browse = QPushButton("...")
|
||
btn_source_output_browse.setFixedWidth(30)
|
||
source_output_layout.addWidget(btn_source_output_browse)
|
||
btn_source_output_browse.clicked.connect(self.__browse_source_output)
|
||
|
||
|
||
self.btn_update_vars = QPushButton(scan_title)
|
||
self.btn_update_vars.clicked.connect(self.update_vars_data)
|
||
|
||
# Кнопка сохранения
|
||
btn_save = QPushButton(build_title)
|
||
btn_save.clicked.connect(self.save_build)
|
||
|
||
# Кнопка добавления переменных
|
||
self.btn_add_vars = QPushButton(add_vars_title)
|
||
self.btn_add_vars.clicked.connect(self.__open_variable_selector)
|
||
|
||
# Кнопка открыть output-файл с выбором программы
|
||
btn_open_output = QPushButton(open_output_title)
|
||
btn_open_output.clicked.connect(self.__open_output_file_with_program)
|
||
# Таблица
|
||
self.table = VariableTableWidget()
|
||
# Основной layout
|
||
layout = QVBoxLayout()
|
||
layout.addLayout(xml_layout)
|
||
layout.addLayout(proj_layout)
|
||
layout.addLayout(makefile_layout)
|
||
layout.addWidget(self.btn_update_vars)
|
||
layout.addWidget(self.table)
|
||
layout.addWidget(self.btn_add_vars)
|
||
layout.addLayout(source_output_layout)
|
||
layout.addWidget(btn_save)
|
||
layout.addWidget(btn_open_output)
|
||
|
||
self.setLayout(layout)
|
||
|
||
|
||
|
||
def get_xml_path(self):
|
||
xml_path = self.xml_output_edit.text().strip()
|
||
return xml_path
|
||
|
||
def get_proj_path(self):
|
||
proj_path = self.proj_path_edit.text().strip()
|
||
return proj_path
|
||
|
||
def get_makefile_path(self):
|
||
proj_path = self.get_proj_path()
|
||
rel_makefile_path = self.makefile_edit.text().strip()
|
||
if not rel_makefile_path:
|
||
return None
|
||
makefile_path = myXML.make_absolute_path(rel_makefile_path, proj_path)
|
||
return makefile_path
|
||
|
||
def get_struct_path(self):
|
||
proj_path = self.get_proj_path()
|
||
xml_path = self.get_xml_path()
|
||
root, tree = myXML.safe_parse_xml(xml_path)
|
||
if root is None:
|
||
return
|
||
# --- structs_path из атрибута ---
|
||
structs_path = root.attrib.get('structs_path', '').strip()
|
||
structs_path_full = myXML.make_absolute_path(structs_path, proj_path)
|
||
if structs_path_full and os.path.isfile(structs_path_full):
|
||
structs_path = structs_path_full
|
||
else:
|
||
structs_path = None
|
||
return structs_path
|
||
|
||
def get_output_path(self):
|
||
output_path = os.path.abspath(self.source_output_edit.text().strip())
|
||
return output_path
|
||
|
||
def update_all_paths(self):
|
||
self.proj_path = self.get_proj_path()
|
||
self.xml_path = self.get_xml_path()
|
||
self.makefile_path = self.get_makefile_path()
|
||
self.structs_path = self.get_struct_path()
|
||
self.output_path = self.get_output_path()
|
||
|
||
|
||
def update_vars_data(self):
|
||
self.update_all_paths()
|
||
|
||
if not self.proj_path or not self.xml_path:
|
||
QMessageBox.warning(self, "Ошибка", "Укажите пути проекта и XML.")
|
||
return
|
||
|
||
if not os.path.isfile(self.makefile_path):
|
||
QMessageBox.warning(self, "Ошибка", f"Makefile не найден:\n{self.makefile_path}")
|
||
return
|
||
|
||
|
||
# Создаём окно с кнопкой "Готово"
|
||
self.proc_win = ProcessOutputWindow(self.proj_path, self.makefile_path, self.xml_path,
|
||
on_done_callback=self.__after_scanvars_finished)
|
||
self.proc_win.start_scan()
|
||
|
||
|
||
|
||
def save_build(self):
|
||
vars_out = []
|
||
for row in range(self.table.rowCount()):
|
||
include_cb = self.table.cellWidget(row, rows.include)
|
||
if not include_cb.isChecked():
|
||
continue
|
||
name_edit = self.table.cellWidget(row, rows.name)
|
||
pt_type_combo = self.table.cellWidget(row, rows.pt_type)
|
||
iq_combo = self.table.cellWidget(row, rows.iq_type)
|
||
ret_combo = self.table.cellWidget(row, rows.ret_type)
|
||
short_name_edit = self.table.cellWidget(row, rows.short_name)
|
||
|
||
var_data = {
|
||
'name': name_edit.text(),
|
||
'type': 'pt_' + pt_type_combo.currentText(),
|
||
'iq_type': iq_combo.currentText(),
|
||
'return_type': ret_combo.currentText() if ret_combo.currentText() else 'int',
|
||
'short_name': short_name_edit.text(),
|
||
}
|
||
vars_out.append(var_data)
|
||
|
||
self.update_all_paths()
|
||
|
||
if not self.proj_path or not self.xml_path or not self.output_path:
|
||
QMessageBox.warning(self, "Ошибка", f"Заполните: {xml_path_title[:-1]}, {proj_path_title[:-1]}, {output_path_title[:-1]}.")
|
||
return
|
||
|
||
try:
|
||
run_generate(self.proj_path, self.xml_path, self.output_path)
|
||
QMessageBox.information(self, "Готово", "Файл debug_vars.c успешно сгенерирован.")
|
||
self.update()
|
||
except Exception as e:
|
||
QMessageBox.critical(self, "Ошибка при генерации", str(e))
|
||
|
||
|
||
def update(self):
|
||
if self._updating:
|
||
return # Уже в процессе обновления — выходим, чтобы избежать рекурсии
|
||
self._updating = True
|
||
|
||
self.update_all_paths()
|
||
try:
|
||
if self.xml_path and not os.path.isfile(self.xml_path):
|
||
return
|
||
|
||
try:
|
||
root, tree = myXML.safe_parse_xml(self.xml_path)
|
||
if root is None:
|
||
return
|
||
|
||
if not self.proj_path:
|
||
# Если в поле ничего нет, пробуем взять из XML
|
||
proj_path_from_xml = root.attrib.get('proj_path', '').strip()
|
||
if proj_path_from_xml and os.path.isdir(proj_path_from_xml):
|
||
self.proj_path = proj_path_from_xml
|
||
self.proj_path_edit.setText(proj_path_from_xml)
|
||
else:
|
||
QMessageBox.warning(
|
||
self,
|
||
"Внимание",
|
||
"Путь к проекту не найден или не существует.\n"
|
||
f"Пожалуйста, укажите его вручную в поле '{proj_path_title[:-1]}'."
|
||
)
|
||
else:
|
||
if not os.path.isdir(self.proj_path):
|
||
QMessageBox.warning(
|
||
self,
|
||
"Внимание",
|
||
f"Указанный путь к проекту не существует:\n{self.proj_path}\n"
|
||
"Пожалуйста, исправьте путь в поле '{proj_path_title[:-1]}'."
|
||
)
|
||
|
||
if not self.makefile_path and self.proj_path and os.path.isdir(self.proj_path):
|
||
makefile_path = root.attrib.get('makefile_path', '').strip()
|
||
makefile_path_full = myXML.make_absolute_path(makefile_path, self.proj_path)
|
||
if os.path.isfile(makefile_path_full):
|
||
# Обновляем edit-поле на относительный путь, абсолют сохраняем
|
||
self.makefile_path = makefile_path_full
|
||
self.makefile_edit.setText(makefile_path)
|
||
else:
|
||
self.makefile_path = None
|
||
self.makefile_edit.setText("")
|
||
|
||
|
||
# --- structs_path из атрибута ---
|
||
structs_path = root.attrib.get('structs_path', '').strip()
|
||
structs_path_full = myXML.make_absolute_path(structs_path, self.proj_path)
|
||
if structs_path_full and os.path.isfile(structs_path_full):
|
||
self.structs_path = structs_path_full
|
||
self.structs, self.typedef_map = setupVars.parse_structs(structs_path_full)
|
||
else:
|
||
self.structs_path = None
|
||
|
||
self.vars_list = setupVars.parse_vars(self.xml_path, self.typedef_map)
|
||
self.table.populate(self.vars_list, self.structs, self.write_to_xml)
|
||
except Exception as e:
|
||
QMessageBox.warning(self, "Ошибка", f"Ошибка при чтении XML:\n{e}")
|
||
|
||
|
||
finally:
|
||
self._updating = False # Снимаем блокировку при выходе из функции
|
||
|
||
def __browse_proj_path(self):
|
||
dir_path = QFileDialog.getExistingDirectory(self, "Выберите папку проекта")
|
||
if dir_path:
|
||
self.proj_path_edit.setText(dir_path)
|
||
self.proj_path = dir_path
|
||
|
||
# Сброс makefile, если proj_path изменился
|
||
if not os.path.isdir(dir_path):
|
||
self.makefile_path = None
|
||
self.makefile_edit.setText("")
|
||
else:
|
||
if self.makefile_path and os.path.isfile(self.makefile_path):
|
||
rel_path = myXML.make_relative_path(self.makefile_path, dir_path)
|
||
self.makefile_edit.setText(rel_path)
|
||
|
||
self.update()
|
||
|
||
self.update()
|
||
if self.makefile_path and self.proj_path:
|
||
path = myXML.make_relative_path(self.makefile_path, self.proj_path)
|
||
self.makefile_edit.setText(path)
|
||
self.makefile_path = path
|
||
|
||
def __browse_xml_output(self):
|
||
dialog = QFileDialog(self, "Выберите или создайте XML-файл")
|
||
dialog.setAcceptMode(QFileDialog.AcceptSave)
|
||
dialog.setNameFilter("XML files (*.xml);;All Files (*)")
|
||
dialog.setDefaultSuffix("xml")
|
||
dialog.setOption(QFileDialog.DontConfirmOverwrite, True) # ⚠️ Не спрашивать про перезапись
|
||
if dialog.exec_():
|
||
file_path = dialog.selectedFiles()[0]
|
||
if not file_path.endswith(".xml"):
|
||
file_path += ".xml"
|
||
self.xml_output_edit.setText(file_path)
|
||
self.xml_path = file_path
|
||
|
||
def keyPressEvent(self, event: QKeyEvent):
|
||
if event.key() == Qt.Key_Delete:
|
||
self.delete_selected_rows()
|
||
else:
|
||
super().keyPressEvent(event)
|
||
|
||
def __browse_makefile(self):
|
||
file_path, _ = QFileDialog.getOpenFileName(
|
||
self, "Выберите Makefile", filter="Makefile (makefile);;All Files (*)"
|
||
)
|
||
if file_path and self.proj_path:
|
||
path = myXML.make_relative_path(file_path, self.proj_path)
|
||
else:
|
||
path = file_path
|
||
self.makefile_edit.setText(path)
|
||
self.makefile_path = path
|
||
|
||
def __browse_source_output(self):
|
||
dir_path = QFileDialog.getExistingDirectory(self, "Выберите папку для debug_vars.c")
|
||
if dir_path:
|
||
self.source_output_edit.setText(dir_path)
|
||
self.output_path = dir_path
|
||
else:
|
||
self.output_path = ''
|
||
|
||
|
||
def __on_xml_path_changed(self, _):
|
||
self.xml_path = self.get_xml_path()
|
||
self.update()
|
||
|
||
def __on_proj_path_changed(self, _):
|
||
self.proj_path = self.get_proj_path()
|
||
|
||
if not os.path.isdir(self.proj_path):
|
||
self.makefile_path = None
|
||
self.makefile_edit.setText("")
|
||
return # Преждевременно выходим, если проект не существует
|
||
|
||
# Обновим путь к makefile, если он уже задан и абсолютен
|
||
if self.makefile_path and os.path.isfile(self.makefile_path):
|
||
rel_path = myXML.make_relative_path(self.makefile_path, self.proj_path)
|
||
self.makefile_edit.setText(rel_path)
|
||
|
||
self.update()
|
||
|
||
def __on_makefile_path_changed(self, _):
|
||
self.makefile_path = self.get_makefile_path()
|
||
if self.makefile_path and self.proj_path:
|
||
path = myXML.make_relative_path(self.makefile_path, self.proj_path)
|
||
self.makefile_edit.setText(path)
|
||
self.update()
|
||
|
||
|
||
def __after_scanvars_finished(self):
|
||
self.update_all_paths()
|
||
if not os.path.isfile(self.xml_path):
|
||
QMessageBox.critical(self, "Ошибка", f"Файл не найден: {self.xml_path}")
|
||
return
|
||
|
||
try:
|
||
self.makefile_path = None
|
||
self.structs_path = None
|
||
self.proj_path = None
|
||
self.update()
|
||
|
||
|
||
except Exception as e:
|
||
QMessageBox.critical(self, "Ошибка", f"Не удалось загрузить переменные:\n{e}")
|
||
|
||
def delete_selected_rows(self):
|
||
selected_rows = sorted(set(index.row() for index in self.table.selectedIndexes()), reverse=True)
|
||
if not selected_rows:
|
||
return
|
||
|
||
for row in selected_rows:
|
||
if 0 <= row < len(self.vars_list):
|
||
# Меняем флаг show_var для переменной с этим индексом
|
||
self.vars_list[row]['show_var'] = 'false'
|
||
|
||
self.table.populate(self.vars_list, self.structs, self.write_to_xml)
|
||
self.write_to_xml()
|
||
|
||
|
||
def __open_variable_selector(self):
|
||
if not self.vars_list:
|
||
QMessageBox.warning(self, "Нет переменных", f"Сначала загрузите переменные ({scan_title}).")
|
||
return
|
||
|
||
dlg = VariableSelectorDialog(self.table, self.vars_list, self.structs, self.typedef_map, self.xml_path, self)
|
||
if dlg.exec_():
|
||
self.write_to_xml()
|
||
self.update()
|
||
|
||
|
||
def write_to_xml(self, dummy=None):
|
||
self.update_all_paths()
|
||
|
||
if not self.xml_path or not os.path.isfile(self.xml_path):
|
||
print("XML файл не найден или путь пустой")
|
||
return
|
||
if not self.proj_path or not os.path.isdir(self.proj_path):
|
||
print("Project path не найден или путь пустой")
|
||
return
|
||
if not self.makefile_path or not os.path.isfile(self.makefile_path):
|
||
print("makefile файл не найден или путь пустой")
|
||
return
|
||
if os.path.abspath(self.makefile_path) == os.path.abspath(self.proj_path):
|
||
print("makefile_path совпадает с proj_path — игнор")
|
||
return
|
||
|
||
try:
|
||
root, tree = myXML.safe_parse_xml(self.xml_path)
|
||
if root is None:
|
||
return
|
||
|
||
|
||
root.set("proj_path", self.proj_path.replace("\\", "/"))
|
||
|
||
if self.makefile_path and os.path.isfile(self.makefile_path):
|
||
rel_makefile = myXML.make_relative_path(self.makefile_path, self.proj_path)
|
||
root.set("makefile_path", rel_makefile)
|
||
# Если результат — абсолютный путь, не записываем
|
||
if not os.path.isabs(rel_makefile):
|
||
root.set("makefile_path", rel_makefile)
|
||
|
||
if self.structs_path and os.path.isfile(self.structs_path):
|
||
rel_struct = myXML.make_relative_path(self.structs_path, self.proj_path)
|
||
root.set("structs_path", rel_struct)
|
||
if not os.path.isabs(rel_struct):
|
||
root.set("structs_path", rel_struct)
|
||
|
||
|
||
vars_elem = root.find('variables')
|
||
if vars_elem is None:
|
||
vars_elem = ET.SubElement(root, 'variables')
|
||
|
||
original_info = {}
|
||
for var_elem in vars_elem.findall('var'):
|
||
name = var_elem.attrib.get('name')
|
||
if name:
|
||
original_info[name] = {
|
||
'file': var_elem.findtext('file', ''),
|
||
'extern': var_elem.findtext('extern', ''),
|
||
'static': var_elem.findtext('static', '')
|
||
}
|
||
|
||
# Читаем переменные из таблицы (активные/изменённые)
|
||
table_vars = {v['name']: v for v in self.table.read_data()}
|
||
# Все переменные (в том числе новые, которых нет в таблице)
|
||
all_vars_by_name = {v['name']: v for v in self.vars_list}
|
||
|
||
# Объединённый список переменных для записи
|
||
all_names = list(all_vars_by_name.keys())
|
||
for name in all_names:
|
||
v = all_vars_by_name[name]
|
||
v_table = table_vars.get(name)
|
||
var_elem = None
|
||
|
||
# Ищем уже существующий <var> в XML
|
||
for ve in vars_elem.findall('var'):
|
||
if ve.attrib.get('name') == name:
|
||
var_elem = ve
|
||
break
|
||
if var_elem is None:
|
||
var_elem = ET.SubElement(vars_elem, 'var', {'name': name})
|
||
|
||
def set_sub_elem_text(parent, tag, text):
|
||
el = parent.find(tag)
|
||
if el is None:
|
||
el = ET.SubElement(parent, tag)
|
||
el.text = str(text)
|
||
|
||
show_var_val = str(v.get('show_var', 'false')).lower()
|
||
enable_val = str(v_table['enable'] if v_table and 'enable' in v_table else v.get('enable', 'false')).lower()
|
||
|
||
set_sub_elem_text(var_elem, 'show_var', show_var_val)
|
||
set_sub_elem_text(var_elem, 'enable', enable_val)
|
||
|
||
# Тут подтягиваем из таблицы, если есть, иначе из v
|
||
shortname_val = v_table['shortname'] if v_table and 'shortname' in v_table else v.get('shortname', '')
|
||
pt_type_val = v_table['pt_type'] if v_table and 'pt_type' in v_table else v.get('pt_type', '')
|
||
iq_type_val = v_table['iq_type'] if v_table and 'iq_type' in v_table else v.get('iq_type', '')
|
||
ret_type_val = v_table['return_type'] if v_table and 'return_type' in v_table else v.get('return_type', '')
|
||
|
||
set_sub_elem_text(var_elem, 'shortname', shortname_val)
|
||
set_sub_elem_text(var_elem, 'pt_type', pt_type_val)
|
||
set_sub_elem_text(var_elem, 'iq_type', iq_type_val)
|
||
set_sub_elem_text(var_elem, 'return_type', ret_type_val)
|
||
set_sub_elem_text(var_elem, 'type', v.get('type', ''))
|
||
|
||
# file/extern/static: из original_info, либо из v
|
||
file_val = v.get('file') or original_info.get(name, {}).get('file', '')
|
||
extern_val = v.get('extern') or original_info.get(name, {}).get('extern', '')
|
||
static_val = v.get('static') or original_info.get(name, {}).get('static', '')
|
||
|
||
set_sub_elem_text(var_elem, 'file', file_val)
|
||
set_sub_elem_text(var_elem, 'extern', extern_val)
|
||
set_sub_elem_text(var_elem, 'static', static_val)
|
||
|
||
# Преобразуем дерево в строку
|
||
self.table.check()
|
||
myXML.fwrite(root, self.xml_path)
|
||
|
||
except Exception as e:
|
||
print(f"Ошибка при сохранении XML: {e}")
|
||
|
||
def __open_output_file_with_program(self):
|
||
output_path = self.get_output_path()
|
||
if not output_path:
|
||
QMessageBox.warning(self,
|
||
"Ошибка",
|
||
"Путь к debug_var.c не задан."
|
||
f"Пожалуйста, укажите его в поле '{output_path_title[:-1]}'.")
|
||
return
|
||
|
||
output_file = os.path.join(output_path, "debug_vars.c")
|
||
if not os.path.isfile(output_file):
|
||
QMessageBox.warning(self, "Ошибка", f"Файл не найден:\n{output_file}")
|
||
return
|
||
|
||
try:
|
||
# Открыть стандартное окно Windows "Открыть с помощью..."
|
||
subprocess.run([
|
||
"rundll32.exe",
|
||
"shell32.dll,OpenAs_RunDLL",
|
||
output_file
|
||
], shell=False)
|
||
except Exception as e:
|
||
QMessageBox.critical(self, "Ошибка", f"Не удалось открыть диалог 'Открыть с помощью':\n{e}")
|
||
|
||
|
||
|
||
|
||
if __name__ == "__main__":
|
||
app = QApplication(sys.argv)
|
||
|
||
editor = VarEditor()
|
||
editor.resize(900, 600)
|
||
editor.show()
|
||
|
||
sys.exit(app.exec_())
|
||
|