mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-05-31 20:38:27 +08:00
[supervision] Adds documentation tab. (#2972)
* [supervision] Adds documentation tab. * [generator] add a target option to dump modules by target with load type * [supervision] doc: handle modules type. * [supervision] modules doc: add filter. * [supervision] Use internet doc by default. * [supervision] Move the header out of the configuration tab. * [supervision] Add target label. * [supervision] Gracefully handle Ctrl-C. * [supervision] Add new session to combobox. * Update sw/supervision/python/doc_panel.py --------- Co-authored-by: Gautier Hattenberger <gautier.hattenberger@enac.fr>
This commit is contained in:
@@ -1,19 +1,25 @@
|
|||||||
# Copyright (C) 2008-2022 The Paparazzi Team
|
# Copyright (C) 2008-2022 The Paparazzi Team
|
||||||
# released under GNU GPLv2 or later. See COPYING file.
|
# released under GNU GPLv2 or later. See COPYING file.
|
||||||
all:
|
|
||||||
mkdir -p generated
|
|
||||||
pyuic5 ui/conf_header.ui -o generated/ui_conf_header.py
|
|
||||||
pyuic5 ui/conf_item.ui -o generated/ui_conf_item.py
|
|
||||||
pyuic5 ui/build.ui -o generated/ui_build.py
|
|
||||||
pyuic5 ui/configuration_panel.ui -o generated/ui_configuration_panel.py
|
|
||||||
pyuic5 ui/new_ac_dialog.ui -o generated/ui_new_ac_dialog.py
|
|
||||||
pyuic5 ui/session.ui -o generated/ui_session.py
|
|
||||||
pyuic5 ui/program.ui -o generated/ui_program.py
|
|
||||||
pyuic5 ui/operation_panel.ui -o generated/ui_operation_panel.py
|
|
||||||
pyuic5 ui/console.ui -o generated/ui_console.py
|
|
||||||
pyuic5 ui/tools_list.ui -o generated/ui_tools_list.py
|
|
||||||
pyuic5 ui/app_settings.ui -o generated/ui_app_settings.py
|
|
||||||
pyuic5 ui/conf_settings.ui -o generated/ui_conf_settings.py
|
|
||||||
|
|
||||||
clean_ui:
|
SOURCEDIR = ui
|
||||||
|
BUILDDIR = generated
|
||||||
|
|
||||||
|
SOURCES = $(wildcard $(SOURCEDIR)/*.ui)
|
||||||
|
OBJECTS = $(patsubst $(SOURCEDIR)/%.ui,$(BUILDDIR)/%.py,$(SOURCES))
|
||||||
|
|
||||||
|
CC = pyuic5
|
||||||
|
|
||||||
|
all: $(BUILDDIR) $(OBJECTS)
|
||||||
|
|
||||||
|
|
||||||
|
$(OBJECTS): $(BUILDDIR)/%.py : $(SOURCEDIR)/%.ui
|
||||||
|
$(CC) -o $@ $<;
|
||||||
|
|
||||||
|
$(BUILDDIR):
|
||||||
|
mkdir -p $@
|
||||||
|
|
||||||
|
clean:
|
||||||
rm -r generated
|
rm -r generated
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: build_dir
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
# Copyright (C) 2008-2022 The Paparazzi Team
|
||||||
|
# released under GNU GPLv2 or later. See COPYING file.
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import List, Dict
|
from typing import List, Dict
|
||||||
import lxml.etree as ET
|
import lxml.etree as ET
|
||||||
@@ -65,11 +67,6 @@ class Aircraft:
|
|||||||
completed = subprocess.run([MOD_DEP, "-ac", self.name, "-af", self.airframe, "-fp", self.flight_plan],
|
completed = subprocess.run([MOD_DEP, "-ac", self.name, "-af", self.airframe, "-fp", self.flight_plan],
|
||||||
capture_output=True)
|
capture_output=True)
|
||||||
if completed.returncode == 0:
|
if completed.returncode == 0:
|
||||||
def remove_prefix(s):
|
|
||||||
if s.startswith(utils.CONF_DIR):
|
|
||||||
return s[len(utils.CONF_DIR):]
|
|
||||||
else:
|
|
||||||
return s
|
|
||||||
|
|
||||||
def make_setting(m):
|
def make_setting(m):
|
||||||
setting = Setting(m, True)
|
setting = Setting(m, True)
|
||||||
@@ -80,7 +77,7 @@ class Aircraft:
|
|||||||
|
|
||||||
new_settings_modules = []
|
new_settings_modules = []
|
||||||
for module_path in completed.stdout.decode().strip().split():
|
for module_path in completed.stdout.decode().strip().split():
|
||||||
module = remove_prefix(module_path)
|
module = utils.remove_prefix(module_path, utils.CONF_DIR)
|
||||||
xml = ET.parse(module_path)
|
xml = ET.parse(module_path)
|
||||||
for xml_setting in xml.getroot().findall("settings"):
|
for xml_setting in xml.getroot().findall("settings"):
|
||||||
name = xml_setting.get("name")
|
name = xml_setting.get("name")
|
||||||
@@ -215,6 +212,7 @@ class Conf:
|
|||||||
self.tree_orig = self.to_xml_tree()
|
self.tree_orig = self.to_xml_tree()
|
||||||
|
|
||||||
def restore_conf(self):
|
def restore_conf(self):
|
||||||
|
print("conf restored.")
|
||||||
self.parse(self.tree_orig)
|
self.parse(self.tree_orig)
|
||||||
|
|
||||||
def to_string(self):
|
def to_string(self):
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ class ConfSettingsWidget(QWidget, Ui_SettingsConf):
|
|||||||
base_settings_path = os.path.join(utils.CONF_DIR, "settings")
|
base_settings_path = os.path.join(utils.CONF_DIR, "settings")
|
||||||
filenames, _ = QFileDialog.getOpenFileNames(self, "Add settings", base_settings_path, "Settings (*.xml)")
|
filenames, _ = QFileDialog.getOpenFileNames(self, "Add settings", base_settings_path, "Settings (*.xml)")
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
name = utils.removeprefix(filename, utils.CONF_DIR)
|
name = utils.remove_prefix(filename, utils.CONF_DIR)
|
||||||
print(name)
|
print(name)
|
||||||
item = QListWidgetItem(name)
|
item = QListWidgetItem(name)
|
||||||
item.setCheckState(QtCore.Qt.Checked)
|
item.setCheckState(QtCore.Qt.Checked)
|
||||||
|
|||||||
@@ -1,114 +1,44 @@
|
|||||||
import os, sys, copy
|
|
||||||
from PyQt5.QtWidgets import *
|
from PyQt5.QtWidgets import *
|
||||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
import utils
|
import utils
|
||||||
from generated.ui_configuration_panel import Ui_ConfigurationPanel
|
from generated.ui_configuration_panel import Ui_ConfigurationPanel
|
||||||
from generated.ui_new_ac_dialog import Ui_Dialog
|
|
||||||
from program_widget import ProgramWidget
|
from program_widget import ProgramWidget
|
||||||
from conf import *
|
from conf import *
|
||||||
from programs_conf import parse_tools
|
from programs_conf import parse_tools
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
PAPARAZZI_SRC = os.getenv("PAPARAZZI_SRC")
|
|
||||||
PAPARAZZI_HOME = os.getenv("PAPARAZZI_HOME", PAPARAZZI_SRC)
|
|
||||||
lib_path = os.path.normpath(os.path.join(PAPARAZZI_SRC, 'sw', 'lib', 'python'))
|
|
||||||
sys.path.append(lib_path)
|
|
||||||
import paparazzi
|
|
||||||
|
|
||||||
# TODO make a setting ?
|
# TODO make a setting ?
|
||||||
REMOVE_PROGRAMS_FINISHED = True
|
REMOVE_PROGRAMS_FINISHED = True
|
||||||
|
|
||||||
|
|
||||||
class ConfigurationPanel(QWidget, Ui_ConfigurationPanel):
|
class ConfigurationPanel(QWidget, Ui_ConfigurationPanel):
|
||||||
|
|
||||||
msg_error = QtCore.pyqtSignal(str)
|
|
||||||
clear_error = QtCore.pyqtSignal()
|
clear_error = QtCore.pyqtSignal()
|
||||||
ac_changed = QtCore.pyqtSignal(Aircraft)
|
ac_edited = QtCore.pyqtSignal(Aircraft)
|
||||||
|
|
||||||
def __init__(self, parent=None, *args, **kwargs):
|
def __init__(self, parent=None, *args, **kwargs):
|
||||||
QWidget.__init__(self, parent=parent, *args, **kwargs)
|
QWidget.__init__(self, parent=parent, *args, **kwargs)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
self.console_widget.filter_widget.hide()
|
self.console_widget.filter_widget.hide()
|
||||||
self.conf = None # type: conf.Conf
|
self.currentAC = None # type: Aircraft
|
||||||
self.currentAC = None # type: str
|
|
||||||
self.flight_plan_editor = None
|
self.flight_plan_editor = None
|
||||||
self.header.set_changed.connect(self.handle_set_changed)
|
|
||||||
self.header.ac_changed.connect(self.update_ac)
|
|
||||||
self.header.id_changed.connect(self.handle_id_changed)
|
|
||||||
self.header.refresh_button.clicked.connect(self.refresh_ac)
|
|
||||||
self.header.color_button.clicked.connect(self.change_color)
|
|
||||||
self.header.save_button.clicked.connect(lambda: self.conf.save())
|
|
||||||
self.addAction(self.save_conf_action)
|
|
||||||
self.save_conf_action.triggered.connect(lambda: self.conf.save())
|
|
||||||
self.conf_widget.conf_changed.connect(self.handle_conf_changed)
|
self.conf_widget.conf_changed.connect(self.handle_conf_changed)
|
||||||
self.conf_widget.setting_changed.connect(self.handle_setting_changed)
|
self.conf_widget.setting_changed.connect(self.handle_setting_changed)
|
||||||
self.conf_widget.flight_plan.edit_alt.connect(self.edit_flightplan_gcs)
|
self.conf_widget.flight_plan.edit_alt.connect(self.edit_flightplan_gcs)
|
||||||
self.header.rename_action.triggered.connect(self.rename_ac)
|
|
||||||
self.header.new_ac_action.triggered.connect(self.new_ac)
|
|
||||||
self.header.duplicate_action.triggered.connect(self.duplicate_ac)
|
|
||||||
self.header.remove_ac_action.triggered.connect(self.remove_ac)
|
|
||||||
self.build_widget.spawn_program.connect(self.launch_program)
|
self.build_widget.spawn_program.connect(self.launch_program)
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
sets = paparazzi.get_list_of_conf_files()
|
|
||||||
settings = utils.get_settings()
|
settings = utils.get_settings()
|
||||||
self.header.set_sets(sets, conf_init=Conf.get_current_conf())
|
|
||||||
last_ac: QtCore.QVariant = settings.value("ui/last_AC", None, str)
|
|
||||||
last_target: QtCore.QVariant = settings.value("ui/last_target", None, str)
|
|
||||||
if last_ac is not None:
|
|
||||||
self.header.ac_combo.setCurrentText(last_ac)
|
|
||||||
if last_target is not None:
|
|
||||||
self.build_widget.target_combo.setCurrentText(last_target)
|
|
||||||
window_size: QtCore.QSize = settings.value("ui/window_size", QtCore.QSize(1000, 600), QtCore.QSize)
|
window_size: QtCore.QSize = settings.value("ui/window_size", QtCore.QSize(1000, 600), QtCore.QSize)
|
||||||
lpw = settings.value("ui/left_pane_width", 100, int)
|
lpw = settings.value("ui/left_pane_width", 100, int)
|
||||||
self.splitter.setSizes([lpw, window_size.width() - lpw])
|
self.splitter.setSizes([lpw, window_size.width() - lpw])
|
||||||
|
|
||||||
def handle_set_changed(self, conf_file):
|
def set_ac(self, ac: Aircraft):
|
||||||
self.conf = Conf(conf_file)
|
if ac is None:
|
||||||
Conf.set_current_conf(conf_file)
|
|
||||||
self.build_widget.set_conf(self.conf)
|
|
||||||
acs = [ac.name for ac in self.conf.aircrafts]
|
|
||||||
self.header.set_acs(acs)
|
|
||||||
|
|
||||||
def disable_sets(self):
|
|
||||||
self.header.set_combo.setDisabled(True)
|
|
||||||
|
|
||||||
def enable_sets(self):
|
|
||||||
self.header.set_combo.setDisabled(False)
|
|
||||||
|
|
||||||
def update_ac(self, ac_name):
|
|
||||||
ac = self.conf[ac_name]
|
|
||||||
if ac_name != "" and ac is not None:
|
|
||||||
self.conf_widget.setDisabled(False)
|
|
||||||
self.currentAC = ac_name
|
|
||||||
status, stderr = ac.update()
|
|
||||||
if status != 0:
|
|
||||||
self.msg_error.emit(stderr.decode().strip())
|
|
||||||
else:
|
|
||||||
self.clear_error.emit()
|
|
||||||
self.header.set_ac(ac)
|
|
||||||
self.conf_widget.set_ac(ac)
|
|
||||||
self.build_widget.update_targets(self.conf[ac_name])
|
|
||||||
self.ac_changed.emit(self.conf[ac_name])
|
|
||||||
else:
|
|
||||||
# self.conf_widget.reset()
|
|
||||||
self.conf_widget.setDisabled(True)
|
self.conf_widget.setDisabled(True)
|
||||||
|
self.currentAC = ac
|
||||||
def get_current_ac(self) -> str:
|
self.conf_widget.set_ac(ac)
|
||||||
"""
|
self.build_widget.update_targets(ac)
|
||||||
:return: name of the current AC
|
|
||||||
"""
|
|
||||||
return self.currentAC
|
|
||||||
|
|
||||||
def refresh_ac(self):
|
|
||||||
self.update_ac(self.currentAC)
|
|
||||||
|
|
||||||
def handle_id_changed(self, id):
|
|
||||||
self.conf[self.currentAC].ac_id = id
|
|
||||||
if len(self.conf.get_all(id)) > 1:
|
|
||||||
self.header.id_spinBox.setStyleSheet("background-color: red;")
|
|
||||||
else:
|
|
||||||
self.header.id_spinBox.setStyleSheet("background-color: white;")
|
|
||||||
|
|
||||||
def handle_setting_changed(self):
|
def handle_setting_changed(self):
|
||||||
def make_setting(item: QListWidgetItem):
|
def make_setting(item: QListWidgetItem):
|
||||||
@@ -125,142 +55,18 @@ class ConfigurationPanel(QWidget, Ui_ConfigurationPanel):
|
|||||||
else:
|
else:
|
||||||
settings.append(s)
|
settings.append(s)
|
||||||
|
|
||||||
self.conf[self.currentAC].settings_modules = modules
|
self.currentAC.settings_modules = modules
|
||||||
self.conf[self.currentAC].settings = settings
|
self.currentAC.settings = settings
|
||||||
|
self.ac_edited.emit(self.currentAC)
|
||||||
# should we save each time a tiny change is made ? very inefficient !
|
# should we save each time a tiny change is made ? very inefficient !
|
||||||
# self.conf.save()
|
# self.conf.save()
|
||||||
|
|
||||||
def handle_conf_changed(self):
|
def handle_conf_changed(self):
|
||||||
self.conf[self.currentAC].airframe = self.conf_widget.airframe.path
|
self.currentAC.airframe = self.conf_widget.airframe.path
|
||||||
self.conf[self.currentAC].flight_plan = self.conf_widget.flight_plan.path
|
self.currentAC.flight_plan = self.conf_widget.flight_plan.path
|
||||||
self.conf[self.currentAC].radio = self.conf_widget.radio.path
|
self.currentAC.radio = self.conf_widget.radio.path
|
||||||
self.conf[self.currentAC].telemetry = self.conf_widget.telemetry.path
|
self.currentAC.telemetry = self.conf_widget.telemetry.path
|
||||||
# reload settings modules, and update UI
|
self.ac_edited.emit(self.currentAC)
|
||||||
self.update_ac(self.currentAC)
|
|
||||||
|
|
||||||
def add_ac(self, ac: Aircraft):
|
|
||||||
self.conf.append(ac)
|
|
||||||
self.header.add_ac(ac.name)
|
|
||||||
|
|
||||||
def new_ac(self):
|
|
||||||
orig = Aircraft()
|
|
||||||
self.create_ac(orig)
|
|
||||||
|
|
||||||
def remove_ac(self):
|
|
||||||
button = QMessageBox.question(self, "Remove AC", "Remove AC <strong>{}</strong>?".format(self.currentAC))
|
|
||||||
if button == QMessageBox.Yes:
|
|
||||||
self.conf.remove(self.conf[self.currentAC])
|
|
||||||
self.header.remove_current()
|
|
||||||
|
|
||||||
def duplicate_ac(self):
|
|
||||||
orig = self.conf[self.currentAC]
|
|
||||||
self.create_ac(orig)
|
|
||||||
|
|
||||||
def create_ac(self, orig):
|
|
||||||
ui_dialog = Ui_Dialog()
|
|
||||||
dialog = QDialog(parent=self)
|
|
||||||
ui_dialog.setupUi(dialog)
|
|
||||||
|
|
||||||
def verify():
|
|
||||||
ok = True
|
|
||||||
id = ui_dialog.id_spinbox.value()
|
|
||||||
name = ui_dialog.name_edit.text()
|
|
||||||
if self.conf[id] is not None or id == 0:
|
|
||||||
ui_dialog.id_spinbox.setStyleSheet("background-color: red;")
|
|
||||||
ok = False
|
|
||||||
else:
|
|
||||||
ui_dialog.id_spinbox.setStyleSheet("")
|
|
||||||
|
|
||||||
if self.conf[name] is not None or name == "":
|
|
||||||
ui_dialog.name_edit.setStyleSheet("background-color: red;")
|
|
||||||
ok = False
|
|
||||||
else:
|
|
||||||
ui_dialog.name_edit.setStyleSheet("")
|
|
||||||
|
|
||||||
return ok
|
|
||||||
|
|
||||||
def accept():
|
|
||||||
if verify():
|
|
||||||
dialog.accept()
|
|
||||||
|
|
||||||
def reject():
|
|
||||||
dialog.reject()
|
|
||||||
|
|
||||||
def duplicate(result):
|
|
||||||
if result:
|
|
||||||
new_ac = copy.deepcopy(orig)
|
|
||||||
name = ui_dialog.name_edit.text()
|
|
||||||
ac_id = ui_dialog.id_spinbox.value()
|
|
||||||
new_ac.name = name
|
|
||||||
new_ac.ac_id = ac_id
|
|
||||||
self.add_ac(new_ac)
|
|
||||||
self.header.set_current(name)
|
|
||||||
|
|
||||||
ui_dialog.id_spinbox.setValue(self.conf.get_free_id())
|
|
||||||
ui_dialog.buttonBox.accepted.connect(accept)
|
|
||||||
ui_dialog.buttonBox.rejected.connect(reject)
|
|
||||||
ui_dialog.id_spinbox.valueChanged.connect(verify)
|
|
||||||
ui_dialog.name_edit.textChanged.connect(verify)
|
|
||||||
dialog.finished.connect(duplicate)
|
|
||||||
dialog.open()
|
|
||||||
|
|
||||||
def rename_ac(self):
|
|
||||||
orig = self.conf[self.currentAC]
|
|
||||||
ui_dialog = Ui_Dialog()
|
|
||||||
dialog = QDialog(parent=self)
|
|
||||||
ui_dialog.setupUi(dialog)
|
|
||||||
ui_dialog.name_edit.setText(orig.name)
|
|
||||||
ui_dialog.id_spinbox.setValue(orig.ac_id)
|
|
||||||
|
|
||||||
def verify():
|
|
||||||
ok = True
|
|
||||||
id = ui_dialog.id_spinbox.value()
|
|
||||||
name = ui_dialog.name_edit.text()
|
|
||||||
|
|
||||||
acs_name = self.conf.get_all(name)
|
|
||||||
if len(acs_name) > 1 or (len(acs_name) == 1 and acs_name[0] != orig):
|
|
||||||
ui_dialog.name_edit.setStyleSheet("background-color: red;")
|
|
||||||
ok = False
|
|
||||||
else:
|
|
||||||
ui_dialog.name_edit.setStyleSheet("")
|
|
||||||
|
|
||||||
acs_id = self.conf.get_all(id)
|
|
||||||
if len(acs_id) > 1 or (len(acs_id) == 1 and acs_id[0] != orig):
|
|
||||||
ui_dialog.id_spinbox.setStyleSheet("background-color: red;")
|
|
||||||
ok = False
|
|
||||||
else:
|
|
||||||
ui_dialog.id_spinbox.setStyleSheet("")
|
|
||||||
|
|
||||||
return ok
|
|
||||||
|
|
||||||
def accept():
|
|
||||||
if verify():
|
|
||||||
dialog.accept()
|
|
||||||
|
|
||||||
def reject():
|
|
||||||
dialog.reject()
|
|
||||||
|
|
||||||
def rename(result):
|
|
||||||
if result:
|
|
||||||
orig.name = ui_dialog.name_edit.text()
|
|
||||||
orig.ac_id = ui_dialog.id_spinbox.value()
|
|
||||||
self.header.rename_ac(orig.name)
|
|
||||||
|
|
||||||
ui_dialog.buttonBox.accepted.connect(accept)
|
|
||||||
ui_dialog.buttonBox.rejected.connect(reject)
|
|
||||||
ui_dialog.id_spinbox.valueChanged.connect(verify)
|
|
||||||
ui_dialog.name_edit.textChanged.connect(verify)
|
|
||||||
dialog.finished.connect(rename)
|
|
||||||
dialog.open()
|
|
||||||
|
|
||||||
def change_color(self):
|
|
||||||
ac = self.conf[self.currentAC]
|
|
||||||
initial = QtGui.QColor(ac.get_color())
|
|
||||||
color = QColorDialog.getColor(initial, self, "AC color")
|
|
||||||
if color.isValid():
|
|
||||||
color_name = color.name()
|
|
||||||
ac.set_color(color_name)
|
|
||||||
self.header.set_color(color_name)
|
|
||||||
|
|
||||||
def edit_flightplan_gcs(self, path):
|
def edit_flightplan_gcs(self, path):
|
||||||
if self.flight_plan_editor is None:
|
if self.flight_plan_editor is None:
|
||||||
|
|||||||
@@ -0,0 +1,125 @@
|
|||||||
|
# Copyright (C) 2008-2022 The Paparazzi Team
|
||||||
|
# released under GNU GPLv2 or later. See COPYING file.
|
||||||
|
|
||||||
|
from generated.ui_doc_viewer import Ui_DocPanel
|
||||||
|
from PyQt5.QtWidgets import *
|
||||||
|
from PyQt5.QtCore import QUrl
|
||||||
|
from PyQt5.QtGui import QDesktopServices
|
||||||
|
import utils
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import conf
|
||||||
|
|
||||||
|
LOCAL_DOC_ROOT = os.path.join(utils.PAPARAZZI_HOME, "doc/sphinx/build/html/")
|
||||||
|
INTERNET_DOC_ROOT = "https://paparazzi-uav.readthedocs.io/en/latest/"
|
||||||
|
|
||||||
|
|
||||||
|
class DocPanel(QWidget, Ui_DocPanel):
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
QWidget.__init__(self, parent=parent)
|
||||||
|
self.setupUi(self)
|
||||||
|
self.current_ac = None
|
||||||
|
self.doc_source_combo.currentTextChanged.connect(self.change_doc_source)
|
||||||
|
self.open_browser_button.clicked.connect(lambda: QDesktopServices.openUrl(self.webView.url()))
|
||||||
|
self.urlLineEdit.returnPressed.connect(lambda: self.webView.setUrl(QUrl(self.urlLineEdit.text())))
|
||||||
|
self.webView.loadFinished.connect(self.load_finished)
|
||||||
|
self.webView.loadProgress.connect(self.load_progress)
|
||||||
|
self.modules_list.currentTextChanged.connect(self.handle_select_module)
|
||||||
|
self.depends_modules_list.currentTextChanged.connect(self.handle_select_module)
|
||||||
|
self.unloaded_modules_list.currentTextChanged.connect(self.handle_select_module)
|
||||||
|
self.searchLineEdit.textChanged.connect(self.filter_modules)
|
||||||
|
self.target_combo.currentTextChanged.connect(self.target_changed)
|
||||||
|
self.backButton.clicked.connect(self.webView.back)
|
||||||
|
self.webView.urlChanged.connect(lambda u: self.urlLineEdit.setText(u.toString()))
|
||||||
|
url = self.make_url("index.html")
|
||||||
|
self.webView.load(url)
|
||||||
|
|
||||||
|
def load_finished(self, finished):
|
||||||
|
# print(f"load finished: {finished}")
|
||||||
|
...
|
||||||
|
# if not finished:
|
||||||
|
# self.webView.setHtml("<h1>Doc not found!</h1>"
|
||||||
|
# "<p>Documentation not found! Please build it first.</p>")
|
||||||
|
|
||||||
|
def load_progress(self, progress):
|
||||||
|
# print(f"load progress: {progress}")
|
||||||
|
...
|
||||||
|
|
||||||
|
def set_aircraft(self, ac: conf.Aircraft):
|
||||||
|
self.current_ac = ac
|
||||||
|
targets = ac.boards.keys()
|
||||||
|
self.target_combo.clear()
|
||||||
|
self.target_combo.addItem("all")
|
||||||
|
self.target_combo.addItems(targets)
|
||||||
|
|
||||||
|
def target_changed(self, target):
|
||||||
|
self.modules_list.clear()
|
||||||
|
self.depends_modules_list.clear()
|
||||||
|
self.unloaded_modules_list.clear()
|
||||||
|
if target != "":
|
||||||
|
modules = self.get_all_modules(self.current_ac, target)
|
||||||
|
for module_path, module_type in modules:
|
||||||
|
if module_type == "U" or module_type == "_":
|
||||||
|
self.modules_list.addItem(module_path)
|
||||||
|
elif module_type == "N":
|
||||||
|
self.unloaded_modules_list.addItem(module_path)
|
||||||
|
else:
|
||||||
|
self.depends_modules_list.addItem(module_path)
|
||||||
|
self.filter_modules(self.searchLineEdit.text())
|
||||||
|
|
||||||
|
def filter_modules(self, filter_txt):
|
||||||
|
def filter_list(list):
|
||||||
|
for i in range(list.count()):
|
||||||
|
if filter_txt != "":
|
||||||
|
txt = list.item(i).text()
|
||||||
|
list.item(i).setHidden(filter_txt not in txt)
|
||||||
|
else:
|
||||||
|
list.item(i).setHidden(False)
|
||||||
|
filter_list(self.modules_list)
|
||||||
|
filter_list(self.depends_modules_list)
|
||||||
|
filter_list(self.unloaded_modules_list)
|
||||||
|
|
||||||
|
def make_url(self, doc):
|
||||||
|
if self.doc_source_combo.currentText() == "Local":
|
||||||
|
path = os.path.join(LOCAL_DOC_ROOT, doc)
|
||||||
|
return QUrl.fromLocalFile(path)
|
||||||
|
else:
|
||||||
|
path = INTERNET_DOC_ROOT + doc
|
||||||
|
return QUrl(path)
|
||||||
|
|
||||||
|
def change_doc_source(self, source):
|
||||||
|
current_url = self.webView.url().toString()
|
||||||
|
lu = QUrl.fromLocalFile(LOCAL_DOC_ROOT).toString()
|
||||||
|
iu = QUrl(INTERNET_DOC_ROOT).toString()
|
||||||
|
url = QUrl("http://perdu.com")
|
||||||
|
if source == "Internet" and lu in current_url:
|
||||||
|
url = QUrl(current_url.replace(lu, iu))
|
||||||
|
if source == "Local" and iu in current_url:
|
||||||
|
url = QUrl(current_url.replace(iu, lu))
|
||||||
|
self.webView.load(url)
|
||||||
|
|
||||||
|
def handle_select_module(self, txt):
|
||||||
|
if txt == "":
|
||||||
|
return
|
||||||
|
url = self.make_url("modules/{}.html".format(txt))
|
||||||
|
self.webView.load(url)
|
||||||
|
|
||||||
|
def get_all_modules(self, ac: conf.Aircraft, target: str):
|
||||||
|
args = [conf.MOD_DEP, "-ac", ac.name, "-af", ac.airframe, "-fp", ac.flight_plan]
|
||||||
|
if target != "all":
|
||||||
|
args.extend(["-t", target])
|
||||||
|
completed = subprocess.run(args, capture_output=True)
|
||||||
|
if completed.returncode != 0:
|
||||||
|
return completed.returncode, completed.stderr
|
||||||
|
|
||||||
|
modules_list = []
|
||||||
|
module_lines = completed.stdout.decode().strip().split("\n")
|
||||||
|
for module_line in module_lines:
|
||||||
|
args = module_line.split(" ")
|
||||||
|
module_path = args[0]
|
||||||
|
module = utils.remove_prefix(args[0], os.path.join(utils.CONF_DIR, "modules/"))
|
||||||
|
module = utils.remove_suffix(module, ".xml")
|
||||||
|
module_type = args[1] if len(args) > 1 else "_"
|
||||||
|
modules_list.append((module, module_type))
|
||||||
|
return modules_list
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'ui/app_settings.ui'
|
# Form implementation generated from reading ui file 'ui/ui_app_settings.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.14.1
|
# Created by: PyQt5 UI code generator 5.14.1
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'ui/build.ui'
|
# Form implementation generated from reading ui file 'ui/ui_build.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.14.1
|
# Created by: PyQt5 UI code generator 5.14.1
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'ui/conf_header.ui'
|
# Form implementation generated from reading ui file 'ui/ui_conf_header.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.14.1
|
# Created by: PyQt5 UI code generator 5.14.1
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'ui/conf_item.ui'
|
# Form implementation generated from reading ui file 'ui/ui_conf_item.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.14.1
|
# Created by: PyQt5 UI code generator 5.14.1
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'ui/conf_settings.ui'
|
# Form implementation generated from reading ui file 'ui/ui_conf_settings.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.14.1
|
# Created by: PyQt5 UI code generator 5.14.1
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'ui/configuration_panel.ui'
|
# Form implementation generated from reading ui file 'ui/ui_configuration_panel.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.14.1
|
# Created by: PyQt5 UI code generator 5.14.1
|
||||||
#
|
#
|
||||||
@@ -16,19 +16,6 @@ class Ui_ConfigurationPanel(object):
|
|||||||
ConfigurationPanel.resize(562, 480)
|
ConfigurationPanel.resize(562, 480)
|
||||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(ConfigurationPanel)
|
self.verticalLayout_2 = QtWidgets.QVBoxLayout(ConfigurationPanel)
|
||||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||||
self.header = HeaderWidget(ConfigurationPanel)
|
|
||||||
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)
|
|
||||||
sizePolicy.setHorizontalStretch(0)
|
|
||||||
sizePolicy.setVerticalStretch(0)
|
|
||||||
sizePolicy.setHeightForWidth(self.header.sizePolicy().hasHeightForWidth())
|
|
||||||
self.header.setSizePolicy(sizePolicy)
|
|
||||||
self.header.setObjectName("header")
|
|
||||||
self.verticalLayout_2.addWidget(self.header)
|
|
||||||
self.line = QtWidgets.QFrame(ConfigurationPanel)
|
|
||||||
self.line.setFrameShape(QtWidgets.QFrame.HLine)
|
|
||||||
self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
|
|
||||||
self.line.setObjectName("line")
|
|
||||||
self.verticalLayout_2.addWidget(self.line)
|
|
||||||
self.splitter = QtWidgets.QSplitter(ConfigurationPanel)
|
self.splitter = QtWidgets.QSplitter(ConfigurationPanel)
|
||||||
self.splitter.setOrientation(QtCore.Qt.Horizontal)
|
self.splitter.setOrientation(QtCore.Qt.Horizontal)
|
||||||
self.splitter.setObjectName("splitter")
|
self.splitter.setObjectName("splitter")
|
||||||
@@ -74,4 +61,3 @@ class Ui_ConfigurationPanel(object):
|
|||||||
from build_widget import BuildWidget
|
from build_widget import BuildWidget
|
||||||
from conf_widget import ConfWidget
|
from conf_widget import ConfWidget
|
||||||
from console_widget import ConsoleWidget
|
from console_widget import ConsoleWidget
|
||||||
from header_widget import HeaderWidget
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'ui/console.ui'
|
# Form implementation generated from reading ui file 'ui/ui_console.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.14.1
|
# Created by: PyQt5 UI code generator 5.14.1
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -0,0 +1,142 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file 'ui/ui_doc_viewer.ui'
|
||||||
|
#
|
||||||
|
# Created by: PyQt5 UI code generator 5.14.1
|
||||||
|
#
|
||||||
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
|
|
||||||
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
|
||||||
|
class Ui_DocPanel(object):
|
||||||
|
def setupUi(self, DocPanel):
|
||||||
|
DocPanel.setObjectName("DocPanel")
|
||||||
|
DocPanel.resize(654, 658)
|
||||||
|
self.verticalLayout_5 = QtWidgets.QVBoxLayout(DocPanel)
|
||||||
|
self.verticalLayout_5.setObjectName("verticalLayout_5")
|
||||||
|
self.splitter_2 = QtWidgets.QSplitter(DocPanel)
|
||||||
|
self.splitter_2.setOrientation(QtCore.Qt.Horizontal)
|
||||||
|
self.splitter_2.setObjectName("splitter_2")
|
||||||
|
self.conf = QtWidgets.QWidget(self.splitter_2)
|
||||||
|
self.conf.setLayoutDirection(QtCore.Qt.LeftToRight)
|
||||||
|
self.conf.setObjectName("conf")
|
||||||
|
self.verticalLayout = QtWidgets.QVBoxLayout(self.conf)
|
||||||
|
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
|
self.verticalLayout_4 = QtWidgets.QVBoxLayout()
|
||||||
|
self.verticalLayout_4.setObjectName("verticalLayout_4")
|
||||||
|
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||||
|
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
|
||||||
|
self.label_4 = QtWidgets.QLabel(self.conf)
|
||||||
|
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred)
|
||||||
|
sizePolicy.setHorizontalStretch(0)
|
||||||
|
sizePolicy.setVerticalStretch(0)
|
||||||
|
sizePolicy.setHeightForWidth(self.label_4.sizePolicy().hasHeightForWidth())
|
||||||
|
self.label_4.setSizePolicy(sizePolicy)
|
||||||
|
self.label_4.setObjectName("label_4")
|
||||||
|
self.horizontalLayout_2.addWidget(self.label_4)
|
||||||
|
self.target_combo = QtWidgets.QComboBox(self.conf)
|
||||||
|
self.target_combo.setObjectName("target_combo")
|
||||||
|
self.horizontalLayout_2.addWidget(self.target_combo)
|
||||||
|
self.verticalLayout_4.addLayout(self.horizontalLayout_2)
|
||||||
|
self.searchLineEdit = QtWidgets.QLineEdit(self.conf)
|
||||||
|
self.searchLineEdit.setClearButtonEnabled(True)
|
||||||
|
self.searchLineEdit.setObjectName("searchLineEdit")
|
||||||
|
self.verticalLayout_4.addWidget(self.searchLineEdit)
|
||||||
|
self.verticalLayout.addLayout(self.verticalLayout_4)
|
||||||
|
self.momo = QtWidgets.QWidget(self.conf)
|
||||||
|
self.momo.setObjectName("momo")
|
||||||
|
self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.momo)
|
||||||
|
self.verticalLayout_8.setObjectName("verticalLayout_8")
|
||||||
|
self.splitter = QtWidgets.QSplitter(self.momo)
|
||||||
|
self.splitter.setOrientation(QtCore.Qt.Vertical)
|
||||||
|
self.splitter.setObjectName("splitter")
|
||||||
|
self.layoutWidget = QtWidgets.QWidget(self.splitter)
|
||||||
|
self.layoutWidget.setObjectName("layoutWidget")
|
||||||
|
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.layoutWidget)
|
||||||
|
self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||||
|
self.label = QtWidgets.QLabel(self.layoutWidget)
|
||||||
|
self.label.setObjectName("label")
|
||||||
|
self.verticalLayout_3.addWidget(self.label)
|
||||||
|
self.modules_list = QtWidgets.QListWidget(self.layoutWidget)
|
||||||
|
self.modules_list.setObjectName("modules_list")
|
||||||
|
self.verticalLayout_3.addWidget(self.modules_list)
|
||||||
|
self.layoutWidget1 = QtWidgets.QWidget(self.splitter)
|
||||||
|
self.layoutWidget1.setObjectName("layoutWidget1")
|
||||||
|
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.layoutWidget1)
|
||||||
|
self.verticalLayout_6.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.verticalLayout_6.setObjectName("verticalLayout_6")
|
||||||
|
self.label_2 = QtWidgets.QLabel(self.layoutWidget1)
|
||||||
|
self.label_2.setObjectName("label_2")
|
||||||
|
self.verticalLayout_6.addWidget(self.label_2)
|
||||||
|
self.depends_modules_list = QtWidgets.QListWidget(self.layoutWidget1)
|
||||||
|
self.depends_modules_list.setObjectName("depends_modules_list")
|
||||||
|
self.verticalLayout_6.addWidget(self.depends_modules_list)
|
||||||
|
self.layoutWidget2 = QtWidgets.QWidget(self.splitter)
|
||||||
|
self.layoutWidget2.setObjectName("layoutWidget2")
|
||||||
|
self.verticalLayout_7 = QtWidgets.QVBoxLayout(self.layoutWidget2)
|
||||||
|
self.verticalLayout_7.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.verticalLayout_7.setObjectName("verticalLayout_7")
|
||||||
|
self.label_3 = QtWidgets.QLabel(self.layoutWidget2)
|
||||||
|
self.label_3.setObjectName("label_3")
|
||||||
|
self.verticalLayout_7.addWidget(self.label_3)
|
||||||
|
self.unloaded_modules_list = QtWidgets.QListWidget(self.layoutWidget2)
|
||||||
|
self.unloaded_modules_list.setObjectName("unloaded_modules_list")
|
||||||
|
self.verticalLayout_7.addWidget(self.unloaded_modules_list)
|
||||||
|
self.verticalLayout_8.addWidget(self.splitter)
|
||||||
|
self.verticalLayout.addWidget(self.momo)
|
||||||
|
self.verticalLayout.setStretch(1, 1)
|
||||||
|
self.layoutWidget3 = QtWidgets.QWidget(self.splitter_2)
|
||||||
|
self.layoutWidget3.setObjectName("layoutWidget3")
|
||||||
|
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.layoutWidget3)
|
||||||
|
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||||
|
self.horizontalLayout = QtWidgets.QHBoxLayout()
|
||||||
|
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||||
|
self.backButton = QtWidgets.QPushButton(self.layoutWidget3)
|
||||||
|
self.backButton.setText("")
|
||||||
|
icon = QtGui.QIcon.fromTheme("go-previous")
|
||||||
|
self.backButton.setIcon(icon)
|
||||||
|
self.backButton.setObjectName("backButton")
|
||||||
|
self.horizontalLayout.addWidget(self.backButton)
|
||||||
|
self.urlLineEdit = QtWidgets.QLineEdit(self.layoutWidget3)
|
||||||
|
self.urlLineEdit.setObjectName("urlLineEdit")
|
||||||
|
self.horizontalLayout.addWidget(self.urlLineEdit)
|
||||||
|
self.open_browser_button = QtWidgets.QToolButton(self.layoutWidget3)
|
||||||
|
icon = QtGui.QIcon.fromTheme("applications-internet")
|
||||||
|
self.open_browser_button.setIcon(icon)
|
||||||
|
self.open_browser_button.setObjectName("open_browser_button")
|
||||||
|
self.horizontalLayout.addWidget(self.open_browser_button)
|
||||||
|
self.doc_source_combo = QtWidgets.QComboBox(self.layoutWidget3)
|
||||||
|
self.doc_source_combo.setObjectName("doc_source_combo")
|
||||||
|
self.doc_source_combo.addItem("")
|
||||||
|
self.doc_source_combo.addItem("")
|
||||||
|
self.horizontalLayout.addWidget(self.doc_source_combo)
|
||||||
|
self.verticalLayout_2.addLayout(self.horizontalLayout)
|
||||||
|
self.webView = QtWebKitWidgets.QWebView(self.layoutWidget3)
|
||||||
|
self.webView.setUrl(QtCore.QUrl("about:blank"))
|
||||||
|
self.webView.setObjectName("webView")
|
||||||
|
self.verticalLayout_2.addWidget(self.webView)
|
||||||
|
self.verticalLayout_5.addWidget(self.splitter_2)
|
||||||
|
|
||||||
|
self.retranslateUi(DocPanel)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(DocPanel)
|
||||||
|
|
||||||
|
def retranslateUi(self, DocPanel):
|
||||||
|
_translate = QtCore.QCoreApplication.translate
|
||||||
|
DocPanel.setWindowTitle(_translate("DocPanel", "Form"))
|
||||||
|
self.label_4.setText(_translate("DocPanel", "Target:"))
|
||||||
|
self.searchLineEdit.setPlaceholderText(_translate("DocPanel", "search..."))
|
||||||
|
self.label.setText(_translate("DocPanel", "Modules"))
|
||||||
|
self.label_2.setText(_translate("DocPanel", "Modules Dependencies"))
|
||||||
|
self.label_3.setText(_translate("DocPanel", "Modules Unloaded"))
|
||||||
|
self.backButton.setToolTip(_translate("DocPanel", "Go back"))
|
||||||
|
self.open_browser_button.setToolTip(_translate("DocPanel", "Open in Browser"))
|
||||||
|
self.open_browser_button.setText(_translate("DocPanel", "..."))
|
||||||
|
self.doc_source_combo.setToolTip(_translate("DocPanel", "source"))
|
||||||
|
self.doc_source_combo.setItemText(0, _translate("DocPanel", "Internet"))
|
||||||
|
self.doc_source_combo.setItemText(1, _translate("DocPanel", "Local"))
|
||||||
|
from PyQt5 import QtWebKitWidgets
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'ui/new_ac_dialog.ui'
|
# Form implementation generated from reading ui file 'ui/ui_new_ac_dialog.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.14.1
|
# Created by: PyQt5 UI code generator 5.14.1
|
||||||
#
|
#
|
||||||
@@ -10,38 +10,38 @@
|
|||||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
|
||||||
class Ui_Dialog(object):
|
class Ui_NewACDialog(object):
|
||||||
def setupUi(self, Dialog):
|
def setupUi(self, NewACDialog):
|
||||||
Dialog.setObjectName("Dialog")
|
NewACDialog.setObjectName("NewACDialog")
|
||||||
Dialog.resize(187, 106)
|
NewACDialog.resize(187, 106)
|
||||||
self.gridLayout = QtWidgets.QGridLayout(Dialog)
|
self.gridLayout = QtWidgets.QGridLayout(NewACDialog)
|
||||||
self.gridLayout.setObjectName("gridLayout")
|
self.gridLayout.setObjectName("gridLayout")
|
||||||
self.label = QtWidgets.QLabel(Dialog)
|
self.label = QtWidgets.QLabel(NewACDialog)
|
||||||
self.label.setObjectName("label")
|
self.label.setObjectName("label")
|
||||||
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
|
self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
|
||||||
self.name_edit = QtWidgets.QLineEdit(Dialog)
|
self.name_edit = QtWidgets.QLineEdit(NewACDialog)
|
||||||
self.name_edit.setPlaceholderText("")
|
self.name_edit.setPlaceholderText("")
|
||||||
self.name_edit.setObjectName("name_edit")
|
self.name_edit.setObjectName("name_edit")
|
||||||
self.gridLayout.addWidget(self.name_edit, 0, 1, 1, 1)
|
self.gridLayout.addWidget(self.name_edit, 0, 1, 1, 1)
|
||||||
self.label_2 = QtWidgets.QLabel(Dialog)
|
self.label_2 = QtWidgets.QLabel(NewACDialog)
|
||||||
self.label_2.setObjectName("label_2")
|
self.label_2.setObjectName("label_2")
|
||||||
self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1)
|
self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1)
|
||||||
self.id_spinbox = QtWidgets.QSpinBox(Dialog)
|
self.id_spinbox = QtWidgets.QSpinBox(NewACDialog)
|
||||||
self.id_spinbox.setMinimum(1)
|
self.id_spinbox.setMinimum(1)
|
||||||
self.id_spinbox.setMaximum(255)
|
self.id_spinbox.setMaximum(255)
|
||||||
self.id_spinbox.setObjectName("id_spinbox")
|
self.id_spinbox.setObjectName("id_spinbox")
|
||||||
self.gridLayout.addWidget(self.id_spinbox, 1, 1, 1, 1)
|
self.gridLayout.addWidget(self.id_spinbox, 1, 1, 1, 1)
|
||||||
self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
|
self.buttonBox = QtWidgets.QDialogButtonBox(NewACDialog)
|
||||||
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
|
||||||
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||||
self.buttonBox.setObjectName("buttonBox")
|
self.buttonBox.setObjectName("buttonBox")
|
||||||
self.gridLayout.addWidget(self.buttonBox, 2, 0, 1, 2)
|
self.gridLayout.addWidget(self.buttonBox, 2, 0, 1, 2)
|
||||||
|
|
||||||
self.retranslateUi(Dialog)
|
self.retranslateUi(NewACDialog)
|
||||||
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
QtCore.QMetaObject.connectSlotsByName(NewACDialog)
|
||||||
|
|
||||||
def retranslateUi(self, Dialog):
|
def retranslateUi(self, NewACDialog):
|
||||||
_translate = QtCore.QCoreApplication.translate
|
_translate = QtCore.QCoreApplication.translate
|
||||||
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
|
NewACDialog.setWindowTitle(_translate("NewACDialog", "Aircraft"))
|
||||||
self.label.setText(_translate("Dialog", "Name"))
|
self.label.setText(_translate("NewACDialog", "Name"))
|
||||||
self.label_2.setText(_translate("Dialog", "ID"))
|
self.label_2.setText(_translate("NewACDialog", "ID"))
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'ui/operation_panel.ui'
|
# Form implementation generated from reading ui file 'ui/ui_operation_panel.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.14.1
|
# Created by: PyQt5 UI code generator 5.14.1
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'ui/program.ui'
|
# Form implementation generated from reading ui file 'ui/ui_program.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.14.1
|
# Created by: PyQt5 UI code generator 5.14.1
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'ui/session.ui'
|
# Form implementation generated from reading ui file 'ui/ui_session.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.14.1
|
# Created by: PyQt5 UI code generator 5.14.1
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Form implementation generated from reading ui file 'ui/ui_supervision_window.ui'
|
||||||
|
#
|
||||||
|
# Created by: PyQt5 UI code generator 5.14.1
|
||||||
|
#
|
||||||
|
# WARNING! All changes made in this file will be lost!
|
||||||
|
|
||||||
|
|
||||||
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
|
|
||||||
|
|
||||||
|
class Ui_SupervisionWindow(object):
|
||||||
|
def setupUi(self, SupervisionWindow):
|
||||||
|
SupervisionWindow.setObjectName("SupervisionWindow")
|
||||||
|
SupervisionWindow.resize(800, 600)
|
||||||
|
self.centralwidget = QtWidgets.QWidget(SupervisionWindow)
|
||||||
|
self.centralwidget.setObjectName("centralwidget")
|
||||||
|
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
|
||||||
|
self.verticalLayout.setObjectName("verticalLayout")
|
||||||
|
self.header = HeaderWidget(self.centralwidget)
|
||||||
|
self.header.setObjectName("header")
|
||||||
|
self.verticalLayout.addWidget(self.header)
|
||||||
|
self.tabwidget = QtWidgets.QTabWidget(self.centralwidget)
|
||||||
|
self.tabwidget.setObjectName("tabwidget")
|
||||||
|
self.configuration_panel = ConfigurationPanel()
|
||||||
|
self.configuration_panel.setObjectName("configuration_panel")
|
||||||
|
self.tabwidget.addTab(self.configuration_panel, "")
|
||||||
|
self.operation_panel = OperationPanel()
|
||||||
|
self.operation_panel.setObjectName("operation_panel")
|
||||||
|
self.tabwidget.addTab(self.operation_panel, "")
|
||||||
|
self.doc_panel = DocPanel()
|
||||||
|
self.doc_panel.setObjectName("doc_panel")
|
||||||
|
self.tabwidget.addTab(self.doc_panel, "")
|
||||||
|
self.verticalLayout.addWidget(self.tabwidget)
|
||||||
|
SupervisionWindow.setCentralWidget(self.centralwidget)
|
||||||
|
self.menubar = QtWidgets.QMenuBar(SupervisionWindow)
|
||||||
|
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 22))
|
||||||
|
self.menubar.setObjectName("menubar")
|
||||||
|
self.menuFile = QtWidgets.QMenu(self.menubar)
|
||||||
|
self.menuFile.setObjectName("menuFile")
|
||||||
|
self.menuHelp = QtWidgets.QMenu(self.menubar)
|
||||||
|
self.menuHelp.setObjectName("menuHelp")
|
||||||
|
SupervisionWindow.setMenuBar(self.menubar)
|
||||||
|
self.statusbar = QtWidgets.QStatusBar(SupervisionWindow)
|
||||||
|
self.statusbar.setObjectName("statusbar")
|
||||||
|
SupervisionWindow.setStatusBar(self.statusbar)
|
||||||
|
self.settings_action = QtWidgets.QAction(SupervisionWindow)
|
||||||
|
self.settings_action.setObjectName("settings_action")
|
||||||
|
self.about_action = QtWidgets.QAction(SupervisionWindow)
|
||||||
|
self.about_action.setObjectName("about_action")
|
||||||
|
self.menuFile.addAction(self.settings_action)
|
||||||
|
self.menuHelp.addAction(self.about_action)
|
||||||
|
self.menubar.addAction(self.menuFile.menuAction())
|
||||||
|
self.menubar.addAction(self.menuHelp.menuAction())
|
||||||
|
|
||||||
|
self.retranslateUi(SupervisionWindow)
|
||||||
|
self.tabwidget.setCurrentIndex(0)
|
||||||
|
QtCore.QMetaObject.connectSlotsByName(SupervisionWindow)
|
||||||
|
|
||||||
|
def retranslateUi(self, SupervisionWindow):
|
||||||
|
_translate = QtCore.QCoreApplication.translate
|
||||||
|
SupervisionWindow.setWindowTitle(_translate("SupervisionWindow", "Paparazzi Center"))
|
||||||
|
self.tabwidget.setTabText(self.tabwidget.indexOf(self.configuration_panel), _translate("SupervisionWindow", "Configuration"))
|
||||||
|
self.tabwidget.setTabText(self.tabwidget.indexOf(self.operation_panel), _translate("SupervisionWindow", "Operation"))
|
||||||
|
self.tabwidget.setTabText(self.tabwidget.indexOf(self.doc_panel), _translate("SupervisionWindow", "Documentation"))
|
||||||
|
self.menuFile.setTitle(_translate("SupervisionWindow", "File"))
|
||||||
|
self.menuHelp.setTitle(_translate("SupervisionWindow", "Help"))
|
||||||
|
self.settings_action.setText(_translate("SupervisionWindow", "Edit Settings"))
|
||||||
|
self.about_action.setText(_translate("SupervisionWindow", "About"))
|
||||||
|
from configuration_panel import ConfigurationPanel
|
||||||
|
from doc_panel import DocPanel
|
||||||
|
from header_widget import HeaderWidget
|
||||||
|
from operation_panel import OperationPanel
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Form implementation generated from reading ui file 'ui/tools_list.ui'
|
# Form implementation generated from reading ui file 'ui/ui_tools_list.ui'
|
||||||
#
|
#
|
||||||
# Created by: PyQt5 UI code generator 5.14.1
|
# Created by: PyQt5 UI code generator 5.14.1
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -3,53 +3,95 @@
|
|||||||
from PyQt5.QtWidgets import *
|
from PyQt5.QtWidgets import *
|
||||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||||
from generated.ui_conf_header import Ui_ConfHeader
|
from generated.ui_conf_header import Ui_ConfHeader
|
||||||
import conf
|
from conf import Aircraft, Conf
|
||||||
|
import utils
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
lib_path = os.path.normpath(os.path.join(utils.PAPARAZZI_SRC, 'sw', 'lib', 'python'))
|
||||||
|
sys.path.append(lib_path)
|
||||||
|
import paparazzi
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
class HeaderWidget(QWidget, Ui_ConfHeader):
|
class HeaderWidget(QWidget, Ui_ConfHeader):
|
||||||
|
|
||||||
set_changed = QtCore.pyqtSignal(str)
|
set_changed = QtCore.pyqtSignal(str)
|
||||||
ac_changed = QtCore.pyqtSignal(str)
|
ac_changed = QtCore.pyqtSignal(str)
|
||||||
id_changed = QtCore.pyqtSignal(int)
|
ac_edited = QtCore.pyqtSignal(Aircraft)
|
||||||
|
ac_rename = QtCore.pyqtSignal(Aircraft)
|
||||||
|
ac_delete = QtCore.pyqtSignal(Aircraft)
|
||||||
|
ac_duplicate = QtCore.pyqtSignal(Aircraft)
|
||||||
|
ac_save = QtCore.pyqtSignal(Aircraft)
|
||||||
|
ac_new = QtCore.pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QWidget.__init__(self, parent=parent)
|
QWidget.__init__(self, parent=parent)
|
||||||
self.setupUi(self)
|
self.setupUi(self)
|
||||||
|
self.currentAc: Aircraft = None
|
||||||
self.set_combo.currentTextChanged.connect(self.set_changed)
|
self.set_combo.currentTextChanged.connect(self.set_changed)
|
||||||
self.ac_combo.currentTextChanged.connect(self.ac_changed)
|
self.ac_combo.currentTextChanged.connect(self.ac_changed)
|
||||||
self.id_spinBox.valueChanged.connect(self.id_changed)
|
self.id_spinBox.valueChanged.connect(self.handle_id_changed)
|
||||||
self.menu_button.addAction(self.rename_action)
|
|
||||||
self.menu_button.addAction(self.new_ac_action)
|
|
||||||
self.menu_button.addAction(self.duplicate_action)
|
|
||||||
self.menu_button.addAction(self.remove_ac_action)
|
|
||||||
|
|
||||||
def set_sets(self, sets, conf_init: str = None):
|
self.refresh_button.clicked.connect(lambda: self.ac_edited.emit(self.currentAc))
|
||||||
|
self.color_button.clicked.connect(self.change_color)
|
||||||
|
self.save_button.clicked.connect(lambda: self.ac_save.emit(self.currentAc))
|
||||||
|
|
||||||
|
self.menu_button.addAction(self.rename_action)
|
||||||
|
self.rename_action.triggered.connect(lambda: self.ac_rename.emit(self.currentAc))
|
||||||
|
self.menu_button.addAction(self.remove_ac_action)
|
||||||
|
self.remove_ac_action.triggered.connect(lambda: self.ac_delete.emit(self.currentAc))
|
||||||
|
self.menu_button.addAction(self.duplicate_action)
|
||||||
|
self.duplicate_action.triggered.connect(lambda: self.ac_duplicate.emit(self.currentAc))
|
||||||
|
self.menu_button.addAction(self.new_ac_action)
|
||||||
|
self.new_ac_action.triggered.connect(self.ac_new)
|
||||||
|
|
||||||
|
def handle_id_changed(self, new_id):
|
||||||
|
self.currentAc.ac_id = new_id
|
||||||
|
self.ac_edited.emit(self.currentAc)
|
||||||
|
|
||||||
|
def update_sets(self):
|
||||||
|
sets = paparazzi.get_list_of_conf_files()
|
||||||
|
conf_init = Conf.get_current_conf()
|
||||||
self.set_combo.addItems(sets)
|
self.set_combo.addItems(sets)
|
||||||
if conf_init in sets:
|
if conf_init in sets:
|
||||||
self.set_combo.setCurrentText(conf_init)
|
self.set_combo.setCurrentText(conf_init)
|
||||||
|
|
||||||
def set_acs(self, acs):
|
def set_acs(self, acs: List[str]):
|
||||||
self.ac_combo.clear()
|
self.ac_combo.clear()
|
||||||
self.ac_combo.addItems(acs)
|
self.ac_combo.addItems(acs)
|
||||||
|
|
||||||
def set_ac(self, ac: conf.Aircraft):
|
def set_ac(self, ac: Aircraft):
|
||||||
|
self.currentAc = ac
|
||||||
|
self.id_spinBox.blockSignals(True)
|
||||||
self.id_spinBox.setValue(ac.ac_id)
|
self.id_spinBox.setValue(ac.ac_id)
|
||||||
self.set_color(ac.get_color())
|
self.id_spinBox.blockSignals(False)
|
||||||
|
self.color_button.setStyleSheet("background-color: {};".format(ac.get_color()))
|
||||||
|
self.ac_combo.setCurrentText(ac.name)
|
||||||
|
|
||||||
def remove_current(self):
|
def add_ac(self, ac: Aircraft):
|
||||||
i = self.ac_combo.currentIndex()
|
self.ac_combo.addItem(ac.name)
|
||||||
self.ac_combo.removeItem(i)
|
|
||||||
|
|
||||||
def set_current(self, ac_name):
|
def remove_ac(self, ac):
|
||||||
self.ac_combo.setCurrentText(ac_name)
|
for i in range(self.ac_combo.count()):
|
||||||
|
if self.ac_combo.itemText(i) == ac.name:
|
||||||
def add_ac(self, ac_name):
|
self.ac_combo.removeItem(i)
|
||||||
self.ac_combo.addItem(ac_name)
|
break
|
||||||
self.set_current(ac_name)
|
|
||||||
|
|
||||||
def rename_ac(self, new_name):
|
def rename_ac(self, new_name):
|
||||||
i = self.ac_combo.currentIndex()
|
i = self.ac_combo.currentIndex()
|
||||||
self.ac_combo.setItemText(i, new_name)
|
self.ac_combo.setItemText(i, new_name)
|
||||||
|
|
||||||
def set_color(self, color: str):
|
def change_color(self):
|
||||||
self.color_button.setStyleSheet("background-color: {};".format(color))
|
initial = QtGui.QColor(self.currentAc.get_color())
|
||||||
|
color = QColorDialog.getColor(initial, self, "AC color")
|
||||||
|
if color.isValid():
|
||||||
|
color_name = color.name()
|
||||||
|
self.currentAc.set_color(color_name)
|
||||||
|
self.color_button.setStyleSheet("background-color: {};".format(color_name))
|
||||||
|
self.ac_edited.emit(self.currentAc)
|
||||||
|
|
||||||
|
def disable_sets(self):
|
||||||
|
self.set_combo.setDisabled(True)
|
||||||
|
|
||||||
|
def enable_sets(self):
|
||||||
|
self.set_combo.setDisabled(False)
|
||||||
|
|||||||
@@ -2,92 +2,244 @@
|
|||||||
# Copyright (C) 2008-2022 The Paparazzi Team
|
# Copyright (C) 2008-2022 The Paparazzi Team
|
||||||
# released under GNU GPLv2 or later. See COPYING file.
|
# released under GNU GPLv2 or later. See COPYING file.
|
||||||
import os
|
import os
|
||||||
import conf
|
import sys
|
||||||
|
import signal
|
||||||
|
import copy
|
||||||
from PyQt5.QtWidgets import *
|
from PyQt5.QtWidgets import *
|
||||||
from PyQt5 import QtCore, QtGui
|
from PyQt5 import QtCore, QtGui
|
||||||
from configuration_panel import ConfigurationPanel
|
|
||||||
from operation_panel import OperationPanel
|
|
||||||
import utils
|
import utils
|
||||||
from typing import Dict
|
|
||||||
from lxml import etree as ET
|
from lxml import etree as ET
|
||||||
|
from conf import Conf, Aircraft
|
||||||
from app_settings import AppSettings
|
from app_settings import AppSettings
|
||||||
|
from generated.ui_supervision_window import Ui_SupervisionWindow
|
||||||
|
from generated.ui_new_ac_dialog import Ui_NewACDialog
|
||||||
|
|
||||||
|
|
||||||
class PprzCenter(QMainWindow):
|
class PprzCenter(QMainWindow, Ui_SupervisionWindow):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
QMainWindow.__init__(self, parent=parent)
|
QMainWindow.__init__(self, parent=parent)
|
||||||
self.setWindowTitle("Paparazzi Center")
|
self.setupUi(self)
|
||||||
|
self.conf: Conf = None
|
||||||
|
self.currentAc: Aircraft = None
|
||||||
icon = QtGui.QIcon(os.path.join(utils.PAPARAZZI_HOME, "data", "pictures", "penguin_logo.svg"))
|
icon = QtGui.QIcon(os.path.join(utils.PAPARAZZI_HOME, "data", "pictures", "penguin_logo.svg"))
|
||||||
self.setWindowIcon(icon)
|
self.setWindowIcon(icon)
|
||||||
self.addMenu()
|
|
||||||
self.tabwidget = QTabWidget(parent=self)
|
self.settings_action.triggered.connect(self.edit_settings)
|
||||||
self.setCentralWidget(self.tabwidget)
|
self.about_action.triggered.connect(lambda: QMessageBox.about(self, "About Paparazzi", utils.ABOUT_TEXT))
|
||||||
self.configuration_panel = ConfigurationPanel(self.tabwidget)
|
|
||||||
self.operation_panel = OperationPanel(self.tabwidget)
|
|
||||||
self.tabwidget.addTab(self.configuration_panel, "Configuration")
|
|
||||||
self.tabwidget.addTab(self.operation_panel, "Operation")
|
|
||||||
self.status_msg = QLabel()
|
self.status_msg = QLabel()
|
||||||
self.statusBar().addWidget(self.status_msg)
|
self.statusBar().addWidget(self.status_msg)
|
||||||
self.fill_status_bar()
|
self.fill_status_bar()
|
||||||
self.statusBar().show()
|
|
||||||
self.configuration_panel.msg_error.connect(self.handle_error)
|
self.header.set_changed.connect(self.handle_set_changed)
|
||||||
self.configuration_panel.clear_error.connect(self.clear_error)
|
self.header.ac_changed.connect(self.handle_ac_changed)
|
||||||
self.operation_panel.session.program_spawned.connect(self.configuration_panel.disable_sets)
|
self.header.ac_edited.connect(self.handle_ac_edited)
|
||||||
self.operation_panel.session.programs_all_stopped.connect(self.configuration_panel.enable_sets)
|
self.header.ac_rename.connect(self.handle_rename_ac)
|
||||||
self.configuration_panel.ac_changed.connect(self.operation_panel.session.set_aircraft)
|
self.header.ac_delete.connect(self.handle_remove_ac)
|
||||||
|
self.header.ac_duplicate.connect(self.handle_new_ac)
|
||||||
|
self.header.ac_save.connect(lambda _: self.conf.save())
|
||||||
|
self.header.ac_new.connect(self.handle_new_ac)
|
||||||
|
|
||||||
|
self.operation_panel.session.program_spawned.connect(self.header.disable_sets)
|
||||||
|
self.operation_panel.session.programs_all_stopped.connect(self.header.enable_sets)
|
||||||
|
|
||||||
self.configuration_panel.splitter.splitterMoved.connect(self.update_left_pane_width)
|
self.configuration_panel.splitter.splitterMoved.connect(self.update_left_pane_width)
|
||||||
settings = utils.get_settings()
|
settings = utils.get_settings()
|
||||||
window_size = settings.value("ui/window_size", QtCore.QSize(1000, 600), QtCore.QSize)
|
window_size = settings.value("ui/window_size", QtCore.QSize(1000, 600), QtCore.QSize)
|
||||||
self.resize(window_size)
|
self.resize(window_size)
|
||||||
self.configuration_panel.init()
|
self.configuration_panel.init()
|
||||||
self.operation_panel.session.init()
|
self.operation_panel.session.init()
|
||||||
|
self.header.update_sets()
|
||||||
|
|
||||||
def addMenu(self):
|
def handle_set_changed(self, conf_file):
|
||||||
menubar = QMenuBar()
|
self.conf = Conf(conf_file)
|
||||||
file_menu = QMenu("&File", menubar)
|
Conf.set_current_conf(conf_file)
|
||||||
help_menu = QMenu("&Help", menubar)
|
self.configuration_panel.build_widget.set_conf(self.conf)
|
||||||
menubar.addMenu(file_menu)
|
acs = [ac.name for ac in self.conf.aircrafts]
|
||||||
menubar.addMenu(help_menu)
|
self.header.set_acs(acs)
|
||||||
settings_action = QAction("&Edit Settings", file_menu)
|
|
||||||
file_menu.addAction(settings_action)
|
|
||||||
about_action = QAction("&About", help_menu)
|
|
||||||
help_menu.addAction(about_action)
|
|
||||||
|
|
||||||
def edit_settings():
|
# set last AC as current if it exits in the current conf
|
||||||
settings_dialog = AppSettings(self)
|
settings = utils.get_settings()
|
||||||
settings_dialog.show()
|
last_ac: QtCore.QVariant = settings.value("ui/last_AC", None, str)
|
||||||
settings_action.triggered.connect(edit_settings)
|
if last_ac in acs:
|
||||||
about_action.triggered.connect(lambda: QMessageBox.about(self, "About Paparazzi", utils.ABOUT_TEXT))
|
self.handle_ac_changed(last_ac)
|
||||||
|
last_target: QtCore.QVariant = settings.value("ui/last_target", None, str)
|
||||||
|
if last_target:
|
||||||
|
self.configuration_panel.build_widget.target_combo.setCurrentText(last_target)
|
||||||
|
|
||||||
self.setMenuBar(menubar)
|
def handle_ac_edited(self, ac: Aircraft):
|
||||||
|
# check AC ID
|
||||||
|
if len(self.conf.get_all(ac.ac_id)) > 1:
|
||||||
|
self.header.id_spinBox.setStyleSheet("background-color: red;")
|
||||||
|
else:
|
||||||
|
self.header.id_spinBox.setStyleSheet("background-color: white;")
|
||||||
|
# update ac, then update all widgets
|
||||||
|
status, stderr = ac.update()
|
||||||
|
if status != 0:
|
||||||
|
self.handle_error(stderr.decode().strip())
|
||||||
|
else:
|
||||||
|
self.clear_error()
|
||||||
|
pass
|
||||||
|
self.change_ac(ac)
|
||||||
|
|
||||||
def closeEvent(self, e: QtGui.QCloseEvent) -> None:
|
def handle_ac_changed(self, ac_name):
|
||||||
|
ac = self.conf[ac_name]
|
||||||
|
if ac is not None:
|
||||||
|
# self.handle_ac_edited(ac) # update AC ?
|
||||||
|
self.change_ac(ac)
|
||||||
|
|
||||||
|
def handle_remove_ac(self, ac: Aircraft):
|
||||||
|
button = QMessageBox.question(self, "Remove AC", "Remove AC <strong>{}</strong>?".format(ac.name))
|
||||||
|
if button == QMessageBox.Yes:
|
||||||
|
self.conf.remove(ac)
|
||||||
|
self.header.remove_ac(ac)
|
||||||
|
|
||||||
|
def handle_new_ac(self, orig: Aircraft = None):
|
||||||
|
if orig is None:
|
||||||
|
orig = Aircraft()
|
||||||
|
|
||||||
|
ui_dialog = Ui_NewACDialog()
|
||||||
|
dialog = QDialog(parent=self)
|
||||||
|
ui_dialog.setupUi(dialog)
|
||||||
|
|
||||||
|
def verify():
|
||||||
|
ok = True
|
||||||
|
id = ui_dialog.id_spinbox.value()
|
||||||
|
name = ui_dialog.name_edit.text()
|
||||||
|
if self.conf[id] is not None or id == 0:
|
||||||
|
ui_dialog.id_spinbox.setStyleSheet("background-color: red;")
|
||||||
|
ok = False
|
||||||
|
else:
|
||||||
|
ui_dialog.id_spinbox.setStyleSheet("")
|
||||||
|
|
||||||
|
if self.conf[name] is not None or name == "":
|
||||||
|
ui_dialog.name_edit.setStyleSheet("background-color: red;")
|
||||||
|
ok = False
|
||||||
|
else:
|
||||||
|
ui_dialog.name_edit.setStyleSheet("")
|
||||||
|
|
||||||
|
return ok
|
||||||
|
|
||||||
|
def accept():
|
||||||
|
if verify():
|
||||||
|
dialog.accept()
|
||||||
|
|
||||||
|
def reject():
|
||||||
|
dialog.reject()
|
||||||
|
|
||||||
|
def duplicate(result):
|
||||||
|
if result:
|
||||||
|
new_ac = copy.deepcopy(orig)
|
||||||
|
name = ui_dialog.name_edit.text()
|
||||||
|
ac_id = ui_dialog.id_spinbox.value()
|
||||||
|
new_ac.name = name
|
||||||
|
new_ac.ac_id = ac_id
|
||||||
|
self.conf.append(new_ac)
|
||||||
|
self.header.add_ac(new_ac)
|
||||||
|
self.change_ac(new_ac)
|
||||||
|
|
||||||
|
ui_dialog.id_spinbox.setValue(self.conf.get_free_id())
|
||||||
|
ui_dialog.buttonBox.accepted.connect(accept)
|
||||||
|
ui_dialog.buttonBox.rejected.connect(reject)
|
||||||
|
ui_dialog.id_spinbox.valueChanged.connect(verify)
|
||||||
|
ui_dialog.name_edit.textChanged.connect(verify)
|
||||||
|
dialog.finished.connect(duplicate)
|
||||||
|
dialog.open()
|
||||||
|
|
||||||
|
def change_ac(self, ac):
|
||||||
|
self.currentAc = ac
|
||||||
|
self.header.set_ac(ac)
|
||||||
|
self.configuration_panel.set_ac(ac)
|
||||||
|
self.operation_panel.session.set_aircraft(ac)
|
||||||
|
self.doc_panel.set_aircraft(ac)
|
||||||
|
|
||||||
|
def handle_rename_ac(self, orig: Aircraft):
|
||||||
|
ui_dialog = Ui_NewACDialog()
|
||||||
|
dialog = QDialog(parent=self)
|
||||||
|
ui_dialog.setupUi(dialog)
|
||||||
|
ui_dialog.name_edit.setText(orig.name)
|
||||||
|
ui_dialog.id_spinbox.setValue(orig.ac_id)
|
||||||
|
|
||||||
|
def verify():
|
||||||
|
ok = True
|
||||||
|
id = ui_dialog.id_spinbox.value()
|
||||||
|
name = ui_dialog.name_edit.text()
|
||||||
|
|
||||||
|
acs_name = self.conf.get_all(name)
|
||||||
|
if len(acs_name) > 1 or (len(acs_name) == 1 and acs_name[0] != orig):
|
||||||
|
ui_dialog.name_edit.setStyleSheet("background-color: red;")
|
||||||
|
ok = False
|
||||||
|
else:
|
||||||
|
ui_dialog.name_edit.setStyleSheet("")
|
||||||
|
|
||||||
|
acs_id = self.conf.get_all(id)
|
||||||
|
if len(acs_id) > 1 or (len(acs_id) == 1 and acs_id[0] != orig):
|
||||||
|
ui_dialog.id_spinbox.setStyleSheet("background-color: red;")
|
||||||
|
ok = False
|
||||||
|
else:
|
||||||
|
ui_dialog.id_spinbox.setStyleSheet("")
|
||||||
|
|
||||||
|
return ok
|
||||||
|
|
||||||
|
def accept():
|
||||||
|
if verify():
|
||||||
|
dialog.accept()
|
||||||
|
|
||||||
|
def reject():
|
||||||
|
dialog.reject()
|
||||||
|
|
||||||
|
def rename(result):
|
||||||
|
if result:
|
||||||
|
orig.name = ui_dialog.name_edit.text()
|
||||||
|
orig.ac_id = ui_dialog.id_spinbox.value()
|
||||||
|
self.header.rename_ac(orig.name)
|
||||||
|
|
||||||
|
ui_dialog.buttonBox.accepted.connect(accept)
|
||||||
|
ui_dialog.buttonBox.rejected.connect(reject)
|
||||||
|
ui_dialog.id_spinbox.valueChanged.connect(verify)
|
||||||
|
ui_dialog.name_edit.textChanged.connect(verify)
|
||||||
|
dialog.finished.connect(rename)
|
||||||
|
dialog.open()
|
||||||
|
|
||||||
|
def edit_settings(self):
|
||||||
|
settings_dialog = AppSettings(self)
|
||||||
|
settings_dialog.show()
|
||||||
|
|
||||||
|
def quit(self, interactive=True):
|
||||||
|
quit_accepted = True
|
||||||
if self.operation_panel.session.any_program_running():
|
if self.operation_panel.session.any_program_running():
|
||||||
|
quit_accepted = False
|
||||||
self.operation_panel.session.programs_all_stopped.connect(self.close)
|
self.operation_panel.session.programs_all_stopped.connect(self.close)
|
||||||
self.operation_panel.session.stop_all()
|
self.operation_panel.session.stop_all()
|
||||||
e.ignore()
|
|
||||||
self.operation_panel.session.programs_all_stopped.connect(self.close)
|
self.operation_panel.session.programs_all_stopped.connect(self.close)
|
||||||
else:
|
else:
|
||||||
|
restore_conf = True
|
||||||
if utils.get_settings().value("always_keep_changes", False, bool):
|
if utils.get_settings().value("always_keep_changes", False, bool):
|
||||||
self.configuration_panel.conf.save()
|
restore_conf = False
|
||||||
else:
|
else:
|
||||||
conf_tree_orig = self.configuration_panel.conf.tree_orig
|
conf_tree_orig = self.conf.tree_orig
|
||||||
conf_tree = self.configuration_panel.conf.to_xml_tree()
|
conf_tree = self.conf.to_xml_tree()
|
||||||
if ET.tostring(conf_tree) != ET.tostring(conf_tree_orig):
|
if ET.tostring(conf_tree) != ET.tostring(conf_tree_orig) and interactive:
|
||||||
buttons = QMessageBox.question(self, "Save configuration?",
|
buttons = QMessageBox.question(self, "Save configuration?",
|
||||||
"The configuration has changed, do you want to save it?")
|
"The configuration has changed, do you want to save it?")
|
||||||
if buttons == QMessageBox.Yes:
|
if buttons == QMessageBox.Yes:
|
||||||
self.configuration_panel.conf.save()
|
restore_conf = False
|
||||||
else:
|
if restore_conf:
|
||||||
self.configuration_panel.conf.restore_conf()
|
self.conf.restore_conf()
|
||||||
self.configuration_panel.conf.save()
|
self.conf.save()
|
||||||
self.save_gconf()
|
self.save_gconf()
|
||||||
|
return quit_accepted
|
||||||
|
|
||||||
|
def closeEvent(self, e: QtGui.QCloseEvent) -> None:
|
||||||
|
if self.quit():
|
||||||
e.accept()
|
e.accept()
|
||||||
|
else:
|
||||||
|
e.ignore()
|
||||||
|
|
||||||
def save_gconf(self):
|
def save_gconf(self):
|
||||||
settings = utils.get_settings()
|
settings = utils.get_settings()
|
||||||
settings.setValue("ui/window_size", self.size())
|
settings.setValue("ui/window_size", self.size())
|
||||||
settings.setValue("ui/last_AC", self.configuration_panel.get_current_ac())
|
settings.setValue("ui/last_AC", self.currentAc.name)
|
||||||
settings.setValue("ui/last_session", self.operation_panel.session.get_current_session())
|
settings.setValue("ui/last_session", self.operation_panel.session.get_current_session())
|
||||||
|
|
||||||
def update_left_pane_width(self, pos, index):
|
def update_left_pane_width(self, pos, index):
|
||||||
@@ -119,10 +271,24 @@ class PprzCenter(QMainWindow):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
|
|
||||||
|
timer = QtCore.QTimer()
|
||||||
|
timer.start(100)
|
||||||
|
timer.timeout.connect(lambda: None) # Let the interpreter run each 100 ms.
|
||||||
|
|
||||||
main_window = PprzCenter()
|
main_window = PprzCenter()
|
||||||
main_window.show()
|
main_window.show()
|
||||||
# qApp.aboutToQuit.connect(main_window.quit)
|
# qApp.aboutToQuit.connect(main_window.quit)
|
||||||
sys.exit(app.exec_())
|
|
||||||
|
|
||||||
|
def sigint_handler(*args):
|
||||||
|
"""Handler for the SIGINT signal."""
|
||||||
|
print("catched SIGINT")
|
||||||
|
sys.stderr.write('\r')
|
||||||
|
if main_window.quit(False):
|
||||||
|
QApplication.quit()
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, sigint_handler)
|
||||||
|
|
||||||
|
sys.exit(app.exec_())
|
||||||
|
|||||||
@@ -215,6 +215,8 @@ class SessionWidget(QWidget, Ui_Session):
|
|||||||
return
|
return
|
||||||
programs = self.get_programs()
|
programs = self.get_programs()
|
||||||
session = Session(session_name, programs)
|
session = Session(session_name, programs)
|
||||||
|
self.sessions_combo.addItem(session_name)
|
||||||
|
self.sessions_combo.setCurrentText(session_name)
|
||||||
self.sessions.append(session)
|
self.sessions.append(session)
|
||||||
self.save_sessions()
|
self.save_sessions()
|
||||||
|
|
||||||
|
|||||||
-23
@@ -14,23 +14,6 @@
|
|||||||
<string>Form</string>
|
<string>Form</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
<item>
|
|
||||||
<widget class="HeaderWidget" name="header" native="true">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSplitter" name="splitter">
|
<widget class="QSplitter" name="splitter">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@@ -96,12 +79,6 @@
|
|||||||
<header>build_widget.h</header>
|
<header>build_widget.h</header>
|
||||||
<container>1</container>
|
<container>1</container>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
<customwidget>
|
|
||||||
<class>HeaderWidget</class>
|
|
||||||
<extends>QWidget</extends>
|
|
||||||
<header>header_widget.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
<customwidget>
|
<customwidget>
|
||||||
<class>ConsoleWidget</class>
|
<class>ConsoleWidget</class>
|
||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
@@ -0,0 +1,196 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>DocPanel</class>
|
||||||
|
<widget class="QWidget" name="DocPanel">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>654</width>
|
||||||
|
<height>658</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QSplitter" name="splitter_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="conf" native="true">
|
||||||
|
<property name="layoutDirection">
|
||||||
|
<enum>Qt::LeftToRight</enum>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,1">
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Target:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="target_combo"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="searchLineEdit">
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>search...</string>
|
||||||
|
</property>
|
||||||
|
<property name="clearButtonEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWidget" name="momo" native="true">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||||
|
<item>
|
||||||
|
<widget class="QSplitter" name="splitter">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="layoutWidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Modules</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="modules_list"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="layoutWidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Modules Dependencies</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="depends_modules_list"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="layoutWidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>Modules Unloaded</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="unloaded_modules_list"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="layoutWidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="backButton">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Go back</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset theme="go-previous">
|
||||||
|
<normaloff>.</normaloff>.</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="urlLineEdit"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="open_browser_button">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Open in Browser</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>...</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset theme="applications-internet">
|
||||||
|
<normaloff>.</normaloff>.</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="doc_source_combo">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>source</string>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Internet</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Local</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QWebView" name="webView">
|
||||||
|
<property name="url">
|
||||||
|
<url>
|
||||||
|
<string>about:blank</string>
|
||||||
|
</url>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>QWebView</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header location="global">QtWebKitWidgets/QWebView</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
+3
-3
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<class>Dialog</class>
|
<class>NewACDialog</class>
|
||||||
<widget class="QDialog" name="Dialog">
|
<widget class="QDialog" name="NewACDialog">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Dialog</string>
|
<string>Aircraft</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>SupervisionWindow</class>
|
||||||
|
<widget class="QMainWindow" name="SupervisionWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>800</width>
|
||||||
|
<height>600</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Paparazzi Center</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="centralwidget">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="HeaderWidget" name="header" native="true"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTabWidget" name="tabwidget">
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<widget class="ConfigurationPanel" name="configuration_panel">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Configuration</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
<widget class="OperationPanel" name="operation_panel">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Operation</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
<widget class="DocPanel" name="doc_panel">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Documentation</string>
|
||||||
|
</attribute>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenuBar" name="menubar">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>800</width>
|
||||||
|
<height>22</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<widget class="QMenu" name="menuFile">
|
||||||
|
<property name="title">
|
||||||
|
<string>File</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="settings_action"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuHelp">
|
||||||
|
<property name="title">
|
||||||
|
<string>Help</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="about_action"/>
|
||||||
|
</widget>
|
||||||
|
<addaction name="menuFile"/>
|
||||||
|
<addaction name="menuHelp"/>
|
||||||
|
</widget>
|
||||||
|
<widget class="QStatusBar" name="statusbar"/>
|
||||||
|
<action name="settings_action">
|
||||||
|
<property name="text">
|
||||||
|
<string>Edit Settings</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="about_action">
|
||||||
|
<property name="text">
|
||||||
|
<string>About</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>HeaderWidget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>header_widget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>ConfigurationPanel</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>configuration_panel.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>OperationPanel</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>operation_panel.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>DocPanel</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>doc_panel.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
@@ -18,12 +18,20 @@ PAPARAZZI_HOME = os.getenv("PAPARAZZI_HOME", PAPARAZZI_SRC)
|
|||||||
CONF_DIR = os.path.join(PAPARAZZI_HOME, "conf/")
|
CONF_DIR = os.path.join(PAPARAZZI_HOME, "conf/")
|
||||||
|
|
||||||
|
|
||||||
def removeprefix(string: str, prefix: str, /) -> str:
|
def remove_prefix(string: str, prefix: str, /) -> str:
|
||||||
if string.startswith(prefix):
|
if string.startswith(prefix):
|
||||||
return string[len(prefix):]
|
return string[len(prefix):]
|
||||||
else:
|
else:
|
||||||
return string[:]
|
return string[:]
|
||||||
|
|
||||||
|
|
||||||
|
def remove_suffix(s: str, suffix: str, /) -> str:
|
||||||
|
if s.endswith(suffix):
|
||||||
|
return s[:-len(suffix)]
|
||||||
|
else:
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
# TODO: make it work with shell program such as vim.
|
# TODO: make it work with shell program such as vim.
|
||||||
def edit_file(file_path, prefix=CONF_DIR):
|
def edit_file(file_path, prefix=CONF_DIR):
|
||||||
path = prefix + file_path
|
path = prefix + file_path
|
||||||
|
|||||||
@@ -24,16 +24,24 @@ let (//) = Filename.concat
|
|||||||
let conf_dir = Env.paparazzi_home // "conf"
|
let conf_dir = Env.paparazzi_home // "conf"
|
||||||
let conf_xml_file = conf_dir // "conf.xml"
|
let conf_xml_file = conf_dir // "conf.xml"
|
||||||
|
|
||||||
|
let letter_of_load_tyoe = function
|
||||||
|
| Aircraft.UserLoad -> "U"
|
||||||
|
| Aircraft.Depend -> "D"
|
||||||
|
| Aircraft.AutoLoad -> "A"
|
||||||
|
| Aircraft.Unloaded -> "N"
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
let ac_name = ref None
|
let ac_name = ref None
|
||||||
and af_xml = ref None
|
and af_xml = ref None
|
||||||
and fp_xml = ref None
|
and fp_xml = ref None
|
||||||
|
and target = ref None
|
||||||
and output = ref None in
|
and output = ref None in
|
||||||
|
|
||||||
let options = [
|
let options = [
|
||||||
"-ac", Arg.String (fun x -> ac_name := Some x), "Aircraft name (mandatory)";
|
"-ac", Arg.String (fun x -> ac_name := Some x), "Aircraft name (mandatory)";
|
||||||
"-af", Arg.String (fun x -> af_xml := Some x), "Airframe XML file (optinal)";
|
"-af", Arg.String (fun x -> af_xml := Some x), "Airframe XML file (optinal)";
|
||||||
"-fp", Arg.String (fun x -> fp_xml := Some x), "Flight_plan XML file (optional)";
|
"-fp", Arg.String (fun x -> fp_xml := Some x), "Flight_plan XML file (optional)";
|
||||||
|
"-t", Arg.String (fun x -> target := Some x), "Target name (optional)";
|
||||||
"-o", Arg.String (fun x -> output := Some x), "Output file name (stdout if not specified)"
|
"-o", Arg.String (fun x -> output := Some x), "Output file name (stdout if not specified)"
|
||||||
] in
|
] in
|
||||||
Arg.parse options (fun _ -> ()) "Usage:";
|
Arg.parse options (fun _ -> ()) "Usage:";
|
||||||
@@ -56,7 +64,15 @@ let () =
|
|||||||
in
|
in
|
||||||
|
|
||||||
let ac = Aircraft.parse_aircraft ~parse_af:true ~parse_ap:true ~parse_fp:true "" aircraft_xml in
|
let ac = Aircraft.parse_aircraft ~parse_af:true ~parse_ap:true ~parse_fp:true "" aircraft_xml in
|
||||||
let modules_filenames = List.map (fun m -> m.Module.xml_filename) ac.Aircraft.all_modules in
|
let modules_filenames = match !target with
|
||||||
|
| None -> List.map (fun m -> m.Module.xml_filename) ac.Aircraft.all_modules
|
||||||
|
| Some t ->
|
||||||
|
try
|
||||||
|
let selected = Hashtbl.find ac.Aircraft.config_by_target t in
|
||||||
|
List.map (fun (load_type, m) -> Printf.sprintf "%s %s" m.Module.xml_filename (letter_of_load_tyoe load_type))
|
||||||
|
selected.Aircraft.modules
|
||||||
|
with Not_found -> failwith "Dump modules: unknown target"
|
||||||
|
in
|
||||||
let modules_filenames = String.concat "\n" modules_filenames in
|
let modules_filenames = String.concat "\n" modules_filenames in
|
||||||
|
|
||||||
match !output with
|
match !output with
|
||||||
|
|||||||
Reference in New Issue
Block a user