mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-05-25 23:46:04 +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
|
||||
# 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
|
||||
|
||||
|
||||
.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 typing import List, Dict
|
||||
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],
|
||||
capture_output=True)
|
||||
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):
|
||||
setting = Setting(m, True)
|
||||
@@ -80,7 +77,7 @@ class Aircraft:
|
||||
|
||||
new_settings_modules = []
|
||||
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)
|
||||
for xml_setting in xml.getroot().findall("settings"):
|
||||
name = xml_setting.get("name")
|
||||
@@ -215,6 +212,7 @@ class Conf:
|
||||
self.tree_orig = self.to_xml_tree()
|
||||
|
||||
def restore_conf(self):
|
||||
print("conf restored.")
|
||||
self.parse(self.tree_orig)
|
||||
|
||||
def to_string(self):
|
||||
|
||||
@@ -21,7 +21,7 @@ class ConfSettingsWidget(QWidget, Ui_SettingsConf):
|
||||
base_settings_path = os.path.join(utils.CONF_DIR, "settings")
|
||||
filenames, _ = QFileDialog.getOpenFileNames(self, "Add settings", base_settings_path, "Settings (*.xml)")
|
||||
for filename in filenames:
|
||||
name = utils.removeprefix(filename, utils.CONF_DIR)
|
||||
name = utils.remove_prefix(filename, utils.CONF_DIR)
|
||||
print(name)
|
||||
item = QListWidgetItem(name)
|
||||
item.setCheckState(QtCore.Qt.Checked)
|
||||
|
||||
@@ -1,114 +1,44 @@
|
||||
import os, sys, copy
|
||||
from PyQt5.QtWidgets import *
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
import utils
|
||||
from generated.ui_configuration_panel import Ui_ConfigurationPanel
|
||||
from generated.ui_new_ac_dialog import Ui_Dialog
|
||||
from program_widget import ProgramWidget
|
||||
from conf import *
|
||||
from programs_conf import parse_tools
|
||||
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 ?
|
||||
REMOVE_PROGRAMS_FINISHED = True
|
||||
|
||||
|
||||
class ConfigurationPanel(QWidget, Ui_ConfigurationPanel):
|
||||
|
||||
msg_error = QtCore.pyqtSignal(str)
|
||||
clear_error = QtCore.pyqtSignal()
|
||||
ac_changed = QtCore.pyqtSignal(Aircraft)
|
||||
ac_edited = QtCore.pyqtSignal(Aircraft)
|
||||
|
||||
def __init__(self, parent=None, *args, **kwargs):
|
||||
QWidget.__init__(self, parent=parent, *args, **kwargs)
|
||||
self.setupUi(self)
|
||||
self.console_widget.filter_widget.hide()
|
||||
self.conf = None # type: conf.Conf
|
||||
self.currentAC = None # type: str
|
||||
self.currentAC = None # type: Aircraft
|
||||
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.setting_changed.connect(self.handle_setting_changed)
|
||||
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)
|
||||
|
||||
def init(self):
|
||||
sets = paparazzi.get_list_of_conf_files()
|
||||
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)
|
||||
lpw = settings.value("ui/left_pane_width", 100, int)
|
||||
self.splitter.setSizes([lpw, window_size.width() - lpw])
|
||||
|
||||
def handle_set_changed(self, conf_file):
|
||||
self.conf = Conf(conf_file)
|
||||
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()
|
||||
def set_ac(self, ac: Aircraft):
|
||||
if ac is None:
|
||||
self.conf_widget.setDisabled(True)
|
||||
|
||||
def get_current_ac(self) -> str:
|
||||
"""
|
||||
: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;")
|
||||
self.currentAC = ac
|
||||
self.conf_widget.set_ac(ac)
|
||||
self.build_widget.update_targets(ac)
|
||||
|
||||
def handle_setting_changed(self):
|
||||
def make_setting(item: QListWidgetItem):
|
||||
@@ -125,142 +55,18 @@ class ConfigurationPanel(QWidget, Ui_ConfigurationPanel):
|
||||
else:
|
||||
settings.append(s)
|
||||
|
||||
self.conf[self.currentAC].settings_modules = modules
|
||||
self.conf[self.currentAC].settings = settings
|
||||
self.currentAC.settings_modules = modules
|
||||
self.currentAC.settings = settings
|
||||
self.ac_edited.emit(self.currentAC)
|
||||
# should we save each time a tiny change is made ? very inefficient !
|
||||
# self.conf.save()
|
||||
|
||||
def handle_conf_changed(self):
|
||||
self.conf[self.currentAC].airframe = self.conf_widget.airframe.path
|
||||
self.conf[self.currentAC].flight_plan = self.conf_widget.flight_plan.path
|
||||
self.conf[self.currentAC].radio = self.conf_widget.radio.path
|
||||
self.conf[self.currentAC].telemetry = self.conf_widget.telemetry.path
|
||||
# reload settings modules, and update UI
|
||||
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)
|
||||
self.currentAC.airframe = self.conf_widget.airframe.path
|
||||
self.currentAC.flight_plan = self.conf_widget.flight_plan.path
|
||||
self.currentAC.radio = self.conf_widget.radio.path
|
||||
self.currentAC.telemetry = self.conf_widget.telemetry.path
|
||||
self.ac_edited.emit(self.currentAC)
|
||||
|
||||
def edit_flightplan_gcs(self, path):
|
||||
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 -*-
|
||||
|
||||
# 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
|
||||
#
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- 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
|
||||
#
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- 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
|
||||
#
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- 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
|
||||
#
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- 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
|
||||
#
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- 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
|
||||
#
|
||||
@@ -16,19 +16,6 @@ class Ui_ConfigurationPanel(object):
|
||||
ConfigurationPanel.resize(562, 480)
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout(ConfigurationPanel)
|
||||
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.setOrientation(QtCore.Qt.Horizontal)
|
||||
self.splitter.setObjectName("splitter")
|
||||
@@ -74,4 +61,3 @@ class Ui_ConfigurationPanel(object):
|
||||
from build_widget import BuildWidget
|
||||
from conf_widget import ConfWidget
|
||||
from console_widget import ConsoleWidget
|
||||
from header_widget import HeaderWidget
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- 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
|
||||
#
|
||||
|
||||
@@ -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 -*-
|
||||
|
||||
# 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
|
||||
#
|
||||
@@ -10,38 +10,38 @@
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
|
||||
class Ui_Dialog(object):
|
||||
def setupUi(self, Dialog):
|
||||
Dialog.setObjectName("Dialog")
|
||||
Dialog.resize(187, 106)
|
||||
self.gridLayout = QtWidgets.QGridLayout(Dialog)
|
||||
class Ui_NewACDialog(object):
|
||||
def setupUi(self, NewACDialog):
|
||||
NewACDialog.setObjectName("NewACDialog")
|
||||
NewACDialog.resize(187, 106)
|
||||
self.gridLayout = QtWidgets.QGridLayout(NewACDialog)
|
||||
self.gridLayout.setObjectName("gridLayout")
|
||||
self.label = QtWidgets.QLabel(Dialog)
|
||||
self.label = QtWidgets.QLabel(NewACDialog)
|
||||
self.label.setObjectName("label")
|
||||
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.setObjectName("name_edit")
|
||||
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.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.setMaximum(255)
|
||||
self.id_spinbox.setObjectName("id_spinbox")
|
||||
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.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
|
||||
self.buttonBox.setObjectName("buttonBox")
|
||||
self.gridLayout.addWidget(self.buttonBox, 2, 0, 1, 2)
|
||||
|
||||
self.retranslateUi(Dialog)
|
||||
QtCore.QMetaObject.connectSlotsByName(Dialog)
|
||||
self.retranslateUi(NewACDialog)
|
||||
QtCore.QMetaObject.connectSlotsByName(NewACDialog)
|
||||
|
||||
def retranslateUi(self, Dialog):
|
||||
def retranslateUi(self, NewACDialog):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
|
||||
self.label.setText(_translate("Dialog", "Name"))
|
||||
self.label_2.setText(_translate("Dialog", "ID"))
|
||||
NewACDialog.setWindowTitle(_translate("NewACDialog", "Aircraft"))
|
||||
self.label.setText(_translate("NewACDialog", "Name"))
|
||||
self.label_2.setText(_translate("NewACDialog", "ID"))
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- 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
|
||||
#
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- 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
|
||||
#
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# -*- 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
|
||||
#
|
||||
|
||||
@@ -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 -*-
|
||||
|
||||
# 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
|
||||
#
|
||||
|
||||
@@ -3,53 +3,95 @@
|
||||
from PyQt5.QtWidgets import *
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
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):
|
||||
|
||||
set_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):
|
||||
QWidget.__init__(self, parent=parent)
|
||||
self.setupUi(self)
|
||||
self.currentAc: Aircraft = None
|
||||
self.set_combo.currentTextChanged.connect(self.set_changed)
|
||||
self.ac_combo.currentTextChanged.connect(self.ac_changed)
|
||||
self.id_spinBox.valueChanged.connect(self.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)
|
||||
self.id_spinBox.valueChanged.connect(self.handle_id_changed)
|
||||
|
||||
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)
|
||||
if conf_init in sets:
|
||||
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.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.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):
|
||||
i = self.ac_combo.currentIndex()
|
||||
self.ac_combo.removeItem(i)
|
||||
def add_ac(self, ac: Aircraft):
|
||||
self.ac_combo.addItem(ac.name)
|
||||
|
||||
def set_current(self, ac_name):
|
||||
self.ac_combo.setCurrentText(ac_name)
|
||||
|
||||
def add_ac(self, ac_name):
|
||||
self.ac_combo.addItem(ac_name)
|
||||
self.set_current(ac_name)
|
||||
def remove_ac(self, ac):
|
||||
for i in range(self.ac_combo.count()):
|
||||
if self.ac_combo.itemText(i) == ac.name:
|
||||
self.ac_combo.removeItem(i)
|
||||
break
|
||||
|
||||
def rename_ac(self, new_name):
|
||||
i = self.ac_combo.currentIndex()
|
||||
self.ac_combo.setItemText(i, new_name)
|
||||
|
||||
def set_color(self, color: str):
|
||||
self.color_button.setStyleSheet("background-color: {};".format(color))
|
||||
def change_color(self):
|
||||
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
|
||||
# released under GNU GPLv2 or later. See COPYING file.
|
||||
import os
|
||||
import conf
|
||||
import sys
|
||||
import signal
|
||||
import copy
|
||||
from PyQt5.QtWidgets import *
|
||||
from PyQt5 import QtCore, QtGui
|
||||
from configuration_panel import ConfigurationPanel
|
||||
from operation_panel import OperationPanel
|
||||
import utils
|
||||
from typing import Dict
|
||||
from lxml import etree as ET
|
||||
from conf import Conf, Aircraft
|
||||
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):
|
||||
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"))
|
||||
self.setWindowIcon(icon)
|
||||
self.addMenu()
|
||||
self.tabwidget = QTabWidget(parent=self)
|
||||
self.setCentralWidget(self.tabwidget)
|
||||
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.settings_action.triggered.connect(self.edit_settings)
|
||||
self.about_action.triggered.connect(lambda: QMessageBox.about(self, "About Paparazzi", utils.ABOUT_TEXT))
|
||||
|
||||
self.status_msg = QLabel()
|
||||
self.statusBar().addWidget(self.status_msg)
|
||||
self.fill_status_bar()
|
||||
self.statusBar().show()
|
||||
self.configuration_panel.msg_error.connect(self.handle_error)
|
||||
self.configuration_panel.clear_error.connect(self.clear_error)
|
||||
self.operation_panel.session.program_spawned.connect(self.configuration_panel.disable_sets)
|
||||
self.operation_panel.session.programs_all_stopped.connect(self.configuration_panel.enable_sets)
|
||||
self.configuration_panel.ac_changed.connect(self.operation_panel.session.set_aircraft)
|
||||
|
||||
self.header.set_changed.connect(self.handle_set_changed)
|
||||
self.header.ac_changed.connect(self.handle_ac_changed)
|
||||
self.header.ac_edited.connect(self.handle_ac_edited)
|
||||
self.header.ac_rename.connect(self.handle_rename_ac)
|
||||
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)
|
||||
settings = utils.get_settings()
|
||||
window_size = settings.value("ui/window_size", QtCore.QSize(1000, 600), QtCore.QSize)
|
||||
self.resize(window_size)
|
||||
self.configuration_panel.init()
|
||||
self.operation_panel.session.init()
|
||||
self.header.update_sets()
|
||||
|
||||
def addMenu(self):
|
||||
menubar = QMenuBar()
|
||||
file_menu = QMenu("&File", menubar)
|
||||
help_menu = QMenu("&Help", menubar)
|
||||
menubar.addMenu(file_menu)
|
||||
menubar.addMenu(help_menu)
|
||||
settings_action = QAction("&Edit Settings", file_menu)
|
||||
file_menu.addAction(settings_action)
|
||||
about_action = QAction("&About", help_menu)
|
||||
help_menu.addAction(about_action)
|
||||
def handle_set_changed(self, conf_file):
|
||||
self.conf = Conf(conf_file)
|
||||
Conf.set_current_conf(conf_file)
|
||||
self.configuration_panel.build_widget.set_conf(self.conf)
|
||||
acs = [ac.name for ac in self.conf.aircrafts]
|
||||
self.header.set_acs(acs)
|
||||
|
||||
def edit_settings():
|
||||
settings_dialog = AppSettings(self)
|
||||
settings_dialog.show()
|
||||
settings_action.triggered.connect(edit_settings)
|
||||
about_action.triggered.connect(lambda: QMessageBox.about(self, "About Paparazzi", utils.ABOUT_TEXT))
|
||||
# set last AC as current if it exits in the current conf
|
||||
settings = utils.get_settings()
|
||||
last_ac: QtCore.QVariant = settings.value("ui/last_AC", None, str)
|
||||
if last_ac in acs:
|
||||
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():
|
||||
quit_accepted = False
|
||||
self.operation_panel.session.programs_all_stopped.connect(self.close)
|
||||
self.operation_panel.session.stop_all()
|
||||
e.ignore()
|
||||
self.operation_panel.session.programs_all_stopped.connect(self.close)
|
||||
else:
|
||||
restore_conf = True
|
||||
if utils.get_settings().value("always_keep_changes", False, bool):
|
||||
self.configuration_panel.conf.save()
|
||||
restore_conf = False
|
||||
else:
|
||||
conf_tree_orig = self.configuration_panel.conf.tree_orig
|
||||
conf_tree = self.configuration_panel.conf.to_xml_tree()
|
||||
if ET.tostring(conf_tree) != ET.tostring(conf_tree_orig):
|
||||
conf_tree_orig = self.conf.tree_orig
|
||||
conf_tree = self.conf.to_xml_tree()
|
||||
if ET.tostring(conf_tree) != ET.tostring(conf_tree_orig) and interactive:
|
||||
buttons = QMessageBox.question(self, "Save configuration?",
|
||||
"The configuration has changed, do you want to save it?")
|
||||
if buttons == QMessageBox.Yes:
|
||||
self.configuration_panel.conf.save()
|
||||
else:
|
||||
self.configuration_panel.conf.restore_conf()
|
||||
self.configuration_panel.conf.save()
|
||||
restore_conf = False
|
||||
if restore_conf:
|
||||
self.conf.restore_conf()
|
||||
self.conf.save()
|
||||
self.save_gconf()
|
||||
return quit_accepted
|
||||
|
||||
def closeEvent(self, e: QtGui.QCloseEvent) -> None:
|
||||
if self.quit():
|
||||
e.accept()
|
||||
else:
|
||||
e.ignore()
|
||||
|
||||
def save_gconf(self):
|
||||
settings = utils.get_settings()
|
||||
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())
|
||||
|
||||
def update_left_pane_width(self, pos, index):
|
||||
@@ -119,10 +271,24 @@ class PprzCenter(QMainWindow):
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
|
||||
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.show()
|
||||
# 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
|
||||
programs = self.get_programs()
|
||||
session = Session(session_name, programs)
|
||||
self.sessions_combo.addItem(session_name)
|
||||
self.sessions_combo.setCurrentText(session_name)
|
||||
self.sessions.append(session)
|
||||
self.save_sessions()
|
||||
|
||||
|
||||
-23
@@ -14,23 +14,6 @@
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<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>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
@@ -96,12 +79,6 @@
|
||||
<header>build_widget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>HeaderWidget</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>header_widget.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>ConsoleWidget</class>
|
||||
<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"?>
|
||||
<ui version="4.0">
|
||||
<class>Dialog</class>
|
||||
<widget class="QDialog" name="Dialog">
|
||||
<class>NewACDialog</class>
|
||||
<widget class="QDialog" name="NewACDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
@@ -11,7 +11,7 @@
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
<string>Aircraft</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<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/")
|
||||
|
||||
|
||||
def removeprefix(string: str, prefix: str, /) -> str:
|
||||
def remove_prefix(string: str, prefix: str, /) -> str:
|
||||
if string.startswith(prefix):
|
||||
return string[len(prefix):]
|
||||
else:
|
||||
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.
|
||||
def edit_file(file_path, prefix=CONF_DIR):
|
||||
path = prefix + file_path
|
||||
|
||||
Reference in New Issue
Block a user