diff --git a/paparazzi b/paparazzi index 2557c7debe..18e723de9c 100755 --- a/paparazzi +++ b/paparazzi @@ -11,7 +11,7 @@ env['PAPARAZZI_HOME'] = PAPARAZZI_HOME env['PAPARAZZI_SRC'] = PAPARAZZI_SRC if len(sys.argv) > 1 and sys.argv[1] == "-python": - path = os.path.normpath(os.path.join(dirname, 'sw', 'supervision', 'python', 'main.py')) + path = os.path.normpath(os.path.join(dirname, 'sw', 'supervision', 'python', 'paparazzicenter.py')) os.execve(path, sys.argv, env) else: path = os.path.normpath(os.path.join(dirname, 'sw', 'supervision', 'paparazzicenter')) diff --git a/sw/supervision/python/.cache.dtd b/sw/supervision/python/.cache.dtd deleted file mode 100644 index 3a3f843f05..0000000000 --- a/sw/supervision/python/.cache.dtd +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/sw/supervision/python/Makefile b/sw/supervision/python/Makefile new file mode 100644 index 0000000000..6db5e54e04 --- /dev/null +++ b/sw/supervision/python/Makefile @@ -0,0 +1,18 @@ +# 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 + +clean: + rm -r generated diff --git a/sw/supervision/python/README.md b/sw/supervision/python/README.md deleted file mode 100644 index 759f72a36b..0000000000 --- a/sw/supervision/python/README.md +++ /dev/null @@ -1,69 +0,0 @@ -############################################################################### -# Welcome in the future Paparazzi Center ! # -############################################################################### - -1) Run instructions : - -To run the new Paparazzi Center, you need : - -> A Linux or IOS system - -> A correctly installed version of Paparazzi UAV software - -> Python 3.4 (install package 'python3') - -> PyQt5 (install package 'python3-pyqt5') - -First "git pull" my part of code or copy the current "./sw/supervision/python" -version into your own "./sw/supervision" directory. No installation nor -compilation is needed. -Then, make the 'main.py' file executable ('chmod +x main.py') and launch the -program in a terminal ('./main.py') or from the paparazzi launcher (soon). - -############################################################################### - -2) Feedback : - -I'm an intern student at the ENAC and my mission is to reconceive the Paparazzi -Center in Python/Qt to make it more intuitive and 'maintainable' (that can -evolve easily). So I'd really like to have your feeling about my propositions ! - -If you have any question or comment about it, please contact me by -Github (my pseudo is 'floienac' and I use Gitter) or by mail -('f.bitard@gmail.com'). -I'd be glad to be criticized, especially if you're directly concerned as a -final user or a developer of Paparazzi UAV. - -Thanks by advance :) - -Florian BITARD - intern student at the ENAC's drones lab -(February to June 2016) - -http://wiki.paparazziuav.org/wiki/Paparazzi_Center/Evolutions -############################################################################### - -3) GNU License : - -As this new Paparazzi Center is a free and open source software part, feel -free to correct bugs, improve the functions and add new ones to it. - -# Paparazzi center utilities -# -# Copyright (C) 2016 ENAC, Florian BITARD (intern student) -# -# This file is part of paparazzi. -# -# paparazzi is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# paparazzi is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with paparazzi; see the file COPYING. If not, write to -# the Free Software Foundation, 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. diff --git a/sw/supervision/python/Readme.md b/sw/supervision/python/Readme.md new file mode 100644 index 0000000000..6ec617f025 --- /dev/null +++ b/sw/supervision/python/Readme.md @@ -0,0 +1,10 @@ +# Paparazzi Center + +The Paparazzi Center is the home application for Paparazzi UAV. + + + +Install the package `pyqt5-dev-tools` and run `make` to generate python ui files. + +Install python dependencies: +`python3 -m pip install -r requirements.txt` diff --git a/sw/supervision/python/app_settings.py b/sw/supervision/python/app_settings.py new file mode 100644 index 0000000000..d74fa78ed8 --- /dev/null +++ b/sw/supervision/python/app_settings.py @@ -0,0 +1,28 @@ +# Copyright (C) 2008-2022 The Paparazzi Team +# released under GNU GPLv2 or later. See COPYING file. +from PyQt5.QtWidgets import * +from PyQt5 import QtCore, QtGui, QtWidgets +from generated.ui_app_settings import Ui_AppSettingsDialog +import utils + + +class AppSettings(QDialog, Ui_AppSettingsDialog): + + def __init__(self, parent=None): + QWidget.__init__(self, parent=parent) + self.setupUi(self) + settings = utils.get_settings() + self.text_editor_edit.setText(settings.value("text_editor", "", str)) + self.terminal_emulator_edit.setText(settings.value("terminal_emulator", "", str)) + self.keep_changes_checkbox.setChecked(settings.value("always_keep_changes", False, bool)) + self.finished.connect(self.handle_finished) + + def handle_finished(self, result): + if result: + settings = utils.get_settings() + text_editor = self.text_editor_edit.text() + settings.setValue("text_editor", text_editor) + terminal_emulator = self.terminal_emulator_edit.text() + settings.setValue("terminal_emulator", terminal_emulator) + keep_changes = self.keep_changes_checkbox.isChecked() + settings.setValue("always_keep_changes", keep_changes) diff --git a/sw/supervision/python/build_widget.py b/sw/supervision/python/build_widget.py new file mode 100644 index 0000000000..64a2e9594f --- /dev/null +++ b/sw/supervision/python/build_widget.py @@ -0,0 +1,119 @@ +# Copyright (C) 2008-2022 The Paparazzi Team +# released under GNU GPLv2 or later. See COPYING file. +from PyQt5.QtWidgets import * +from PyQt5 import QtCore +from generated.ui_build import Ui_Build +import lxml.etree as ET +import os +import utils +from conf import Aircraft, Conf +from typing import List, Dict +from dataclasses import dataclass, field +import re + + +@dataclass +class FlashMode: + name: str + vars: Dict[str, str] = field(default_factory=dict) + boards: List[str] = field(default_factory=list) + + def match(self, board): + for regex in self.boards: + if re.match(regex, board) is not None: + return True + return False + + +class BuildWidget(Ui_Build, QWidget): + + spawn_program = QtCore.pyqtSignal(str, list, str) + + def __init__(self, parent=None): + QWidget.__init__(self, parent=parent) + self.setupUi(self) + # uic.loadUi("ui/build.ui", self) + self.ac: Aircraft = None + self.conf: Conf = None # to save conf before building + self.flash_modes: List[FlashMode] = self.parse_flash_modes() + self.build_button.clicked.connect(self.build) + self.clean_button.clicked.connect(self.clean) + self.flash_button.clicked.connect(self.flash) + self.target_combo.currentTextChanged.connect(self.update_flash_mode) + + def set_conf(self, conf: Conf): + self.conf = conf + + @staticmethod + def parse_flash_modes() -> List[FlashMode]: + flash_xml = ET.parse(os.path.join(utils.CONF_DIR, "flash_modes.xml")) + modes = [] + for xml_mode in flash_xml.getroot().findall("mode"): + mode_name = xml_mode.get("name") + vars = {} + for xml_var in xml_mode.findall("variable"): + var_name = xml_var.get("name") + var_value = xml_var.get("value") + vars[var_name] = var_value + mode = FlashMode(mode_name, vars) + for xml_board in xml_mode.find("boards").findall("board"): + board = xml_board.get("name") + mode.boards.append(board) + modes.append(mode) + return modes + + def get_flash_modes(self, board): + modes = filter(lambda fm: fm.match(board), self.flash_modes) + mode_names = [mode.name for mode in modes] + return mode_names + + def update_targets(self, ac: Aircraft): + self.ac = ac + self.target_combo.clear() + + for target in ac.boards.keys(): + self.target_combo.addItem(target) + + def update_flash_mode(self, target): + self.device_combo.clear() + if target != "": + self.device_combo.addItem("Default") + board = self.ac.boards[target] + flash_modes = self.get_flash_modes(board) + self.device_combo.addItems(flash_modes) + + def get_current_target(self) -> str: + return self.target_combo.currentText() + + def build(self): + target = self.target_combo.currentText() + cmd = ["make", "-C", utils.PAPARAZZI_HOME, "-f", "Makefile.ac", + "AIRCRAFT={}".format(self.ac.name), "{}.compile".format(target)] + if self.print_config_checkbox.isChecked(): + cmd.append("PRINT_CONFIG=1") + shortname = "Build {}".format(self.ac.name) + self.conf.save(False) + self.spawn_program.emit(shortname, cmd, None) + + def clean(self): + cmd = ["make", "-C", utils.PAPARAZZI_HOME, "-f", "Makefile.ac", + "AIRCRAFT={}".format(self.ac.name), "clean_ac"] + shortname = "Clean {}".format(self.ac.name) + self.spawn_program.emit(shortname, cmd, None) + + def flash(self): + target = self.target_combo.currentText() + vars = [] + flash_mode = self.device_combo.currentText() + if flash_mode != "Default": + for mode in self.flash_modes: + if mode.name == flash_mode: + vars = ["{}={}".format(var_name, var_value) for (var_name, var_value) in mode.vars.items()] + break + else: + raise Exception("Flash mode {} not found!".format(flash_mode)) + cmd = ["make", "-C", utils.PAPARAZZI_HOME, "-f", "Makefile.ac", + "AIRCRAFT={}".format(self.ac.name)] + vars + ["{}.upload".format(target)] + shortname = "Flash {}".format(self.ac.name) + self.spawn_program.emit(shortname, cmd, None) + diff --git a/sw/supervision/python/conf.py b/sw/supervision/python/conf.py new file mode 100644 index 0000000000..e7540aab37 --- /dev/null +++ b/sw/supervision/python/conf.py @@ -0,0 +1,247 @@ +from dataclasses import dataclass, field +from typing import List, Dict +import lxml.etree as ET +import os +import subprocess +import utils + +MOD_DEP = os.path.join(utils.PAPARAZZI_SRC, "sw", "tools", "generators", "dump_modules_list.out") +CONF = os.path.join(utils.PAPARAZZI_HOME, "conf", "conf.xml") + + +@dataclass +class Setting: + name: str + enabled: bool + + def __str__(self): + if self.enabled: + return self.name + else: + return f"[{self.name}]" + + +@dataclass +class Aircraft: + name: str = "" + ac_id: int = 0 + airframe: str = "" + radio: str = "" + telemetry: str = "" + flight_plan: str = "" + gui_color: str = "red" + settings: List[Setting] = field(default_factory=list) + settings_modules: List[Setting] = field(default_factory=list) + boards: Dict[str, str] = field(default_factory=dict, init=False) # {target: board} + + def __post_init__(self): + self.update_targets() + + def get_color(self) -> str: + if self.gui_color.startswith("#"): + r = self.gui_color[1:3] + g = self.gui_color[5:7] + b = self.gui_color[9:11] + color = "#{}{}{}".format(r, g, b) + return color + + else: + return self.gui_color + + def set_color(self, color: str): + if color.startswith("#"): + r = color[1:3] + g = color[3:5] + b = color[5:7] + self.gui_color = "#{}00{}00{}00".format(r, g, b) + else: + self.gui_color = color + + def update(self): + self.update_targets() + return self.update_settings() + + def update_settings(self): + 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) + for s in self.settings_modules: + if m == s.name and not s.enabled: + setting.enabled = False + return setting + + new_settings_modules = [] + for module_path in completed.stdout.decode().strip().split(): + module = remove_prefix(module_path) + xml = ET.parse(module_path) + for xml_setting in xml.getroot().findall("settings"): + name = xml_setting.get("name") + if name is None: + txt = module + else: + txt = "{}~{}~".format(module, name) + setting = make_setting(txt) + new_settings_modules.append(setting) + + self.settings_modules = new_settings_modules + + return completed.returncode, completed.stderr + + def to_xml(self) -> ET.Element: + xml = ET.Element("aircraft") + xml.set("name", self.name) + xml.set("ac_id", str(self.ac_id)) + xml.set("airframe", self.airframe) + xml.set("radio", self.radio) + xml.set("telemetry", self.telemetry) + xml.set("flight_plan", self.flight_plan) + settings_modules = " ".join(str(setting) for setting in self.settings_modules) + settings = " ".join(str(setting) for setting in self.settings) + xml.set("settings", settings) + xml.set("settings_modules", settings_modules) + xml.set("gui_color", self.gui_color) + return xml + + def to_string(self): + xml = " 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;") + + def handle_setting_changed(self): + def make_setting(item: QListWidgetItem): + name = item.text() + state = True if item.checkState() == QtCore.Qt.Checked else False + return Setting(name, state) + + modules, settings = [], [] + for i in range(self.conf_widget.settings.count()): + item = self.conf_widget.settings.item(i) + s = make_setting(item) + if item.text().startswith("module"): + modules.append(s) + else: + settings.append(s) + + self.conf[self.currentAC].settings_modules = modules + self.conf[self.currentAC].settings = settings + # 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 {}?".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): + if self.flight_plan_editor is None: + tools = parse_tools() + if "Flight Plan Editor" in tools: + self.flight_plan_editor = tools["Flight Plan Editor"] + + if self.flight_plan_editor is not None: + cmd = [os.path.join(utils.PAPARAZZI_SRC, self.flight_plan_editor.command)] + for arg in self.flight_plan_editor.args: + cmd += arg.args() + cmd.append(os.path.join(utils.CONF_DIR, path)) + subprocess.Popen(cmd) + # self.launch_program(self.flight_plan_editor.name, cmd, self.flight_plan_editor.icon) + + def launch_program(self, shortname, cmd, icon): + pw = ProgramWidget(shortname, cmd, icon, self.programs_widget) + self.programs_widget.layout().addWidget(pw) + pw.ready_read_stderr.connect(lambda: self.console_widget.handle_stderr(pw)) + pw.ready_read_stdout.connect(lambda: self.console_widget.handle_stdout(pw)) + pw.finished.connect(lambda c, s: self.console_widget.handle_program_finished(pw, c, s)) + pw.remove.connect(lambda: self.remove_program(pw)) + if REMOVE_PROGRAMS_FINISHED: + pw.finished.connect(lambda: self.remove_program(pw)) + pw.start_program() + + def remove_program(self, pw: ProgramWidget): + self.programs_widget.layout().removeWidget(pw) + self.console_widget.remove_program(pw) + pw.deleteLater() diff --git a/sw/supervision/python/console_widget.py b/sw/supervision/python/console_widget.py new file mode 100644 index 0000000000..6ffc1b1435 --- /dev/null +++ b/sw/supervision/python/console_widget.py @@ -0,0 +1,189 @@ +# Copyright (C) 2008-2022 The Paparazzi Team +# released under GNU GPLv2 or later. See COPYING file. +from generated.ui_console import Ui_Console +from PyQt5.QtWidgets import * +from PyQt5.QtCore import QProcess, QByteArray, Qt +from PyQt5.QtGui import QTextCursor +import utils +from program_widget import ProgramWidget +from dataclasses import dataclass +from enum import Enum +from typing import Dict, List + + +class Level(Enum): + ERROR = 0 + WARNING = 1 + INFO = 2 + ALL = 3 + + +class Channel(Enum): + STDOUT = 0 + STDERR = 1 + MANAGEMENT = 2 + + +@dataclass +class Record: + level: Level + data: str + emitter: ProgramWidget + channel: Channel + + +class ConsoleWidget(QWidget, Ui_Console): + + LEVELS_REG = { + Level.ERROR: ["error:", "error ", "no such file", "undefined reference", "failure", "multiple definition"], + Level.WARNING: ["warning", "no srtm data found"], + Level.INFO: ["pragma message", "info:", "paparazzi version", "build aircraft"] + } + + def __init__(self, parent=None): + QWidget.__init__(self, parent=parent) + self.setupUi(self) + self.records: List[Record] = [] + self.p_checkboxes: Dict[ProgramWidget, QCheckBox] = {} + self.programs_checkbox.stateChanged.connect(self.handle_check_all) + self.log_level_slider.valueChanged.connect(self.log_level_changed) + self.clear_button.clicked.connect(self.clear) + self.splitter.setSizes([500, 100]) + + def display_record(self, record): + if record.level == Level.ERROR: + bg = "background-color:red;" + elif record.level == Level.WARNING: + bg = "background-color:orange;" + elif record.level == Level.INFO: + bg = "background-color:lime;" + else: + bg = "" + + if record.channel == Channel.STDOUT: + ch = "" + elif record.channel == Channel.STDERR: + ch = "font-style: italic;" + else: + ch = "font-weight: bold;" + + data = "{}".format(bg, ch, record.data) + self.console_textedit.append(data) + + def classify(self, line: str): + for level, regs in self.LEVELS_REG.items(): + for reg in regs: + if reg in line.lower(): + return level + return Level.ALL + + def handle_data(self, pw: ProgramWidget, data: QByteArray, channel: Channel): + if pw not in self.p_checkboxes: + self.new_program(pw) + if data.endsWith(b'\n'): + data = data[:-1] + lines = data.split(b'\n') + for line in lines: + line = line.data().decode() + level = self.classify(line) + r = Record(level, line, pw, channel) + self.records.append(r) + self.display_record(r) + + def handle_stdout(self, pw: ProgramWidget): + data = pw.process.readAllStandardOutput() + self.handle_data(pw, data, Channel.STDOUT) + + def handle_stderr(self, pw: ProgramWidget): + data = pw.process.readAllStandardError() + self.handle_data(pw, data, Channel.STDERR) + + def handle_program_finished(self, pw: ProgramWidget, exit_code: int, exit_status: QProcess.ExitStatus): + if exit_code == 0: + self.post_message(pw, "{} Done".format(pw.shortname)) + else: + self.post_message(pw, "{} terminated with code {}".format(pw.shortname, exit_code)) + + def post_message(self, pw: ProgramWidget, msg): + r = Record(Level.ALL, msg, pw, Channel.MANAGEMENT) + self.records.append(r) + self.display_record(r) + + def new_program(self, pw: ProgramWidget): + chk = QCheckBox(pw.shortname, self.programs_widget) + chk.setToolTip(" ".join(pw.cmd)) + self.p_checkboxes[pw] = chk + index = self.programs_widget.layout().count() - 1 + lay: QVBoxLayout = self.programs_widget.layout() + lay.insertWidget(index, chk) + chk.stateChanged.connect(self.handle_program_checked) + self.handle_program_checked() + + def remove_program(self, pw: ProgramWidget): + chk = self.p_checkboxes.pop(pw) + if chk is not None: + for r in self.records: + if r.emitter == pw: + r.emitter = None + self.programs_widget.layout().removeWidget(chk) + chk.deleteLater() + self.update_content() + + def handle_check_all(self, state): + if state == Qt.PartiallyChecked: + state = Qt.Checked + for chk in self.p_checkboxes.values(): + chk.blockSignals(True) + chk.setCheckState(state) + chk.blockSignals(False) + self.update_content() + + def handle_program_checked(self): + chks = list(self.p_checkboxes.values()) + if len(chks) > 0: + state = chks[0].checkState() + for s in chks[1:]: + if s.checkState() != state: + self.programs_checkbox.blockSignals(True) + self.programs_checkbox.setCheckState(Qt.PartiallyChecked) + self.programs_checkbox.blockSignals(False) + break + else: + self.programs_checkbox.blockSignals(True) + self.programs_checkbox.setCheckState(state) + self.programs_checkbox.blockSignals(False) + self.update_content() + + def log_level_changed(self, value): + if value == Level.ERROR.value: + self.log_level_label.setText("Errors") + elif value == Level.WARNING.value: + self.log_level_label.setText("Warnings") + elif value == Level.INFO.value: + self.log_level_label.setText("Info") + elif value == Level.ALL.value: + self.log_level_label.setText("All") + self.update_content() + + def filter(self, r: Record): + log_level = self.log_level_slider.value() + if r.level.value > log_level: + return False + # if any program is checked, display only those that are checked + if self.programs_checkbox.checkState() != Qt.Unchecked: + if r.emitter is None: + return False + if self.p_checkboxes[r.emitter].checkState() != Qt.Checked: + return False + return True + + def update_content(self): + self.console_textedit.clear() + for r in self.records: + if self.filter(r): + self.display_record(r) + + def clear(self): + # TODO remove only filtered ? plus trashed ? + self.records.clear() + self.update_content() diff --git a/sw/supervision/python/dialogs.py b/sw/supervision/python/dialogs.py deleted file mode 100644 index 1f3c1c2097..0000000000 --- a/sw/supervision/python/dialogs.py +++ /dev/null @@ -1,103 +0,0 @@ -# Paparazzi center utilities -# -# Copyright (C) 2016 ENAC, Florian BITARD (intern student) -# -# This file is part of paparazzi. -# -# paparazzi is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# paparazzi is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with paparazzi; see the file COPYING. If not, write to -# the Free Software Foundation, 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -############################################################################### -# [Imports] - -import ui.set_manager as manager -import ui.popup as popup - -import PyQt5.QtWidgets as Widgets -import logging -import os - - -############################################################################### -# [Constants] - -LOGGER = logging.getLogger("[DIALOGS]") - -UI_DIR = "ui" - -DATA_CHANGED_POPUP_TYPE = "data changed" -DATA_CHANGED_POPUP_HTML = "data_changed.html" -CREDITS_POPUP_TYPE = "credits" -CREDITS_POPUP_HTML = "credits.html" -TUTORIAL_POPUP_TYPE = "tutorial" -TUTORIAL_POPUP_HTML = "tutorial.html" - - -############################################################################### -# [SettingsManager class] - -class SettingsManager(Widgets.QDialog): - """Class to manage the settings manager HMI.""" - def __init__(self): - super(SettingsManager, self).__init__() - self.ui = manager.Ui_Dialog() - self.ui.setupUi(self) - - -############################################################################### -# [SettingsManager class] - -class Popup(Widgets.QDialog): - """Class to manage the settings manager HMI.""" - def __init__(self, popup_type=None): - super(Popup, self).__init__() - self.ui = popup.Ui_Dialog() - self.ui.setupUi(self) - self.ui.textBrowser.setOpenExternalLinks(True) - - self.type = popup_type - - self.set_popup_details() - - def set_popup_details(self): - """ - -> Set the title, the text and the dialog buttons of the popup window - according to its type. - """ - if self.type == DATA_CHANGED_POPUP_TYPE: - self.setWindowTitle("/!\ Some unsaved data found !") - self.ui.buttonBox.setStandardButtons( - Widgets.QDialogButtonBox.Cancel | Widgets.QDialogButtonBox.Save) - html_file = DATA_CHANGED_POPUP_HTML - elif self.type == CREDITS_POPUP_TYPE: - self.setWindowTitle("Paparazzi UAV Center credits " - "(Python/Qt version)") - self.ui.buttonBox.setStandardButtons(Widgets.QDialogButtonBox.Close) - html_file = CREDITS_POPUP_HTML - elif self.type == TUTORIAL_POPUP_TYPE: - self.setWindowTitle("Tutorials and documents") - self.ui.buttonBox.setStandardButtons(Widgets.QDialogButtonBox.Close) - html_file = TUTORIAL_POPUP_HTML - else: - self.setWindowTitle("Popup without specific type.") - html_file = "none.html" - - try: - html_config_path = os.path.join(UI_DIR, html_file) - with open(html_config_path, 'r') as popup_html_content: - self.ui.textBrowser.setHtml(popup_html_content.read()) - except FileNotFoundError: - print("Popup HTML configuration file not found ! " - "('%s' should be in 'ui' directory.)" % html_file) diff --git a/sw/supervision/python/generated/ui_app_settings.py b/sw/supervision/python/generated/ui_app_settings.py new file mode 100644 index 0000000000..3f8f2aa4c1 --- /dev/null +++ b/sw/supervision/python/generated/ui_app_settings.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ui/app_settings.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_AppSettingsDialog(object): + def setupUi(self, AppSettingsDialog): + AppSettingsDialog.setObjectName("AppSettingsDialog") + AppSettingsDialog.resize(381, 131) + self.gridLayout = QtWidgets.QGridLayout(AppSettingsDialog) + self.gridLayout.setObjectName("gridLayout") + self.label = QtWidgets.QLabel(AppSettingsDialog) + self.label.setObjectName("label") + self.gridLayout.addWidget(self.label, 0, 0, 1, 1) + self.text_editor_edit = QtWidgets.QLineEdit(AppSettingsDialog) + self.text_editor_edit.setObjectName("text_editor_edit") + self.gridLayout.addWidget(self.text_editor_edit, 0, 1, 1, 1) + self.label_2 = QtWidgets.QLabel(AppSettingsDialog) + self.label_2.setObjectName("label_2") + self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1) + self.terminal_emulator_edit = QtWidgets.QLineEdit(AppSettingsDialog) + self.terminal_emulator_edit.setObjectName("terminal_emulator_edit") + self.gridLayout.addWidget(self.terminal_emulator_edit, 1, 1, 1, 1) + self.label_3 = QtWidgets.QLabel(AppSettingsDialog) + self.label_3.setObjectName("label_3") + self.gridLayout.addWidget(self.label_3, 2, 0, 1, 1) + self.keep_changes_checkbox = QtWidgets.QCheckBox(AppSettingsDialog) + self.keep_changes_checkbox.setText("") + self.keep_changes_checkbox.setObjectName("keep_changes_checkbox") + self.gridLayout.addWidget(self.keep_changes_checkbox, 2, 1, 1, 1) + self.buttonBox = QtWidgets.QDialogButtonBox(AppSettingsDialog) + self.buttonBox.setOrientation(QtCore.Qt.Horizontal) + self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) + self.buttonBox.setObjectName("buttonBox") + self.gridLayout.addWidget(self.buttonBox, 3, 0, 1, 2) + + self.retranslateUi(AppSettingsDialog) + self.buttonBox.accepted.connect(AppSettingsDialog.accept) + self.buttonBox.rejected.connect(AppSettingsDialog.reject) + QtCore.QMetaObject.connectSlotsByName(AppSettingsDialog) + + def retranslateUi(self, AppSettingsDialog): + _translate = QtCore.QCoreApplication.translate + AppSettingsDialog.setWindowTitle(_translate("AppSettingsDialog", "Settings")) + self.label.setText(_translate("AppSettingsDialog", "Text editor")) + self.label_2.setText(_translate("AppSettingsDialog", "Terminal Emulator")) + self.label_3.setText(_translate("AppSettingsDialog", "Keep changes on exit")) diff --git a/sw/supervision/python/generated/ui_build.py b/sw/supervision/python/generated/ui_build.py new file mode 100644 index 0000000000..b2d0095f24 --- /dev/null +++ b/sw/supervision/python/generated/ui_build.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ui/build.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_Build(object): + def setupUi(self, Build): + Build.setObjectName("Build") + Build.resize(437, 87) + self.horizontalLayout = QtWidgets.QHBoxLayout(Build) + self.horizontalLayout.setObjectName("horizontalLayout") + self.groupBox = QtWidgets.QGroupBox(Build) + self.groupBox.setObjectName("groupBox") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.groupBox) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.label_14 = QtWidgets.QLabel(self.groupBox) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_14.sizePolicy().hasHeightForWidth()) + self.label_14.setSizePolicy(sizePolicy) + self.label_14.setObjectName("label_14") + self.horizontalLayout_2.addWidget(self.label_14) + self.target_combo = QtWidgets.QComboBox(self.groupBox) + self.target_combo.setCurrentText("") + self.target_combo.setDuplicatesEnabled(False) + self.target_combo.setObjectName("target_combo") + self.horizontalLayout_2.addWidget(self.target_combo) + self.clean_button = QtWidgets.QToolButton(self.groupBox) + icon = QtGui.QIcon.fromTheme("edit-clear") + self.clean_button.setIcon(icon) + self.clean_button.setObjectName("clean_button") + self.horizontalLayout_2.addWidget(self.clean_button) + self.build_button = QtWidgets.QToolButton(self.groupBox) + icon = QtGui.QIcon.fromTheme("system-run") + self.build_button.setIcon(icon) + self.build_button.setToolButtonStyle(QtCore.Qt.ToolButtonIconOnly) + self.build_button.setObjectName("build_button") + self.horizontalLayout_2.addWidget(self.build_button) + self.print_config_checkbox = QtWidgets.QCheckBox(self.groupBox) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.print_config_checkbox.sizePolicy().hasHeightForWidth()) + self.print_config_checkbox.setSizePolicy(sizePolicy) + self.print_config_checkbox.setText("") + self.print_config_checkbox.setObjectName("print_config_checkbox") + self.horizontalLayout_2.addWidget(self.print_config_checkbox) + self.horizontalLayout.addWidget(self.groupBox) + self.groupBox_2 = QtWidgets.QGroupBox(Build) + self.groupBox_2.setObjectName("groupBox_2") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.groupBox_2) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.label_15 = QtWidgets.QLabel(self.groupBox_2) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Preferred) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_15.sizePolicy().hasHeightForWidth()) + self.label_15.setSizePolicy(sizePolicy) + self.label_15.setObjectName("label_15") + self.horizontalLayout_3.addWidget(self.label_15) + self.device_combo = QtWidgets.QComboBox(self.groupBox_2) + self.device_combo.setObjectName("device_combo") + self.horizontalLayout_3.addWidget(self.device_combo) + self.flash_button = QtWidgets.QToolButton(self.groupBox_2) + icon = QtGui.QIcon.fromTheme("emblem-downloads") + self.flash_button.setIcon(icon) + self.flash_button.setObjectName("flash_button") + self.horizontalLayout_3.addWidget(self.flash_button) + self.horizontalLayout.addWidget(self.groupBox_2) + + self.retranslateUi(Build) + QtCore.QMetaObject.connectSlotsByName(Build) + + def retranslateUi(self, Build): + _translate = QtCore.QCoreApplication.translate + Build.setWindowTitle(_translate("Build", "Form")) + self.groupBox.setTitle(_translate("Build", "Build")) + self.label_14.setText(_translate("Build", "Target")) + self.clean_button.setToolTip(_translate("Build", "Clean")) + self.clean_button.setText(_translate("Build", "...")) + self.build_button.setToolTip(_translate("Build", "Build")) + self.build_button.setText(_translate("Build", "...")) + self.print_config_checkbox.setToolTip(_translate("Build", "print config at build time")) + self.groupBox_2.setTitle(_translate("Build", "Flash")) + self.label_15.setText(_translate("Build", "Device")) + self.flash_button.setToolTip(_translate("Build", "Upload")) + self.flash_button.setText(_translate("Build", "Flash")) diff --git a/sw/supervision/python/generated/ui_conf_header.py b/sw/supervision/python/generated/ui_conf_header.py new file mode 100644 index 0000000000..b5331f61a4 --- /dev/null +++ b/sw/supervision/python/generated/ui_conf_header.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ui/conf_header.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_ConfHeader(object): + def setupUi(self, ConfHeader): + ConfHeader.setObjectName("ConfHeader") + ConfHeader.resize(664, 192) + self.horizontalLayout = QtWidgets.QHBoxLayout(ConfHeader) + self.horizontalLayout.setObjectName("horizontalLayout") + self.id_spinBox = QtWidgets.QSpinBox(ConfHeader) + self.id_spinBox.setMaximum(255) + self.id_spinBox.setObjectName("id_spinBox") + self.horizontalLayout.addWidget(self.id_spinBox) + self.color_button = QtWidgets.QToolButton(ConfHeader) + self.color_button.setStyleSheet("") + self.color_button.setText("") + self.color_button.setObjectName("color_button") + self.horizontalLayout.addWidget(self.color_button) + self.ac_combo = QtWidgets.QComboBox(ConfHeader) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.ac_combo.sizePolicy().hasHeightForWidth()) + self.ac_combo.setSizePolicy(sizePolicy) + self.ac_combo.setEditable(False) + self.ac_combo.setObjectName("ac_combo") + self.horizontalLayout.addWidget(self.ac_combo) + self.menu_button = QtWidgets.QToolButton(ConfHeader) + self.menu_button.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) + self.menu_button.setText("") + icon = QtGui.QIcon.fromTheme("format-justify-fill") + self.menu_button.setIcon(icon) + self.menu_button.setObjectName("menu_button") + self.horizontalLayout.addWidget(self.menu_button) + self.refresh_button = QtWidgets.QToolButton(ConfHeader) + icon = QtGui.QIcon.fromTheme("view-refresh") + self.refresh_button.setIcon(icon) + self.refresh_button.setObjectName("refresh_button") + self.horizontalLayout.addWidget(self.refresh_button) + self.save_button = QtWidgets.QToolButton(ConfHeader) + icon = QtGui.QIcon.fromTheme("document-save") + self.save_button.setIcon(icon) + self.save_button.setObjectName("save_button") + self.horizontalLayout.addWidget(self.save_button) + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem) + self.label_4 = QtWidgets.QLabel(ConfHeader) + self.label_4.setObjectName("label_4") + self.horizontalLayout.addWidget(self.label_4) + self.set_combo = QtWidgets.QComboBox(ConfHeader) + self.set_combo.setObjectName("set_combo") + self.horizontalLayout.addWidget(self.set_combo) + self.new_ac_action = QtWidgets.QAction(ConfHeader) + icon = QtGui.QIcon.fromTheme("document-new") + self.new_ac_action.setIcon(icon) + self.new_ac_action.setObjectName("new_ac_action") + self.remove_ac_action = QtWidgets.QAction(ConfHeader) + icon = QtGui.QIcon.fromTheme("edit-delete") + self.remove_ac_action.setIcon(icon) + self.remove_ac_action.setObjectName("remove_ac_action") + self.duplicate_action = QtWidgets.QAction(ConfHeader) + icon = QtGui.QIcon.fromTheme("edit-copy") + self.duplicate_action.setIcon(icon) + self.duplicate_action.setObjectName("duplicate_action") + self.rename_action = QtWidgets.QAction(ConfHeader) + icon = QtGui.QIcon.fromTheme("format-text-italic") + self.rename_action.setIcon(icon) + self.rename_action.setObjectName("rename_action") + + self.retranslateUi(ConfHeader) + self.menu_button.clicked.connect(self.menu_button.showMenu) + QtCore.QMetaObject.connectSlotsByName(ConfHeader) + + def retranslateUi(self, ConfHeader): + _translate = QtCore.QCoreApplication.translate + ConfHeader.setWindowTitle(_translate("ConfHeader", "Form")) + self.refresh_button.setToolTip(_translate("ConfHeader", "refresh Aircraft")) + self.refresh_button.setText(_translate("ConfHeader", "...")) + self.save_button.setToolTip(_translate("ConfHeader", "save conf")) + self.save_button.setText(_translate("ConfHeader", "...")) + self.label_4.setText(_translate("ConfHeader", "Set")) + self.new_ac_action.setText(_translate("ConfHeader", "New AC")) + self.remove_ac_action.setText(_translate("ConfHeader", "Remove")) + self.duplicate_action.setText(_translate("ConfHeader", "Duplicate")) + self.rename_action.setText(_translate("ConfHeader", "Rename")) diff --git a/sw/supervision/python/generated/ui_conf_item.py b/sw/supervision/python/generated/ui_conf_item.py new file mode 100644 index 0000000000..0e8b83985e --- /dev/null +++ b/sw/supervision/python/generated/ui_conf_item.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ui/conf_item.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_FileConf(object): + def setupUi(self, FileConf): + FileConf.setObjectName("FileConf") + FileConf.resize(306, 129) + self.verticalLayout = QtWidgets.QVBoxLayout(FileConf) + self.verticalLayout.setObjectName("verticalLayout") + self.horizontalLayout_5 = QtWidgets.QHBoxLayout() + self.horizontalLayout_5.setObjectName("horizontalLayout_5") + self.title_label = QtWidgets.QLabel(FileConf) + self.title_label.setStyleSheet("font-weight: bold;") + self.title_label.setObjectName("title_label") + self.horizontalLayout_5.addWidget(self.title_label) + self.edit_alt_button = QtWidgets.QPushButton(FileConf) + self.edit_alt_button.setObjectName("edit_alt_button") + self.horizontalLayout_5.addWidget(self.edit_alt_button) + self.edit_button = QtWidgets.QToolButton(FileConf) + self.edit_button.setObjectName("edit_button") + self.horizontalLayout_5.addWidget(self.edit_button) + self.select_button = QtWidgets.QToolButton(FileConf) + self.select_button.setObjectName("select_button") + self.horizontalLayout_5.addWidget(self.select_button) + self.verticalLayout.addLayout(self.horizontalLayout_5) + self.path_label = QtWidgets.QLabel(FileConf) + self.path_label.setWordWrap(True) + self.path_label.setOpenExternalLinks(False) + self.path_label.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByKeyboard|QtCore.Qt.TextSelectableByMouse) + self.path_label.setObjectName("path_label") + self.verticalLayout.addWidget(self.path_label) + + self.retranslateUi(FileConf) + QtCore.QMetaObject.connectSlotsByName(FileConf) + + def retranslateUi(self, FileConf): + _translate = QtCore.QCoreApplication.translate + FileConf.setWindowTitle(_translate("FileConf", "Form")) + self.title_label.setText(_translate("FileConf", "Flight Plan")) + self.edit_alt_button.setText(_translate("FileConf", "Edit alt")) + self.edit_button.setText(_translate("FileConf", "Edit")) + self.select_button.setText(_translate("FileConf", "Select")) + self.path_label.setText(_translate("FileConf", "/path/to/file.xml")) diff --git a/sw/supervision/python/generated/ui_configuration_panel.py b/sw/supervision/python/generated/ui_configuration_panel.py new file mode 100644 index 0000000000..494017000e --- /dev/null +++ b/sw/supervision/python/generated/ui_configuration_panel.py @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ui/configuration_panel.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_ConfigurationPanel(object): + def setupUi(self, ConfigurationPanel): + ConfigurationPanel.setObjectName("ConfigurationPanel") + 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") + self.conf_widget = ConfWidget(self.splitter) + self.conf_widget.setObjectName("conf_widget") + self.widget_2 = QtWidgets.QWidget(self.splitter) + self.widget_2.setObjectName("widget_2") + self.verticalLayout = QtWidgets.QVBoxLayout(self.widget_2) + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setObjectName("verticalLayout") + self.build_widget = BuildWidget(self.widget_2) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.build_widget.sizePolicy().hasHeightForWidth()) + self.build_widget.setSizePolicy(sizePolicy) + self.build_widget.setMinimumSize(QtCore.QSize(0, 0)) + self.build_widget.setObjectName("build_widget") + self.verticalLayout.addWidget(self.build_widget) + self.programs_widget = QtWidgets.QFrame(self.widget_2) + self.programs_widget.setFrameShape(QtWidgets.QFrame.StyledPanel) + self.programs_widget.setFrameShadow(QtWidgets.QFrame.Raised) + self.programs_widget.setObjectName("programs_widget") + self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.programs_widget) + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.verticalLayout.addWidget(self.programs_widget) + self.console_widget = ConsoleWidget(self.widget_2) + self.console_widget.setObjectName("console_widget") + self.verticalLayout.addWidget(self.console_widget) + self.verticalLayout.setStretch(2, 1) + self.verticalLayout_2.addWidget(self.splitter) + self.save_conf_action = QtWidgets.QAction(ConfigurationPanel) + self.save_conf_action.setObjectName("save_conf_action") + + self.retranslateUi(ConfigurationPanel) + QtCore.QMetaObject.connectSlotsByName(ConfigurationPanel) + + def retranslateUi(self, ConfigurationPanel): + _translate = QtCore.QCoreApplication.translate + ConfigurationPanel.setWindowTitle(_translate("ConfigurationPanel", "Form")) + self.save_conf_action.setText(_translate("ConfigurationPanel", "Save configuration")) + self.save_conf_action.setShortcut(_translate("ConfigurationPanel", "Ctrl+S")) +from build_widget import BuildWidget +from conf_widget import ConfWidget +from console_widget import ConsoleWidget +from header_widget import HeaderWidget diff --git a/sw/supervision/python/generated/ui_console.py b/sw/supervision/python/generated/ui_console.py new file mode 100644 index 0000000000..2ba3261794 --- /dev/null +++ b/sw/supervision/python/generated/ui_console.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ui/console.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_Console(object): + def setupUi(self, Console): + Console.setObjectName("Console") + Console.resize(709, 647) + self.verticalLayout_2 = QtWidgets.QVBoxLayout(Console) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.splitter = QtWidgets.QSplitter(Console) + self.splitter.setOrientation(QtCore.Qt.Horizontal) + self.splitter.setObjectName("splitter") + self.console_textedit = QtWidgets.QTextEdit(self.splitter) + self.console_textedit.setReadOnly(True) + self.console_textedit.setObjectName("console_textedit") + self.filter_widget = QtWidgets.QWidget(self.splitter) + self.filter_widget.setObjectName("filter_widget") + self.verticalLayout = QtWidgets.QVBoxLayout(self.filter_widget) + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setObjectName("verticalLayout") + self.label = QtWidgets.QLabel(self.filter_widget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth()) + self.label.setSizePolicy(sizePolicy) + self.label.setObjectName("label") + self.verticalLayout.addWidget(self.label) + self.programs_checkbox = QtWidgets.QCheckBox(self.filter_widget) + self.programs_checkbox.setChecked(False) + self.programs_checkbox.setObjectName("programs_checkbox") + self.verticalLayout.addWidget(self.programs_checkbox) + self.scrollArea = QtWidgets.QScrollArea(self.filter_widget) + self.scrollArea.setWidgetResizable(True) + self.scrollArea.setObjectName("scrollArea") + self.programs_widget = QtWidgets.QWidget() + self.programs_widget.setGeometry(QtCore.QRect(0, 0, 382, 524)) + self.programs_widget.setObjectName("programs_widget") + self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.programs_widget) + self.verticalLayout_4.setObjectName("verticalLayout_4") + spacerItem = QtWidgets.QSpacerItem(1, 167, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_4.addItem(spacerItem) + self.scrollArea.setWidget(self.programs_widget) + self.verticalLayout.addWidget(self.scrollArea) + self.verticalLayout_2.addWidget(self.splitter) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.label_3 = QtWidgets.QLabel(Console) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.label_3.sizePolicy().hasHeightForWidth()) + self.label_3.setSizePolicy(sizePolicy) + self.label_3.setObjectName("label_3") + self.horizontalLayout_2.addWidget(self.label_3) + self.log_level_slider = QtWidgets.QSlider(Console) + self.log_level_slider.setMaximumSize(QtCore.QSize(100, 16777215)) + self.log_level_slider.setMaximum(3) + self.log_level_slider.setPageStep(1) + self.log_level_slider.setProperty("value", 3) + self.log_level_slider.setOrientation(QtCore.Qt.Horizontal) + self.log_level_slider.setTickPosition(QtWidgets.QSlider.TicksBelow) + self.log_level_slider.setTickInterval(1) + self.log_level_slider.setObjectName("log_level_slider") + self.horizontalLayout_2.addWidget(self.log_level_slider) + self.log_level_label = QtWidgets.QLabel(Console) + self.log_level_label.setObjectName("log_level_label") + self.horizontalLayout_2.addWidget(self.log_level_label) + spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_2.addItem(spacerItem1) + self.clear_button = QtWidgets.QPushButton(Console) + icon = QtGui.QIcon.fromTheme("edit-clear") + self.clear_button.setIcon(icon) + self.clear_button.setObjectName("clear_button") + self.horizontalLayout_2.addWidget(self.clear_button) + self.horizontalLayout_2.setStretch(1, 1) + self.horizontalLayout_2.setStretch(3, 2) + self.verticalLayout_2.addLayout(self.horizontalLayout_2) + self.verticalLayout_2.setStretch(0, 1) + + self.retranslateUi(Console) + QtCore.QMetaObject.connectSlotsByName(Console) + + def retranslateUi(self, Console): + _translate = QtCore.QCoreApplication.translate + Console.setWindowTitle(_translate("Console", "Form")) + self.label.setText(_translate("Console", "Filters")) + self.programs_checkbox.setText(_translate("Console", "Programs")) + self.label_3.setText(_translate("Console", "Log level:")) + self.log_level_label.setText(_translate("Console", "All")) + self.clear_button.setText(_translate("Console", "Clear console")) diff --git a/sw/supervision/python/generated/ui_new_ac_dialog.py b/sw/supervision/python/generated/ui_new_ac_dialog.py new file mode 100644 index 0000000000..d120aef70f --- /dev/null +++ b/sw/supervision/python/generated/ui_new_ac_dialog.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ui/new_ac_dialog.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_Dialog(object): + def setupUi(self, Dialog): + Dialog.setObjectName("Dialog") + Dialog.resize(187, 106) + self.gridLayout = QtWidgets.QGridLayout(Dialog) + self.gridLayout.setObjectName("gridLayout") + self.label = QtWidgets.QLabel(Dialog) + self.label.setObjectName("label") + self.gridLayout.addWidget(self.label, 0, 0, 1, 1) + self.name_edit = QtWidgets.QLineEdit(Dialog) + 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.setObjectName("label_2") + self.gridLayout.addWidget(self.label_2, 1, 0, 1, 1) + self.id_spinbox = QtWidgets.QSpinBox(Dialog) + 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.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) + + def retranslateUi(self, Dialog): + _translate = QtCore.QCoreApplication.translate + Dialog.setWindowTitle(_translate("Dialog", "Dialog")) + self.label.setText(_translate("Dialog", "Name")) + self.label_2.setText(_translate("Dialog", "ID")) diff --git a/sw/supervision/python/generated/ui_operation_panel.py b/sw/supervision/python/generated/ui_operation_panel.py new file mode 100644 index 0000000000..f83f320a00 --- /dev/null +++ b/sw/supervision/python/generated/ui_operation_panel.py @@ -0,0 +1,35 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ui/operation_panel.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_OperationPanel(object): + def setupUi(self, OperationPanel): + OperationPanel.setObjectName("OperationPanel") + OperationPanel.resize(400, 300) + self.verticalLayout = QtWidgets.QVBoxLayout(OperationPanel) + self.verticalLayout.setObjectName("verticalLayout") + self.splitter = QtWidgets.QSplitter(OperationPanel) + self.splitter.setOrientation(QtCore.Qt.Vertical) + self.splitter.setObjectName("splitter") + self.session = SessionWidget(self.splitter) + self.session.setObjectName("session") + self.console = ConsoleWidget(self.splitter) + self.console.setObjectName("console") + self.verticalLayout.addWidget(self.splitter) + + self.retranslateUi(OperationPanel) + QtCore.QMetaObject.connectSlotsByName(OperationPanel) + + def retranslateUi(self, OperationPanel): + _translate = QtCore.QCoreApplication.translate + OperationPanel.setWindowTitle(_translate("OperationPanel", "Form")) +from console_widget import ConsoleWidget +from session_widget import SessionWidget diff --git a/sw/supervision/python/generated/ui_program.py b/sw/supervision/python/generated/ui_program.py new file mode 100644 index 0000000000..c685c856ca --- /dev/null +++ b/sw/supervision/python/generated/ui_program.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ui/program.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_Program(object): + def setupUi(self, Program): + Program.setObjectName("Program") + Program.resize(374, 25) + self.horizontalLayout = QtWidgets.QHBoxLayout(Program) + self.horizontalLayout.setContentsMargins(-1, 0, -1, 0) + self.horizontalLayout.setObjectName("horizontalLayout") + self.icon_label = QtWidgets.QLabel(Program) + self.icon_label.setObjectName("icon_label") + self.horizontalLayout.addWidget(self.icon_label) + self.program_lineedit = QtWidgets.QLineEdit(Program) + self.program_lineedit.setObjectName("program_lineedit") + self.horizontalLayout.addWidget(self.program_lineedit) + self.line = QtWidgets.QFrame(Program) + self.line.setFrameShape(QtWidgets.QFrame.VLine) + self.line.setFrameShadow(QtWidgets.QFrame.Sunken) + self.line.setObjectName("line") + self.horizontalLayout.addWidget(self.line) + self.run_button = QtWidgets.QToolButton(Program) + icon = QtGui.QIcon.fromTheme("media-playback-stop") + self.run_button.setIcon(icon) + self.run_button.setObjectName("run_button") + self.horizontalLayout.addWidget(self.run_button) + self.remove_button = QtWidgets.QToolButton(Program) + icon = QtGui.QIcon.fromTheme("list-remove") + self.remove_button.setIcon(icon) + self.remove_button.setObjectName("remove_button") + self.horizontalLayout.addWidget(self.remove_button) + + self.retranslateUi(Program) + QtCore.QMetaObject.connectSlotsByName(Program) + + def retranslateUi(self, Program): + _translate = QtCore.QCoreApplication.translate + Program.setWindowTitle(_translate("Program", "Form")) + self.icon_label.setText(_translate("Program", "...")) + self.run_button.setText(_translate("Program", "...")) + self.remove_button.setText(_translate("Program", "...")) diff --git a/sw/supervision/python/generated/ui_session.py b/sw/supervision/python/generated/ui_session.py new file mode 100644 index 0000000000..09ab39345b --- /dev/null +++ b/sw/supervision/python/generated/ui_session.py @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ui/session.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_Session(object): + def setupUi(self, Session): + Session.setObjectName("Session") + Session.resize(400, 300) + self.verticalLayout = QtWidgets.QVBoxLayout(Session) + self.verticalLayout.setObjectName("verticalLayout") + self.label_2 = QtWidgets.QLabel(Session) + self.label_2.setObjectName("label_2") + self.verticalLayout.addWidget(self.label_2) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.sessions_combo = QtWidgets.QComboBox(Session) + self.sessions_combo.setObjectName("sessions_combo") + self.horizontalLayout_2.addWidget(self.sessions_combo) + self.start_session_button = QtWidgets.QToolButton(Session) + icon = QtGui.QIcon.fromTheme("media-playback-start") + self.start_session_button.setIcon(icon) + self.start_session_button.setObjectName("start_session_button") + self.horizontalLayout_2.addWidget(self.start_session_button) + self.menu_button = QtWidgets.QToolButton(Session) + self.menu_button.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu) + icon = QtGui.QIcon.fromTheme("format-justify-fill") + self.menu_button.setIcon(icon) + self.menu_button.setObjectName("menu_button") + self.horizontalLayout_2.addWidget(self.menu_button) + self.verticalLayout.addLayout(self.horizontalLayout_2) + self.favorite_tools = QtWidgets.QWidget(Session) + self.favorite_tools.setObjectName("favorite_tools") + self.verticalLayout.addWidget(self.favorite_tools) + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.label = QtWidgets.QLabel(Session) + self.label.setObjectName("label") + self.horizontalLayout.addWidget(self.label) + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem) + self.add_tool_button = QtWidgets.QToolButton(Session) + icon = QtGui.QIcon.fromTheme("list-add") + self.add_tool_button.setIcon(icon) + self.add_tool_button.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + self.add_tool_button.setAutoRaise(False) + self.add_tool_button.setArrowType(QtCore.Qt.NoArrow) + self.add_tool_button.setObjectName("add_tool_button") + self.horizontalLayout.addWidget(self.add_tool_button) + spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem1) + self.line = QtWidgets.QFrame(Session) + self.line.setFrameShape(QtWidgets.QFrame.VLine) + self.line.setFrameShadow(QtWidgets.QFrame.Sunken) + self.line.setObjectName("line") + self.horizontalLayout.addWidget(self.line) + self.startall_button = QtWidgets.QToolButton(Session) + icon = QtGui.QIcon.fromTheme("media-playback-start") + self.startall_button.setIcon(icon) + self.startall_button.setObjectName("startall_button") + self.horizontalLayout.addWidget(self.startall_button) + self.stopall_button = QtWidgets.QToolButton(Session) + icon = QtGui.QIcon.fromTheme("media-playback-stop") + self.stopall_button.setIcon(icon) + self.stopall_button.setObjectName("stopall_button") + self.horizontalLayout.addWidget(self.stopall_button) + self.removeall_button = QtWidgets.QToolButton(Session) + icon = QtGui.QIcon.fromTheme("list-remove") + self.removeall_button.setIcon(icon) + self.removeall_button.setObjectName("removeall_button") + self.horizontalLayout.addWidget(self.removeall_button) + self.verticalLayout.addLayout(self.horizontalLayout) + self.scrollArea = QtWidgets.QScrollArea(Session) + self.scrollArea.setWidgetResizable(True) + self.scrollArea.setObjectName("scrollArea") + self.programs_widget = QtWidgets.QWidget() + self.programs_widget.setGeometry(QtCore.QRect(0, 0, 380, 176)) + self.programs_widget.setObjectName("programs_widget") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.programs_widget) + self.verticalLayout_2.setObjectName("verticalLayout_2") + spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) + self.verticalLayout_2.addItem(spacerItem2) + self.scrollArea.setWidget(self.programs_widget) + self.verticalLayout.addWidget(self.scrollArea) + self.save_session_action = QtWidgets.QAction(Session) + icon = QtGui.QIcon.fromTheme("document-save") + self.save_session_action.setIcon(icon) + self.save_session_action.setObjectName("save_session_action") + self.save_as_action = QtWidgets.QAction(Session) + icon = QtGui.QIcon.fromTheme("edit-copy") + self.save_as_action.setIcon(icon) + self.save_as_action.setObjectName("save_as_action") + self.rename_session_action = QtWidgets.QAction(Session) + icon = QtGui.QIcon.fromTheme("format-text-italic") + self.rename_session_action.setIcon(icon) + self.rename_session_action.setObjectName("rename_session_action") + self.remove_session_action = QtWidgets.QAction(Session) + icon = QtGui.QIcon.fromTheme("edit-delete") + self.remove_session_action.setIcon(icon) + self.remove_session_action.setObjectName("remove_session_action") + + self.retranslateUi(Session) + self.menu_button.clicked.connect(self.menu_button.showMenu) + QtCore.QMetaObject.connectSlotsByName(Session) + + def retranslateUi(self, Session): + _translate = QtCore.QCoreApplication.translate + Session.setWindowTitle(_translate("Session", "Form")) + self.label_2.setText(_translate("Session", "Session")) + self.start_session_button.setToolTip(_translate("Session", "Start Session")) + self.start_session_button.setText(_translate("Session", "...")) + self.menu_button.setText(_translate("Session", "...")) + self.label.setText(_translate("Session", "Programs")) + self.add_tool_button.setToolTip(_translate("Session", "Add Tool")) + self.add_tool_button.setText(_translate("Session", "Add tool")) + self.startall_button.setToolTip(_translate("Session", "Start All")) + self.startall_button.setText(_translate("Session", "...")) + self.stopall_button.setToolTip(_translate("Session", "Stop All")) + self.stopall_button.setText(_translate("Session", "...")) + self.removeall_button.setToolTip(_translate("Session", "Remove All")) + self.removeall_button.setText(_translate("Session", "...")) + self.save_session_action.setText(_translate("Session", "Save session")) + self.save_as_action.setText(_translate("Session", "Save as...")) + self.save_as_action.setToolTip(_translate("Session", "Save session as...")) + self.rename_session_action.setText(_translate("Session", "Rename session")) + self.remove_session_action.setText(_translate("Session", "Remove session")) diff --git a/sw/supervision/python/generated/ui_tools_list.py b/sw/supervision/python/generated/ui_tools_list.py new file mode 100644 index 0000000000..1ac6019775 --- /dev/null +++ b/sw/supervision/python/generated/ui_tools_list.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'ui/tools_list.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_ToolsList(object): + def setupUi(self, ToolsList): + ToolsList.setObjectName("ToolsList") + ToolsList.resize(328, 357) + self.verticalLayout = QtWidgets.QVBoxLayout(ToolsList) + self.verticalLayout.setObjectName("verticalLayout") + self.filter_lineedit = QtWidgets.QLineEdit(ToolsList) + self.filter_lineedit.setClearButtonEnabled(True) + self.filter_lineedit.setObjectName("filter_lineedit") + self.verticalLayout.addWidget(self.filter_lineedit) + self.scrollArea = QtWidgets.QScrollArea(ToolsList) + self.scrollArea.setWidgetResizable(True) + self.scrollArea.setObjectName("scrollArea") + self.content_widget = QtWidgets.QWidget() + self.content_widget.setGeometry(QtCore.QRect(0, 0, 308, 306)) + self.content_widget.setObjectName("content_widget") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.content_widget) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.scrollArea.setWidget(self.content_widget) + self.verticalLayout.addWidget(self.scrollArea) + + self.retranslateUi(ToolsList) + QtCore.QMetaObject.connectSlotsByName(ToolsList) + + def retranslateUi(self, ToolsList): + _translate = QtCore.QCoreApplication.translate + ToolsList.setWindowTitle(_translate("ToolsList", "Form")) diff --git a/sw/supervision/python/header_widget.py b/sw/supervision/python/header_widget.py new file mode 100644 index 0000000000..93b99c80a6 --- /dev/null +++ b/sw/supervision/python/header_widget.py @@ -0,0 +1,55 @@ +# Copyright (C) 2008-2022 The Paparazzi Team +# released under GNU GPLv2 or later. See COPYING file. +from PyQt5.QtWidgets import * +from PyQt5 import QtCore, QtGui, QtWidgets +from generated.ui_conf_header import Ui_ConfHeader +import conf + + +class HeaderWidget(QWidget, Ui_ConfHeader): + + set_changed = QtCore.pyqtSignal(str) + ac_changed = QtCore.pyqtSignal(str) + id_changed = QtCore.pyqtSignal(int) + + def __init__(self, parent=None): + QWidget.__init__(self, parent=parent) + self.setupUi(self) + 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) + + def set_sets(self, sets, conf_init: str = None): + self.set_combo.addItems(sets) + if conf_init in sets: + self.set_combo.setCurrentText(conf_init) + + def set_acs(self, acs): + self.ac_combo.clear() + self.ac_combo.addItems(acs) + + def set_ac(self, ac: conf.Aircraft): + self.id_spinBox.setValue(ac.ac_id) + self.set_color(ac.get_color()) + + def remove_current(self): + i = self.ac_combo.currentIndex() + self.ac_combo.removeItem(i) + + 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 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)) diff --git a/sw/supervision/python/hmi.py b/sw/supervision/python/hmi.py deleted file mode 100644 index dbf41fdf54..0000000000 --- a/sw/supervision/python/hmi.py +++ /dev/null @@ -1,1781 +0,0 @@ -# Paparazzi center utilities -# -# Copyright (C) 2016 ENAC, Florian BITARD (intern student) -# -# This file is part of paparazzi. -# -# paparazzi is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# paparazzi is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with paparazzi; see the file COPYING. If not, write to -# the Free Software Foundation, 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -############################################################################### -# [Imports] - -import ui.main_window as ui -import dialogs as dial -import lib.console as cs -import lib.database as db -import lib.environment as env -import lib.gui as gui -import parser -import processes as proc - -import PyQt5.QtCore as Core -import PyQt5.QtWidgets as Widgets -import functools -import logging -import os -import sys -import re -import shutil - -############################################################################### -# [Constants] - -DEFAULT_TOOL_ICON = "default_tool_icon.svg" - -LOGGER = logging.getLogger("[HMI]") - -CONF_PATH = env.PAPARAZZI_CONF -SET_SYMBOLIC_LINK = CONF_PATH + "/conf.xml" -CONF_XML_COPY = CONF_PATH + "/conf_copy.xml" - -OK_QPIXMAP = "icons/dialog-apply.svg" -ERROR_QPIXMAP = "icons/dialog-error.svg" -START_ICON = "icons/media-playback-start.svg" -STOP_ICON = "icons/process-stop.svg" -CHANGED_ICON = "icons/dialog-warning-symbolic.svg" -ICONS_TOOLS_PATH = "data/pictures/tools_icons/" - -UNKNOWN_VALUE = "---" - -PROGRESS_BAR_LINE = " " -PROGRESS_BAR_CURSOR = "***" -PROGRESS_BAR_SPEED = 10 - - -############################################################################### -# [Functions] System functions - -def control_cwd(): - """ - -> Get the current directory path and log it. - """ - cwd = os.getcwd() - LOGGER.info("Current directory : '%s'.", cwd) - return cwd - - -def point_symbol_link_to(set_file): - """ - :param set_file: - -> Make the 'conf.xml' symbolic file point to the given 'set_file'. - """ - if os.path.exists(SET_SYMBOLIC_LINK): - os.remove(SET_SYMBOLIC_LINK) - os.symlink(set_file, SET_SYMBOLIC_LINK) - LOGGER.debug("'%s' -> '%s'.", SET_SYMBOLIC_LINK, set_file) - - -def init_conf_xml_path(): - """ - -> Create a copy of the conf.xml file if it's an existing and real file. - -> Make the conf.xml file point to the copy created. - """ - if os.path.exists(SET_SYMBOLIC_LINK) \ - and not os.path.islink(SET_SYMBOLIC_LINK): - shutil.copy(SET_SYMBOLIC_LINK, CONF_XML_COPY) - point_symbol_link_to(CONF_XML_COPY) - - -############################################################################### -# [Functions] Widgets management functions - -def set_widgets_visibility(widgets, set_visible_bool): - """ - :param widgets: - :param set_visible_bool: - -> Set a list of widgets visible or not together. - """ - for widget in widgets: - widget.setVisible(set_visible_bool) - - -def set_widgets_availability(widgets, set_available_bool): - """ - :param widgets: - :param set_available_bool: - -> Set a list of widgets available or not together. - """ - for widget in widgets: - widget.setEnabled(set_available_bool) - - -def set_items_icons(list_widget_items, qicon): - """ - :param list_widget_items: - :param qicon: - -> Put the same QIcon to items of a QListWidget. - """ - for item in list_widget_items: - item.setIcon(qicon) - - -def clear_widgets(widgets): - """ - :param widgets: - -> Clear each widget in a list of widgets. - """ - for widget in widgets: - widget.clear() - - -def clear_list_widgets_selection(widgets): - """ - :param widgets: - -> Clear the selection of each widget in a list of QListWidget widgets. - """ - for widget in widgets: - widget.clearSelection() - widget.clearFocus() - - -############################################################################### -# [Hmi class] - -class Hmi(Widgets.QMainWindow): - """Class to manage the main HMI behavior.""" - def __init__(self): - """ - -> Creation of a MainWindow object generated by the command : - 'pyuic5 *.ui -o *.py' from the PyQt5 HMI designed under QtDesigner. - -> Creation of Dialog objects used from the main HMI. - -> Declaration of widgets groups for code factorization. - -> Declaration of HMI private attributes for its own methods. - """ - super(Hmi, self).__init__() - - self.ui = ui.Ui_MainWindow() - self.ui.setupUi(self) - - # Existing popups : - self.settings = None - self.data_changed_popup = None - self.credits_popup = None - self.tutorial_popup = None - - # Shortcuts for lists of widgets : - self.change_config_widgets = [self.ui.current_airframes, - self.ui.current_settings, - self.ui.current_flight_plan, - self.ui.current_radio, - self.ui.current_telemetry] - self.display_config_widgets = [self.ui.airframes_overview, - self.ui.settings_overview, - self.ui.flight_plan_overview, - self.ui.radio_overview, - self.ui.telemetry_overview, - self.ui.airframes_overview_2, - self.ui.settings_overview_2, - self.ui.flight_plan_overview_2, - self.ui.radio_overview_2, - self.ui.telemetry_overview_2] - self.flight_plan_buttons = [self.ui.open_gui, - self.ui.select_kml] - self.session_widgets = [self.ui.session, - self.ui.session_overview_1, - self.ui.session_overview_2] - self.display_programs_widgets = [self.ui.programs_overview_1, - self.ui.programs_overview_2] - self.target_widgets = [self.ui.quick_target, self.ui.target] - self.messages_level_widgets = [self.ui.important, - self.ui.custom, self.ui.all] - self.log_filters_widgets = [self.ui.display_default, - self.ui.display_info, - self.ui.display_warnings, - self.ui.display_errors] - self.messages_nb_widgets = [self.ui.info_nb, self.ui.warnings_nb, - self.ui.errors_nb] - self.start_all_buttons = [self.ui.start_all_button, - self.ui.quick_restart, - self.ui.quick_restart_3] - self.kill_all_buttons = [self.ui.kill_all_button, self.ui.quick_kill, - self.ui.quick_kill_2] - - # Icons used in widgets (can't be constants because qpixmap objects - # must be declared into a QApplication) : - self.ok_qpixmap = gui.generate_qpixmap(OK_QPIXMAP) - self.error_qpixmap = gui.generate_qpixmap(ERROR_QPIXMAP) - self.start_qicon = gui.generate_qicon(START_ICON) - self.stop_qicon = gui.generate_qicon(STOP_ICON) - self.changed_qicon = gui.generate_qicon(CHANGED_ICON) - - # Progress bar initialization : - self.max_result_field_size = self.ui.build_result.width() // 10 - self.progress_bar_to_left = False - - # HMI parameters initialization (could be set in settings menu) : - self.dev_mode = False - - self.current_log_filter = None - - self.data = None - self.current_set = None - self.current_config = None - self.current_item = None - - self.current_target = None - self.simulation_targets_names = ['nps', 'sim'] - self.change_target_bool = True - - self.current_device = None - self.current_session = None - self.current_program = None - self.current_option = None - - self.run_version = None - self.build_version = None - - self.configurations_changed = {} - self.sessions_changed = {} - - self.build = None - self.build_running = False - self.clean = None - self.clean_running = False - self.upload = None - self.upload_running = False - - self.running_programs = {} - - self.console = cs.Console(self.ui.console) - - # Logger output redirected to a special stream to allow an integrated - # console display (and logger level could be set in settings menu) : - self.logger_stream = proc.LoggerStream() - self.logger_stream.logger_log_sent.connect(self.write_log_in_console) - logging.basicConfig(level=logging.INFO, stream=self.logger_stream) - -############################################################################### -# [Hmi methods] Init HMI methods - - def init_hmi_data(self): - try: - self.init_hmi_data_core() - except: - " if something goes wrong, delete cache and load again (to be improved)" - LOGGER.error("ERROR while load HMI cache" - "Original message : '%s'.", sys.exc_info()[0]) - print("HMI error in cache, load default instead") - parser.delete_cache() - self.init_hmi_data_core() - - # Run and build Paparazzi versions found by existing program - # './paparazzi_version' and file './var/build_version.txt' : - run_version_cmd = env.RUN_VERSION_EXE - self.run_version = os.popen(run_version_cmd).readline().strip() - build_version_cmd = " ".join(["cat", env.BUILD_VERSION_FILE]) - self.build_version = os.popen(build_version_cmd).readline().strip() - - def init_hmi_data_core(self): - """ - -> Initialization of a 'Data' object with all necessary data from XML - files found in the 'CONF_PATH' Paparazzi UAV directory. - -> Loading of cache data (last settings used) to restore them. - -> Initialization of main HMI widgets with necessary data found. - """ - init_conf_xml_path() - self.data = parser.Data(CONF_PATH) - - # Cache parameters extracted from the cache dictionary : - last_geometry = self.data.cache[parser.LAST_GEOMETRY].split(" ") - last_x, last_y, last_width, last_height = map(int, last_geometry) - self.setGeometry(last_x, last_y, last_width, last_height) - - last_set_name = self.data.cache[parser.LAST_SET] - self.current_set = self.data.sets[last_set_name] - - point_symbol_link_to(self.current_set.name) - - last_config_name = self.data.cache[parser.LAST_CONFIG] - self.current_config = self.data.configurations[last_config_name] - - last_target_name = self.data.cache[parser.LAST_TARGET] - self.current_target = self.current_config.targets[last_target_name] - - self.ui.upload.setEnabled(self.current_target.name - not in self.simulation_targets_names) - - last_device_name = self.data.cache[parser.LAST_DEVICE] - self.current_device = self.data.devices[last_device_name] - - last_session_name = self.data.cache[parser.LAST_SESSION] - self.current_session = self.data.sessions[last_session_name] - - last_log_filters = self.data.cache[parser.LAST_LOG_FILTERS].split(" ") - last_level = last_log_filters[0] - last_default, last_info, last_warning, last_error =\ - map(int, last_log_filters[1:]) - self.current_log_filter = cs.LogFilter(last_level, - last_default, last_info, - last_warning, last_error) - - - def init_hmi_widgets(self): - """ - -> Initialization of all the HMI widgets content. - -> Initialization of existing popups. - """ - # Update functions used for initialization : - self.update_home_button() - self.update_mode_button() - self.update_versions() - self.update_set_combo() - self.update_config_combo() - self.update_config_items_lists() - self.update_target_combos(self.target_widgets) - self.update_log_filters() - self.change_messages_level() - self.update_device_combo() - self.update_session_combos() - self.update_programs_list() - self.update_program_options_list() - self.init_tools_menu() - - # Popup initialization : - self.settings = dial.SettingsManager() - self.data_changed_popup = dial.Popup(dial.DATA_CHANGED_POPUP_TYPE) - self.credits_popup = dial.Popup(dial.CREDITS_POPUP_TYPE) - self.tutorial_popup = dial.Popup(dial.TUTORIAL_POPUP_TYPE) - - def init_all_hmi(self): - """ - -> Centralize all initializations before the mainwindow is shown. - """ - control_cwd() - LOGGER.info("HMI init in progress...\n") - print("\nHMI init in progress...") - self.init_hmi_data() - self.init_hmi_widgets() - self.connect_signals() - LOGGER.info("HMI init finished.\n") - print("HMI init finished.\n") - -############################################################################### -# [Hmi methods] Connect signals methods - - def connect_signals(self): - """ - -> Connection of 'triggered' signals from 'QMenu' or 'QAction'. - -> Connection of 'currentIndexChanged' signals from 'QComboBox'. - -> Connection of 'clicked' signals from 'QPushButton'. - """ - ####################################################################### - # Actions in menus - - self.ui.actionQuit_Paparazzi_UAV.triggered.connect(self.close) - - self.ui.actionSetManager.triggered.connect(self.settings.show) - self.ui.actionSave_2.triggered.connect(self.save_current_config) - - self.ui.actionSave_3.triggered.connect(self.save_current_session) - - self.ui.actionFull_screen.triggered.connect(self.fullscreen_view) - self.ui.actionHide_overviews.triggered.connect(self.toggle_overview) - - self.ui.actionAbout_Paparazzi_UAV.triggered.connect( - self.credits_popup.show) - self.ui.actionTutorial.triggered.connect(self.tutorial_popup.show) - - ####################################################################### - # Equipment tab - - for list_widget in self.change_config_widgets: - list_widget.itemSelectionChanged.connect(functools.partial( - self.change_current_item, list_widget)) - self.ui.current_settings.itemClicked.connect( - self.change_setting_check_state) - - self.ui.current_set.currentIndexChanged.connect(self.change_current_set) - self.ui.current_configuration.currentIndexChanged.connect( - self.change_current_config) - - self.ui.remove_item.clicked.connect(self.remove_item_from_config) - self.ui.add_item.clicked.connect(self.open_item_file_chooser) - self.ui.edit.clicked.connect(self.open_gedit) - - self.ui.quick_build.clicked.connect(self.quick_build) - - ####################################################################### - # Build / flash tab - - for combo_widget in self.target_widgets: - combo_widget.currentIndexChanged.connect(functools.partial( - self.change_current_target, combo_widget)) - - for widget in self.log_filters_widgets: - widget.clicked.connect(self.change_sensitivity_filters) - - for widget in self.messages_level_widgets: - widget.clicked.connect(self.change_messages_level) - - self.ui.clean.clicked.connect(self.clean_config) - self.ui.build.clicked.connect(self.build_config) - self.ui.upload.clicked.connect(self.flash_device) - self.ui.show_console.clicked.connect(functools.partial( - self.switch_to_tab, 3)) - - self.ui.device.currentIndexChanged.connect(self.change_current_device) - - ####################################################################### - # Session tab - - for combo_widget in self.session_widgets: - combo_widget.currentIndexChanged.connect(functools.partial( - self.change_current_session, combo_widget)) - - self.ui.programs.itemSelectionChanged.connect( - self.change_current_program) - self.ui.options.itemSelectionChanged.connect( - self.change_current_option) - - self.ui.play_stop_program.clicked.connect(functools.partial( - self.run_program, None)) - for button in self.start_all_buttons: - button.clicked.connect(self.start_all_programs) - for button in self.kill_all_buttons: - button.clicked.connect(self.kill_all_programs) - - self.ui.remove_program.clicked.connect( - self.remove_program_from_session) - self.ui.remove_option.clicked.connect(self.remove_option_from_program) - self.ui.add_option.clicked.connect(self.add_option_to_program) - self.ui.options.itemChanged.connect(self.edit_current_option) - - ####################################################################### - # Console tab - - self.ui.clean_console.clicked.connect(self.clean_console) - - ####################################################################### - # Other widgets connected - - self.ui.open_home_terminal.clicked.connect(self.open_terminal) - self.ui.switch_mode.clicked.connect(self.switch_current_mode) - -############################################################################### -# [Hmi methods] Reimplemented methods - - def closeEvent(self, event): - """ - :param event: QEvent object automatically filled when 'closed' signal - caught. - -> Called automatically when when 'closed' signal caught. - -> Kill all processes still running. - -> Update the cache file. - -> Call the real mainWindow closeEvent to finish the 'app.exec_' - events loop. - """ - for process in [self.clean, self.build, self.upload]: - # + list(self.running_programs.values()): - # /!\ REQUIREMENT : DON'T KILL SESSION PROCESSES WHEN THE - # APPLICATION EXITS... - if process is not None: - try: - process.subprocess.kill() - except ProcessLookupError: - print("Process : '%s' already stopped. " - "Can't be killed again !\n" % process.name) - else: - print("Process : '%s' killed !\n" % process.name) - - # Ask for a confirmation if some data are unsaved and quit saving - # these data : - if self.configurations_changed != {} or self.sessions_changed != {}: - if self.sessions_changed != {parser.SIMULATION_NAME: - parser.SIMULATION_SESSION} \ - and self.sessions_changed != {parser.REPLAY_NAME: - parser.REPLAY_SESSION}: - self.data_changed_popup.show() - self.data_changed_popup.accepted.connect( - self.save_all_changed_data) - self.data_changed_popup.rejected.connect( - self.save_cache_data) - else: - print("A special in-code defined session (Session or Replay) " - "has been changed and could not have been saved...\n") - self.save_cache_data() - else: - self.save_cache_data() - -############################################################################### -# [Hmi methods] Update widgets methods - - def update_home_button(self): - self.ui.open_home_terminal.setText(env.PAPARAZZI_HOME) - - def update_mode_button(self): - if self.dev_mode: - self.ui.switch_mode.setText("Developer") - else: - self.ui.switch_mode.setText("Standard") - - def update_versions(self): - for field, value in zip([self.ui.run_version, self.ui.build_version], - [self.run_version, self.build_version]): - if value is not None: - field.setText(value) - else: - field.setText(UNKNOWN_VALUE) - - def switch_to_tab(self, tab_index): - self.ui.main_tab.setCurrentIndex(tab_index) - - def init_tools_menu(self): - """ - -> Clear the 'Tools' menu actions (menubar). - -> Fill the 'Tools' menu with the names found in 'control_panel.xml' - -> Connect each action to the corresponding tool process. - """ - # The tools are sorted first by whether they are favorite or not, then by their names - for tool in sorted(self.data.tools.values(), key=lambda tool: (not tool.favorite, tool.name)): - if not tool.blacklisted: - command = functools.partial(self.add_program_to_session, tool) - icon_name = tool.icon if tool.icon is not None else DEFAULT_TOOL_ICON - icon_path = "/".join([env.PAPARAZZI_HOME, ICONS_TOOLS_PATH, icon_name]) - self.ui.tools_menu.add_item(tool.name, icon_path, command) - - def fullscreen_view(self): - if self.isMaximized(): - self.resize(800, 600) - else: - self.showMaximized() - - def toggle_overview(self): - if self.ui.dockWidget.isVisible(): - self.ui.dockWidget.hide() - self.ui.actionHide_overviews.setText("Show overviews") - else: - self.ui.dockWidget.show() - self.ui.actionHide_overviews.setText("Hide overviews") - - def update_set_combo(self): - """ - -> Clear the 'Set' combobox. - -> Fill the combobox with the names found in 'conf.xml'. - """ - self.ui.current_set.clear() - sorted_names = parser.sorted_sets_names(self.data.sets) - self.ui.current_set.addItems(sorted_names) - self.ui.current_set.setCurrentText(self.current_set.name) - - def update_config_combo(self): - """ - -> Clear the 'Configuration' combobox. - -> Fill the combobox with the configurations names corresponding to the - current selected set. - -> Save the current settings check state when configuration changed. - (allows to the configuration to be recovered when selected again) - """ - self.ui.current_configuration.clear() - sorted_names = parser.sorted_current_configs_names( - self.data.configurations, - self.current_set) - self.ui.current_configuration.addItems(sorted_names) - self.ui.current_configuration.setCurrentText(self.current_config.name) - - def update_config_items_lists(self): - """ - -> Disable or hide widgets and buttons to init config. - -> Set config ID and color. - -> Set config items by category. - -> Make 'settings' items checkable and set check-boxes. - """ - set_widgets_visibility(self.display_config_widgets + - self.change_config_widgets, False) - set_widgets_availability([self.ui.remove_item, - self.ui.edit], False) - set_widgets_visibility(self.flight_plan_buttons, False) - - self.ui.current_id.setText(self.current_config.id) - color = gui.generate_qcolor(self.current_config.color[0]) - palette = gui.generate_widget_palette(self.ui.current_color, color) - self.ui.current_color.setPalette(palette) - - clear_widgets(self.change_config_widgets) - for widget, values in zip(self.change_config_widgets, - [self.current_config.airframes, - self.current_config.settings + - self.current_config.modules, - self.current_config.flight_plan, - self.current_config.radio, - self.current_config.telemetry]): - for value in values: - value = value.strip() - if value: - widget.addItem(value) - if values: - set_widgets_visibility([widget], True) - - for i in range(self.ui.current_settings.count()): - item = self.ui.current_settings.item(i) - item.setFlags(Core.Qt.ItemIsUserCheckable | Core.Qt.ItemIsEnabled | - Core.Qt.ItemIsSelectable) - if item.text().startswith("["): - item.setText(item.text().strip("[]")) - item.setCheckState(Core.Qt.Unchecked) - else: - item.setCheckState(Core.Qt.Checked) - - self.update_config_overview_lists() - - def update_config_overview_lists(self): - """ - -> Hide all the configuration overview widgets. - -> Clear these widgets. - -> Copy the content of the real configuration QListWidget widgets. - -> Keep only the basename of long items (put full name in tooltip). - -> Display the widgets only if not empty (save some vertical space). - """ - set_widgets_visibility(self.display_config_widgets, False) - clear_widgets(self.display_config_widgets) - for input_widget, display_widget in zip(self.change_config_widgets*2, - self.display_config_widgets): - items_full_names = [] - for i in range(input_widget.count()): - item_full_name = input_widget.item(i).text() - item_name = os.path.splitext( - os.path.basename(item_full_name))[0] - display_widget.addItem(item_name) - items_full_names.append(item_full_name) - display_widget.setToolTip("\n".join(items_full_names)) - if display_widget.count() != 0: - display_widget.setVisible(True) - - def update_target_combos(self, combo_widgets): - """ - :param combo_widgets: - -> Clear the 2 'Target' combo widgets. - -> Fill them with the targets available for the current configuration. - """ - clear_widgets(combo_widgets) - sorted_names = parser.sorted_current_targets_names( - self.current_config.targets) - for widget in combo_widgets: - widget.addItems(sorted_names) - widget.setCurrentText(self.current_target.name) - - def update_log_filters(self): - """ - -> Load the last filters from the cache. - -> Disable the filters if the level is minimum or maximum. - -> Set the filters check state by the current LogFilter object - properties. - """ - if self.current_log_filter.level == cs.MINIMAL_MESSAGES_LEVEL: - self.ui.important.setChecked(True) - set_widgets_availability(self.log_filters_widgets, False) - elif self.current_log_filter.level == cs.ALL_MESSAGES_LEVEL: - self.ui.all.setChecked(True) - set_widgets_availability(self.log_filters_widgets, False) - else: - self.ui.custom.setChecked(True) - set_widgets_availability(self.log_filters_widgets, True) - self.ui.display_default.setChecked(self.current_log_filter.default) - self.ui.display_info.setChecked(self.current_log_filter.info) - self.ui.display_warnings.setChecked(self.current_log_filter.warning) - self.ui.display_errors.setChecked(self.current_log_filter.error) - - def update_device_combo(self): - """ - -> Clear the 'Device' combobox. - -> Search compatible boards for current target. - -> Update the combo-box with devices corresponding to each board. - -> Deal with empty devices list because of default Wi-Fi flash. - """ - self.ui.device.clear() - current_devices = [] - for device in self.data.devices.values(): - if device.name != parser.DEFAULT_DEVICE_NAME: - for board_regex in device.boards_regex: - found_match = re.search(board_regex, self.current_target.board) - if found_match: - current_devices.append(device) - break - else: - current_devices.append(device) - sorted_names = parser.sorted_current_devices_names(current_devices) - self.ui.device.addItems(sorted_names) - self.ui.device.setCurrentText(self.current_device.name) - self.ui.device.setEnabled(True) - - def update_session_combos(self): - """ - -> Clear the 'Session' combobox. - -> Fill it with the sessions found in 'control_panel.xml' - """ - clear_widgets(self.session_widgets) - sorted_names = parser.sorted_sessions_names(self.data.sessions) - for widget in self.session_widgets: - widget.addItems(sorted_names) - sep_index = sorted_names.index(parser.SESSIONS_COMBO_SEP) - variant = Core.QVariant(not Core.Qt.ItemIsEnabled) - widget.setItemData(sep_index, variant, Core.Qt.UserRole - 1) - widget.setCurrentText(self.current_session.name) - - def update_programs_list(self): - """ - -> Clear the programs QListWidget. - -> Fill it with the programs available for the current session. - -> Update the programs overview widgets with the same programs. - -> Init the play/stop program button HMI. - """ - self.ui.programs.clear() - self.current_program = None - sorted_names = parser.sorted_current_programs_names( - self.current_session) - self.ui.programs.addItems(sorted_names) - for i in range(self.ui.programs.count()): - self.ui.programs.item(i).setIcon(self.stop_qicon) - self.update_programs_overviews() - self.update_program_button() - self.update_program_options_list() - - set_widgets_availability([self.ui.play_stop_program, - self.ui.remove_program, - self.ui.add_option] + - self.kill_all_buttons, False) - - def update_programs_overviews(self): - """ - -> Clear the programs overview QListWidget widgets. - -> Fill them with the current programs widget items. - -> Set their icon to stopped state. - """ - clear_widgets(self.display_programs_widgets) - for input_widget, display_widget in zip([self.ui.programs]*2, - self.display_programs_widgets): - for i in range(input_widget.count()): - display_widget.addItem(input_widget.item(i).text()) - item = display_widget.item(i) - item.setIcon(self.stop_qicon) - item.setFlags(Core.Qt.ItemIsEnabled) - - def update_program_options_list(self): - """ - -> Clear the options QListWidget. - -> Fill them with the current options of the selected program if - possible (and detect the option shape : tuple or str). - """ - self.ui.options.clear() - self.current_option = None - if self.current_program is not None: - options = self.current_program[1].options - for option in options: - option_str = option - if type(option) is tuple: - option_str = " ".join(option) - self.ui.options.addItem(option_str) - for i in range(self.ui.options.count()): - item = self.ui.options.item(i) - item.setFlags(Core.Qt.ItemIsEditable | Core.Qt.ItemIsEnabled | - Core.Qt.ItemIsSelectable) - self.ui.remove_option.setEnabled(False) - - def init_build_flash_hmi(self): - """ - -> Kill the build processes if already running. - -> Clear the build widgets. - """ - clear_widgets([self.ui.build_result_icon, - self.ui.build_result, - self.ui.flash_resut_icon, - self.ui.flash_result] + self.messages_nb_widgets) - - def update_flags_nb_hmi(self, compilation_object): - """ - :param compilation_object: - -> Update the flags number QLabel widgets at each log sent to the - console. - """ - self.ui.errors_nb.setText(str( - compilation_object.flags[cs.ERROR_FLAG])) - self.ui.warnings_nb.setText(str( - compilation_object.flags[cs.WARNING_FLAG])) - self.ui.info_nb.setText(str( - compilation_object.flags[cs.INFO_FLAG])) - -############################################################################### -# [Hmi methods] Clean methods - - def set_clean_started_hmi(self): - """ - -> Turn HMI to clean running state. - """ - self.init_build_flash_hmi() - self.clean_running = True - set_widgets_availability([self.ui.build, self.ui.upload, - self.ui.quick_build] + - self.target_widgets, False) - self.ui.clean.setText("Stop !") - self.setCursor(gui.generate_qcursor(gui.WAIT_CURSOR_SHAPE)) - - def set_clean_stopped_hmi(self): - """ - -> Turn HMI to clean stopped state. - -> Display the result of the clean process. - -> Switch to the build / flash tab. - """ - self.clean_running = False - set_widgets_availability([self.ui.build, self.ui.quick_build, - self.ui.clean] + - self.target_widgets, True) - if self.current_target.name not in self.simulation_targets_names: - self.ui.upload.setEnabled(True) - self.ui.clean.setText("Clean") - self.setCursor(gui.generate_qcursor(gui.NORMAL_CURSOR_SHAPE)) - self.update_flags_nb_hmi(self.clean) - errors = self.clean.flags[cs.ERROR_FLAG] - if self.clean.exit_code == proc.INTERRUPTED_EXIT_CODE: - self.ui.build_result.setText("Clean aborted by user !") - self.ui.build_result_icon.setPixmap(self.error_qpixmap) - elif errors != 0 or self.clean.exit_code == proc.DEFAULT_EXIT_CODE: - self.ui.build_result.setText("Error(s) found " + - "during clean. " + - "Please try again !") - self.ui.build_result_icon.setPixmap(self.error_qpixmap) - elif self.clean.exit_code == proc.SUCCESS_EXIT_CODE: - self.ui.build_result.setText("Clean done with success !") - self.ui.build_result_icon.setPixmap(self.ok_qpixmap) - else: - self.ui.build_result.setText("Unknown error !") - self.ui.build_result_icon.setPixmap(self.error_qpixmap) - self.clean = None - self.switch_to_tab(1) - -############################################################################### -# [Hmi methods] Build methods - - def set_build_started_hmi(self): - """ - -> Turn HMI to build running state. - """ - self.init_build_flash_hmi() - self.build_running = True - set_widgets_availability([self.ui.clean, self.ui.upload, - self.ui.quick_build] + - self.target_widgets, False) - self.ui.build.setText("Stop !") - self.setCursor(gui.generate_qcursor(gui.WAIT_CURSOR_SHAPE)) - - def set_build_stopped_hmi(self): - """ - -> Turn HMI to build stopped state. - -> Display the result of the build process. - -> Switch to the build / flash tab. - """ - self.build_running = False - set_widgets_availability([self.ui.clean, self.ui.quick_build, - self.ui.build] + - self.target_widgets, True) - if self.current_target.name not in self.simulation_targets_names: - self.ui.upload.setEnabled(True) - self.ui.build.setText("Build") - self.setCursor(gui.generate_qcursor(gui.NORMAL_CURSOR_SHAPE)) - self.update_flags_nb_hmi(self.build) - errors = self.build.flags[cs.ERROR_FLAG] - if self.build.exit_code == proc.INTERRUPTED_EXIT_CODE: - self.ui.build_result.setText("Build aborted by user !") - self.ui.build_result_icon.setPixmap(self.error_qpixmap) - elif errors != 0 or self.build.exit_code == proc.DEFAULT_EXIT_CODE: - self.ui.build_result.setText("Error(s) found " + - "during build. " + - "Please try again !") - self.ui.build_result_icon.setPixmap(self.error_qpixmap) - elif self.build.exit_code == proc.SUCCESS_EXIT_CODE: - self.ui.build_result.setText("Build done with success !") - self.ui.build_result_icon.setPixmap(self.ok_qpixmap) - else: - self.ui.build_result.setText("Unknown error !") - self.ui.build_result_icon.setPixmap(self.error_qpixmap) - self.build = None - self.switch_to_tab(1) - -############################################################################### -# [Hmi methods] Flash methods - - def set_flash_started_hmi(self): - """ - -> Turn HMI to flash running state. - """ - self.init_build_flash_hmi() - self.upload_running = True - set_widgets_availability([self.ui.clean, self.ui.build, - self.ui.quick_build, self.ui.device] + - self.target_widgets, False) - self.ui.upload.setText("Stop !") - self.setCursor(gui.generate_qcursor(gui.WAIT_CURSOR_SHAPE)) - clear_widgets([self.ui.flash_resut_icon, - self.ui.flash_result]) - - def set_flash_stopped_hmi(self): - """ - -> Turn HMI to flash stopped state. - -> Display the result of the upload process. - -> Switch to the build / flash tab. - """ - self.upload_running = False - set_widgets_availability([self.ui.clean, self.ui.build, - self.ui.upload, - self.ui.quick_build, self.ui.device] + - self.target_widgets, True) - self.ui.upload.setText("Upload") - self.setCursor(gui.generate_qcursor(gui.NORMAL_CURSOR_SHAPE)) - self.update_flags_nb_hmi(self.upload) - errors = self.upload.flags[cs.ERROR_FLAG] - if self.upload.exit_code == proc.INTERRUPTED_EXIT_CODE: - self.ui.flash_result.setText("Upload aborted by user !") - self.ui.flash_resut_icon.setPixmap(self.error_qpixmap) - elif errors != 0 or self.upload.exit_code == proc.DEFAULT_EXIT_CODE: - self.ui.flash_result.setText("Error(s) found " + - "during upload. " + - "Please try again !") - self.ui.flash_resut_icon.setPixmap(self.error_qpixmap) - elif self.upload.exit_code == proc.SUCCESS_EXIT_CODE: - self.ui.flash_result.setText("Upload done with success !") - self.ui.flash_resut_icon.setPixmap(self.ok_qpixmap) - else: - self.ui.flash_result.setText("Unknown error !") - self.ui.flash_resut_icon.setPixmap(self.error_qpixmap) - self.upload = None - self.switch_to_tab(1) - -############################################################################### -# [Hmi methods] Program methods - - def update_program_button(self): - """ - -> Update the play/stop program button HMI to correct state. - """ - if self.current_program is not None: - self.ui.play_stop_program.setEnabled(True) - if self.current_program[1].name in self.running_programs.keys(): - self.ui.play_stop_program.setIcon(self.stop_qicon) - self.ui.play_stop_program.setText("Stop") - else: - self.ui.play_stop_program.setIcon(self.start_qicon) - self.ui.play_stop_program.setText("Start") - else: - self.ui.play_stop_program.setEnabled(False) - self.ui.play_stop_program.setIcon(self.start_qicon) - - def set_program_started_hmi(self, program_process): - """ - :param program_process: - -> Turn HMI to program running state. - """ - self.running_programs[program_process.program.name] = program_process - - items = [widget.findItems(program_process.program.name, - Core.Qt.MatchExactly)[0] - for widget in [self.ui.programs, - self.ui.programs_overview_1, - self.ui.programs_overview_2]] - set_items_icons(items, self.start_qicon) - self.update_program_button() - - if self.running_programs != {}: - set_widgets_availability([self.ui.session, - self.ui.session_overview_1, - self.ui.session_overview_2, - self.ui.current_set], - False) - set_widgets_availability(self.kill_all_buttons, True) - set_widgets_availability(self.start_all_buttons, False) - - def set_program_stopped_hmi(self, program_process): - """ - :param program_process: - -> Turn HMI to program stopped state. - -> Display the result of the program process. - -> Switch to the sessions management tab. - """ - self.running_programs.pop(program_process.program.name) - - items = [widget.findItems(program_process.program.name, - Core.Qt.MatchExactly)[0] - for widget in [self.ui.programs, - self.ui.programs_overview_1, - self.ui.programs_overview_2]] - set_items_icons(items, self.stop_qicon) - self.update_program_button() - - if self.running_programs == {}: - set_widgets_availability([self.ui.session, - self.ui.session_overview_1, - self.ui.session_overview_2, - self.ui.current_set], - True) - set_widgets_availability(self.kill_all_buttons, False) - set_widgets_availability(self.start_all_buttons, True) - self.switch_to_tab(2) - -############################################################################### -# [Hmi methods] Write log methods - - def write_log_in_console(self, log, flag, log_type): - """ - :param log: - :param flag: - :param log_type: - -> Get the logs sent by the processes when a 'log_sent' signal is - caught. - -> Treat the log depending if it's an application or a process one. - -> Put color to the log line and write it into the console. - """ - if log_type == cs.PROCESS_MESSAGE_TYPE: - if self.current_log_filter.write_line_decision(flag): - str_color = cs.BACKGROUNDS_COLORS[flag] - background_qcolor = gui.generate_qcolor(str_color) - self.console.write(log, - backgroud_color=background_qcolor) - elif log_type == cs.APPLICATION_MESSAGE_TYPE: - if log != "\n": - str_color = cs.FONTS_COLORS[flag] - font_qcolor = gui.generate_qcolor(str_color) - self.console.write(log, font_color=font_qcolor) - - def animate_progress_bar(self): - """ - -> For all running build / flash processes, animate the progress bar. - -> Change the text displayed in the result field according to its size - and the current direction. - """ - for program, label in zip([self.clean, self.build, self.upload], - [self.ui.build_result, self.ui.build_result, - self.ui.flash_result]): - if program is not None: - last_result_text = label.text() - last_result_text_size = label.fontMetrics().\ - boundingRect(last_result_text).width() - field_width = label.width() - - if len(last_result_text) < PROGRESS_BAR_SPEED+1: - new_result_text = PROGRESS_BAR_LINE * PROGRESS_BAR_SPEED \ - + PROGRESS_BAR_CURSOR - self.progress_bar_to_left = False - elif last_result_text_size > field_width - 100\ - or self.progress_bar_to_left: - new_result_text = last_result_text[PROGRESS_BAR_SPEED:] - self.progress_bar_to_left = True - else: - new_result_text = PROGRESS_BAR_LINE * PROGRESS_BAR_SPEED \ - + last_result_text - self.progress_bar_to_left = False - label.setText(new_result_text) - -############################################################################### -# [Hmi methods] Widgets connected with signals methods - - def switch_current_mode(self): - """ - -> Real switch but no real effect (no dev mode yet...) - -> RELOAD MAIN WINDOW WITH NEW WIDGETS ? - """ - self.dev_mode = not self.dev_mode - self.update_mode_button() - - def change_current_set(self): - """ - -> Get current set when combobox value changed. - -> Symbolic link to 'config.xml' changed to the new set. - -> Update configuration and its items. - """ - self.save_all_changed_configurations() - current_set_name = self.ui.current_set.currentText() - if current_set_name: - self.current_set = self.data.sets[current_set_name] - point_symbol_link_to(self.current_set.name) - self.update_config_combo() - self.update_config_items_lists() - - def change_current_config(self): - """ - -> Get current configuration when combobox value changed. - -> Update target and device values. - -> Stop the build processes if some running. - -> Init the build / flash HMI to be ready to a new process. - """ - current_config_name = self.ui.current_configuration.currentText() - if current_config_name: - self.current_config = self.data.configurations[current_config_name] - self.update_config_items_lists() - self.update_target_combos([self.ui.target]) - self.update_device_combo() - self.init_build_flash_hmi() - - def change_current_item(self, list_widget): - """ - :param list_widget: - -> Update the current selected item : (widget, item, object). - -> Clear the others selected items in other categories. - -> Update the configuration management HMI (buttons). - -> Make the flight plan buttons appear or disappear. - -> Update all the check states of the settings list if the current - selected item is a setting. - """ - current_selected_item = list_widget.currentItem() - if current_selected_item is not None: - current_item_text = current_selected_item.text() - self.current_item = (list_widget, - current_selected_item, - current_item_text) - widgets_to_clear = [_ for _ in self.change_config_widgets] - widgets_to_clear.remove(list_widget) - clear_list_widgets_selection(widgets_to_clear) - set_widgets_availability([self.ui.remove_item, - self.ui.edit], True) - set_widgets_visibility(self.flight_plan_buttons, - list_widget.objectName() == - "current_flight_plan") - - def change_current_target(self, combo_widget): - """ - :param combo_widget: - -> Update the current target and the devices combobox (related). - -> Possible to change the target from 2 widgets. That's why the - solution found is strange... - """ - current_target_name = combo_widget.currentText() - if current_target_name and self.change_target_bool: - self.current_target = self.current_config.targets[ - current_target_name] - self.ui.upload.setEnabled(self.current_target.name - not in self.simulation_targets_names) - other_widgets = [_ for _ in self.target_widgets] - other_widgets.remove(combo_widget) - # TODO BETTER : AVOID THE SIGNALS PING-PONG BETWEEN TARGETS WIDGETS - self.change_target_bool = False - self.update_target_combos(other_widgets) - self.change_target_bool = True - self.update_device_combo() - - def change_sensitivity_filters(self): - """ - -> Get checkbox values to set the current filters. - -> Update the filters values for the console. - """ - self.current_log_filter.set_sensitivity_filter( - self.ui.display_default.checkState(), - self.ui.display_info.checkState(), - self.ui.display_warnings.checkState(), - self.ui.display_errors.checkState()) - self.update_log_filters() - - def change_messages_level(self): - """ - -> Get radiobutton value to set the current message level. - -> Update the level value for the console. - """ - if self.ui.all.isChecked(): - self.current_log_filter.set_level(cs.ALL_MESSAGES_LEVEL) - self.current_log_filter.set_sensitivity_filter(2, 2, 2, 2) - elif self.ui.custom.isChecked(): - self.current_log_filter.set_level(cs.CUSTOM_MESSAGES_LEVEL) - elif self.ui.important.isChecked(): - self.current_log_filter.set_level(cs.MINIMAL_MESSAGES_LEVEL) - self.current_log_filter.set_sensitivity_filter(0, 0, 2, 2) - self.update_log_filters() - - def change_current_device(self): - """ - -> Get current device when combobox value changed. - -> If no device available, the default flash mode is WiFi. - """ - current_device_name = self.ui.device.currentText() - if current_device_name: - self.current_device = self.data.devices[current_device_name] - - def change_current_session(self, combo_widget): - """ - :param combo_widget: - -> Get current session when combobox value changed. - -> Update programs HMI for the new selected session. - -> Deselect the last selected program and clear the options. - """ - current_session_name = combo_widget.currentText() - if current_session_name: - clear_list_widgets_selection([self.ui.programs] + - self.display_programs_widgets) - self.current_session = self.data.sessions[current_session_name] - widgets = [_ for _ in self.session_widgets] - widgets.remove(combo_widget) - for widget in widgets: - widget.setCurrentText(self.current_session.name) - self.update_programs_list() - self.update_program_options_list() - self.ui.options.clear() - - def change_current_program(self): - """ - -> Get current selected program when QListWidget selection changed. - -> Update options HMI for the new selected program. - """ - current_selected_item = self.ui.programs.currentItem() - if current_selected_item is not None: - item_name = current_selected_item.text() - if item_name in self.current_session.programs.keys(): - self.current_program = (current_selected_item, - self.current_session.programs[ - item_name]) - self.ui.remove_program.setEnabled(item_name not in - self.running_programs.keys()) - self.ui.add_option.setEnabled(True) - self.update_program_options_list() - self.update_program_button() - - def change_current_option(self): - """ - -> Get the current selected option when QListWidget selection changed. - -> Enable options management HMI. - """ - current_selected_item = self.ui.options.currentItem() - if current_selected_item is not None: - item_name = current_selected_item.text() - self.current_option = (current_selected_item, item_name) - self.ui.remove_option.setEnabled(True) - - def open_item_file_chooser(self): - """ - -> While left part of equipment tab is not finished, a simple file - chooser is used to select new equipment items. - -> Add the selected new item to the correct category if possible. - """ - file_chooser = Widgets.QFileDialog() - fc_title = "Select a file to add to '" +\ - self.current_config.name + "'..." - fc_dir = env.PAPARAZZI_CONF - fc_filter = "XML file(*.xml)" - path, other = file_chooser.getOpenFileName(file_chooser, - fc_title, - fc_dir, - fc_filter) - if path: - filename = parser.full_to_conf_path(path) - self.add_item_to_config(filename) - - def open_gedit(self): - """ - -> Open a text editor depending on the OS found. - """ - if self.current_item is not None: - - if env.OS in ["linux", "linux2"]: - file_path = os.path.join(CONF_PATH, self.current_item[2]) - command = " ".join(["gedit", file_path]) - try: - os.popen(command) - except ChildProcessError: - LOGGER.error("Gedit text editor is not available !\n") - self.switch_to_tab(3) - elif env.OS in []: - pass - else: - LOGGER.error("No text file editor found for your OS !\n") - self.switch_to_tab(3) - - def clean_console(self): - """ - -> Just clear the console QTextEdit widget. - """ - self.ui.console.clear() - - def open_terminal(self): - """ - -> Open a terminal in the Paparazzi home directory depending on the OS - found. - """ - if env.OS in ["linux", "linux2"]: - command_terms = ["gnome-terminal", "--working-directory ", - env.PAPARAZZI_HOME] - command = " ".join(command_terms) - os.popen(command) - else: - LOGGER.error("No terminal shortcut available for your OS !\n") - self.switch_to_tab(3) - -############################################################################### -# [Hmi methods] Processes management (connected with signals) methods - - def quick_build(self): - """ - -> Clean the current configuration when the quick build button is - clicked. - -> Give the information to the clean function that a build process - is planned after the clean process. - """ - self.switch_to_tab(1) - self.clean_config(is_quick_build=True) - - def clean_config(self, is_quick_build=False): - """ - :param is_quick_build: - -> Clean the current configuration if not already started. - -> Else, abort the current clean process and set the HMI to the - initial state. - """ - if not self.clean_running: - self.clean = proc.Process(proc.CLEAN, - configuration=self.current_config) - if self.clean.check_before_start(): - self.clean.start() - self.clean.subprocess.finished.connect(self.set_clean_stopped_hmi) - self.clean.process_log_sent.connect(functools.partial( - self.update_flags_nb_hmi, self.clean)) - self.clean.process_log_sent.connect(self.write_log_in_console) - self.clean.process_log_sent.connect(self.animate_progress_bar) - self.set_clean_started_hmi() - - if is_quick_build: - self.clean.subprocess.finished.connect(functools.partial( - self.build_config)) - else: - LOGGER.error("Incorrect config, can't clean !\n") - self.switch_to_tab(3) - else: - self.clean.process_killed.emit() - self.ui.clean.setEnabled(False) - - def build_config(self): - """ - -> Build the current configuration if not already started. - -> Else, abort the current build process and set the HMI to the - initial state. - """ - if not self.build_running: - self.build = proc.Process(proc.BUILD, - configuration=self.current_config, - target=self.current_target) - self.save_current_config() - - if self.build.check_before_start(): - self.build.start() - self.build.subprocess.finished.connect(self.set_build_stopped_hmi) - self.build.process_log_sent.connect(functools.partial( - self.update_flags_nb_hmi, self.build)) - self.build.process_log_sent.connect(self.write_log_in_console) - self.build.process_log_sent.connect(self.animate_progress_bar) - self.set_build_started_hmi() - else: - LOGGER.error("Incorrect config, can't build !\n") - self.switch_to_tab(3) - else: - self.build.process_killed.emit() - self.ui.build.setEnabled(False) - - def flash_device(self): - """ - -> Flash the current configuration if not already started. - -> Else, abort the current upload process and set the HMI to the - initial state. - """ - if not self.upload_running: - self.upload = proc.Process(proc.UPLOAD, - configuration=self.current_config, - target=self.current_target, - device=self.current_device) - if self.upload.check_before_start(): - self.upload.start() - self.upload.subprocess.finished.connect(self.set_flash_stopped_hmi) - self.upload.process_log_sent.connect(functools.partial( - self.update_flags_nb_hmi, self.upload)) - self.upload.process_log_sent.connect(self.write_log_in_console) - self.upload.process_log_sent.connect(self.animate_progress_bar) - self.set_flash_started_hmi() - else: - LOGGER.error("Incorrect device, can't upload !\n") - self.switch_to_tab(3) - else: - self.upload.process_killed.emit() - self.ui.upload.setEnabled(False) - - def run_program(self, program): - """ - :param program: - -> Run the current selected program if not already started. - Else, abort it and set the HMI to the initial state. - """ - if program is None and self.current_program is not None: - program_item, program = self.current_program - if program.name not in self.running_programs.keys(): - new_program_proc = proc.Process(proc.PROGRAM, - program=program, - configuration=self.current_config, - target=self.current_target) - if new_program_proc.check_before_start(): - new_program_proc.start() - new_program_proc.subprocess.finished.connect(functools.partial( - self.set_program_stopped_hmi, new_program_proc)) - new_program_proc.process_log_sent.connect( - self.write_log_in_console) - self.set_program_started_hmi(new_program_proc) - else: - self.running_programs[program.name].process_killed.emit() - self.ui.play_stop_program.setEnabled(False) - - def start_all_programs(self): - """ - -> Kill all running programs of the current session. - -> Start all programs not running (so it's a restart). - -> Keep the current selected program if there's one. - """ - for program in self.current_session.programs.values(): - if program.name not in self.running_programs.keys(): - self.run_program(program) - - def kill_all_programs(self): - """ - -> Kill all running programs of the current session. - -> Keep the current selected program if there's one. - """ - for program in self.current_session.programs.values(): - if program.name in self.running_programs.keys(): - self.run_program(program) - -############################################################################### -# [Hmi methods] Data management (connected with signals) methods - - def change_setting_check_state(self, clicked_item): - """ - :param clicked_item: - -> Save the new check state of settings items. - -> Add the current config to changed configs => ask to save - before quitting the application. - """ - if self.current_config is not None\ - and self.current_item is not None: - list_widget, list_item, item_name = self.current_item - setting_name = item_name - setting_state = list_item.checkState() - # TODO BETTER : NO SOLUTION (OR SIGNAL) FOUND TO DETECT A CLICK ON - # : TODO : 'QListWidgetItem' SO ONLY CURRENT ITEM CHECKSTATE - # : TODO : SHOULD BE CHANGED... (NOT WORKING WELL) - if clicked_item == list_item: - if parser.SETTINGS_REF in setting_name: - settings_modules = self.current_config.settings - else: - settings_modules = self.current_config.modules - settings_modules_names = [item.strip("[]") for item in settings_modules] - setting_index = settings_modules_names.index(setting_name) - settings_modules.pop(setting_index) - if not setting_state: - setting_name = "[" + setting_name + "]" - settings_modules.insert(setting_index, setting_name) - - self.configurations_changed[self.current_config.name] = \ - self.current_config - index = self.ui.current_configuration.currentIndex() - self.ui.current_configuration.setItemIcon(index, self.changed_qicon) - else: - clicked_item.setCheckState(setting_state) - - def remove_item_from_config(self): - """ - -> Remove an item from the current selected configuration. - -> Impossible to remove all airframes because it doesn't make sense. - """ - if self.current_config is not None \ - and self.current_item is not None: - list_widget, list_item, item_name = self.current_item - if not (list_widget is self.ui.current_airframes and - len(list_widget) == 1): - if list_widget == self.ui.current_settings and \ - not list_item.checkState(): - item_name = "[" + item_name + "]" - - config_attributes_lists = [self.current_config.airframes, - self.current_config.settings, - self.current_config.modules, - self.current_config.flight_plan, - self.current_config.radio, - self.current_config.telemetry] - for attributes_list in config_attributes_lists: - if item_name in attributes_list: - attributes_list.remove(item_name) - break - - list_widget.takeItem(list_widget.row(list_item)) - list_widget.clearSelection() - self.current_item = None - self.ui.remove_item.setEnabled(False) - if not list_widget: - list_widget.setVisible(False) - if list_widget is self.ui.current_flight_plan: - set_widgets_visibility(self.flight_plan_buttons, False) - self.update_config_overview_lists() - - self.configurations_changed[self.current_config.name] = \ - self.current_config - index = self.ui.current_configuration.currentIndex() - self.ui.current_configuration.setItemIcon(index, - self.changed_qicon) - else: - LOGGER.error("You can't remove all airframes from a " - "configuration !\n") - self.switch_to_tab(3) - - def add_item_to_config(self, filename): - """ - :param filename: - -> Add the selected filename to the correct category if it's possible. - -> Else, an error is raised in the console. - -> If a setting is added, it's checked by default. - """ - if self.current_config is not None: - keywords = [parser.AIRFRAME_REF, parser.SETTINGS_REF, - parser.MODULES_REF, parser.FP_REF, - parser.RADIO_REF, parser.TELEMETRY_REF] - fields = [self.current_config.airframes, - self.current_config.settings, - self.current_config.modules, - self.current_config.flight_plan, - self.current_config.radio, - self.current_config.telemetry] - widgets = self.change_config_widgets.copy() - widgets.insert(2, self.ui.current_settings) - - match_found = False - for keyword, field, widget in zip(keywords, fields, widgets): - if keyword in filename: - field.append(filename) - widget.addItem(filename) - last_item = widget.item(widget.count()-1) - if widget == self.ui.current_settings: - last_item.setFlags(Core.Qt.ItemIsUserCheckable | - Core.Qt.ItemIsEnabled | - Core.Qt.ItemIsSelectable) - last_item.setCheckState(Core.Qt.Checked) - widget.setCurrentItem(last_item) - match_found = True - break - - if match_found: - self.configurations_changed[self.current_config.name] = \ - self.current_config - index = self.ui.current_configuration.currentIndex() - self.ui.current_configuration.setItemIcon(index, - self.changed_qicon) - else: - LOGGER.error("The selected file '%s' is not an acceptable file in" - " a configuration !\n", filename) - self.switch_to_tab(3) - - def remove_program_from_session(self): - """ - -> Remove the selected program from the current selected session. - -> Add the current session to changed sessions => ask to save - before quitting the application. - """ - if self.current_session is not None \ - and self.current_program is not None: - program_item, program = self.current_program - - self.current_session.programs.pop(program.name) - self.update_programs_list() - - self.sessions_changed[self.current_session.name] = \ - self.current_session - index = self.ui.session.currentIndex() - self.ui.session.setItemIcon(index, self.changed_qicon) - self.switch_to_tab(2) - - def add_program_to_session(self, program): - """ - :param program: - -> Add a program object (only a copy of a tool from the Tools menu - for now) to the current selected session. - """ - if self.current_session is not None: - - new_program_name = parser.find_unused_item_name( - self.current_session.programs, program.name) - new_program = db.Program(new_program_name, program.command, - program.options) - self.current_session.programs[new_program.name] = new_program - self.update_programs_list() - new_item = self.ui.programs.findItems(new_program.name, - Core.Qt.MatchExactly)[0] - self.ui.programs.setCurrentItem(new_item) - - self.sessions_changed[self.current_session.name] = \ - self.current_session - index = self.ui.session.currentIndex() - self.ui.session.setItemIcon(index, self.changed_qicon) - self.switch_to_tab(2) - - def remove_option_from_program(self): - """ - -> Remove the selected option from the current selected program. - """ - if self.current_program is not None \ - and self.current_option is not None: - program_item, program = self.current_program - option_item, option = self.current_option - - if type(option) is str: - program.options.remove(option) - else: - program.options.remove(tuple(option.split())) - self.update_program_options_list() - - self.sessions_changed[self.current_session.name] = \ - self.current_session - index = self.ui.session.currentIndex() - self.ui.session.setItemIcon(index, self.changed_qicon) - - def add_option_to_program(self): - """ - -> Add an option to the current selected program. - """ - if self.current_session is not None \ - and self.current_program is not None: - program_item, program = self.current_program - new_option = "" - program.options.append(new_option) - self.update_program_options_list() - last_item = self.ui.options.item(self.ui.options.count()-1) - self.ui.options.setCurrentItem(last_item) - - self.sessions_changed[self.current_session.name] = \ - self.current_session - index = self.ui.session.currentIndex() - self.ui.session.setItemIcon(index, self.changed_qicon) - - def edit_current_option(self): - """ - -> Edit the selected option when enter pressed after changes. - """ - if self.current_program is not None \ - and self.current_option is not None: - program_item, program = self.current_program - - old_option_item, old_option = self.current_option - old_option_index = program.options.index(old_option) - program.options.remove(old_option) - self.change_current_option() - new_option_item, new_option = self.current_option - program.options.insert(old_option_index, new_option) - - self.sessions_changed[self.current_session.name] = \ - self.current_session - index = self.ui.session.currentIndex() - self.ui.session.setItemIcon(index, self.changed_qicon) - -############################################################################### -# [Hmi methods] Data management : XML writing methods - - def save_current_config(self): - """ - -> Update the new values of the current configuration in the - corresponding XML file. - """ - if self.current_config.name in self.configurations_changed.keys(): - self.configurations_changed.pop(self.current_config.name) - index = self.ui.current_configuration.currentIndex() - self.ui.current_configuration.setItemIcon(index, - gui.generate_qicon()) - - LOGGER.info("Saving '%s' configuration...", - self.current_config.name) - parser.save_configuration(self.current_set.name, - self.current_config) - LOGGER.info("'%s' configuration saved.\n", - self.current_config.name) - else: - LOGGER.info("Nothing to save, configuration already up-to-date.\n") - - def save_current_session(self): - """ - -> Update the new values of the current session in the - corresponding 'control_panel.xml' file. - -> Deal with the in-code defined sessions (Simulation, Replay). - """ - if self.current_session.name in self.sessions_changed.keys(): - self.sessions_changed.pop(self.current_session.name) - index = self.ui.session.currentIndex() - self.ui.session.setItemIcon(index, gui.generate_qicon()) - if self.current_session.name not in [parser.SIMULATION_NAME, - parser.REPLAY_NAME]: - LOGGER.info("Saving '%s' session...", self.current_session.name) - parser.save_session(parser.CONTROL_PANEL_FILE, - self.current_session) - LOGGER.info("'%s' session saved.\n", self.current_session.name) - else: - LOGGER.error("'%s' is an in-code defined session. " - "Impossible to save it !\n", - self.current_session.name) - print("'%s' is an in-code defined session. " - "Impossible to save it !\n" - % self.current_session.name) - self.switch_to_tab(3) - else: - LOGGER.info("Nothing to save, session already up-to-date.\n") - - def save_all_changed_configurations(self): - changed_configs = [_ for _ in self.configurations_changed.values()] - for config in changed_configs: - self.current_config = config - self.save_current_config() - - def save_all_changed_sessions(self): - changed_sessions = [_ for _ in self.sessions_changed.values()] - for session in changed_sessions: - self.current_session = session - self.save_current_session() - - def save_all_changed_data(self): - self.save_all_changed_configurations() - self.save_all_changed_sessions() - print("All changes in data saved.\n") - self.save_cache_data() - - def save_cache_data(self): - """ - -> Change values in cache with the 'write' mode of the common parsing - function. - """ - LOGGER.info("Cache updating...") - print("Cache updating...") - current_geometry_str = " ".join(map(str, - [self.geometry().x(), - self.geometry().y(), - self.geometry().width(), - self.geometry().height()])) - current_log_filters_str = " ".join(map(str, - [self.current_log_filter.level, - self.current_log_filter.default, - self.current_log_filter.info, - self.current_log_filter.warning, - self.current_log_filter.error])) - - parser.parse_cache_file("w", self.data.cache_file, - geometry_str=current_geometry_str, - set_str=self.current_set.name, - config_str=self.current_config.name, - target_str=self.current_target.name, - log_filters_str=current_log_filters_str, - device_str=self.current_device.name, - session_str=self.current_session.name) - LOGGER.info("Cache now up-to-date.\n") - print("Cache now up-to-date.\n") diff --git a/sw/supervision/python/icons/accessories-text-editor.svg b/sw/supervision/python/icons/accessories-text-editor.svg deleted file mode 100644 index 03db109a64..0000000000 --- a/sw/supervision/python/icons/accessories-text-editor.svg +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/icons/dialog-apply.svg b/sw/supervision/python/icons/dialog-apply.svg deleted file mode 100644 index f009b90ee3..0000000000 --- a/sw/supervision/python/icons/dialog-apply.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/icons/dialog-error.svg b/sw/supervision/python/icons/dialog-error.svg deleted file mode 100644 index a3d6de4d72..0000000000 --- a/sw/supervision/python/icons/dialog-error.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/icons/dialog-warning-symbolic.svg b/sw/supervision/python/icons/dialog-warning-symbolic.svg deleted file mode 100644 index e9474a9d14..0000000000 --- a/sw/supervision/python/icons/dialog-warning-symbolic.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - image/svg+xml - - Gnome Symbolic Icon Theme - - - - Gnome Symbolic Icon Theme - - - - diff --git a/sw/supervision/python/icons/dialog-warning.png b/sw/supervision/python/icons/dialog-warning.png deleted file mode 100644 index d1020c6d9e..0000000000 Binary files a/sw/supervision/python/icons/dialog-warning.png and /dev/null differ diff --git a/sw/supervision/python/icons/edit-clear.svg b/sw/supervision/python/icons/edit-clear.svg deleted file mode 100644 index 568fe9de66..0000000000 --- a/sw/supervision/python/icons/edit-clear.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/icons/go-up.svg b/sw/supervision/python/icons/go-up.svg deleted file mode 100644 index e5e58672cd..0000000000 --- a/sw/supervision/python/icons/go-up.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/icons/gtk-info.svg b/sw/supervision/python/icons/gtk-info.svg deleted file mode 100644 index f1ec53786a..0000000000 --- a/sw/supervision/python/icons/gtk-info.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/icons/list-add.svg b/sw/supervision/python/icons/list-add.svg deleted file mode 100644 index f40a948324..0000000000 --- a/sw/supervision/python/icons/list-add.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/icons/list-remove.svg b/sw/supervision/python/icons/list-remove.svg deleted file mode 100644 index ebc6bdbe8f..0000000000 --- a/sw/supervision/python/icons/list-remove.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/icons/media-playback-pause.svg b/sw/supervision/python/icons/media-playback-pause.svg deleted file mode 100644 index fde2760829..0000000000 --- a/sw/supervision/python/icons/media-playback-pause.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/icons/media-playback-start.svg b/sw/supervision/python/icons/media-playback-start.svg deleted file mode 100644 index 87c34d3025..0000000000 --- a/sw/supervision/python/icons/media-playback-start.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/icons/penguin_icon.png b/sw/supervision/python/icons/penguin_icon.png deleted file mode 100644 index f61d8024e9..0000000000 Binary files a/sw/supervision/python/icons/penguin_icon.png and /dev/null differ diff --git a/sw/supervision/python/icons/process-stop.svg b/sw/supervision/python/icons/process-stop.svg deleted file mode 100644 index 1c9162caab..0000000000 --- a/sw/supervision/python/icons/process-stop.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/icons/search_field.png b/sw/supervision/python/icons/search_field.png deleted file mode 100644 index c3264f66d9..0000000000 Binary files a/sw/supervision/python/icons/search_field.png and /dev/null differ diff --git a/sw/supervision/python/icons/system-run.png b/sw/supervision/python/icons/system-run.png deleted file mode 100644 index ad6d80b0de..0000000000 Binary files a/sw/supervision/python/icons/system-run.png and /dev/null differ diff --git a/sw/supervision/python/icons/utilities-terminal.svg b/sw/supervision/python/icons/utilities-terminal.svg deleted file mode 100644 index add2893910..0000000000 --- a/sw/supervision/python/icons/utilities-terminal.svg +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/lib/console.py b/sw/supervision/python/lib/console.py deleted file mode 100644 index 945712cc7a..0000000000 --- a/sw/supervision/python/lib/console.py +++ /dev/null @@ -1,155 +0,0 @@ -# Paparazzi center utilities -# -# Copyright (C) 2016 ENAC, Florian BITARD (intern student) -# -# This file is part of paparazzi. -# -# paparazzi is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# paparazzi is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with paparazzi; see the file COPYING. If not, write to -# the Free Software Foundation, 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -############################################################################### -# [Imports] - -import lib.gui as gui - -import PyQt5.QtCore as Core -import re - - -############################################################################### -# [Constants] - -DEFAULT_FONT_QCOLOR = gui.generate_qcolor("black") -DEFAULT_BACKGROUND_QCOLOR = gui.generate_qcolor("white") -DEFAULT_LOGGER_FONT_QCOLOR = gui.generate_qcolor("blue") - -ALL_MESSAGES_LEVEL = "all" -CUSTOM_MESSAGES_LEVEL = "custom" -MINIMAL_MESSAGES_LEVEL = "minimal" - -PROCESS_MESSAGE_TYPE = "process" -APPLICATION_MESSAGE_TYPE = "application" - -ERROR_FLAG = "error" -WARNING_FLAG = "warning" -INFO_FLAG = "info" -DEFAULT_FLAG = "default" - -BACKGROUNDS_COLORS = {ERROR_FLAG: "red", - WARNING_FLAG: "yellow", - INFO_FLAG: "green", - DEFAULT_FLAG: "white"} - -FONTS_COLORS = {ERROR_FLAG: "red", - WARNING_FLAG: "orange", - INFO_FLAG: "blue", - DEFAULT_FLAG: "black"} - -ERROR_REGEX = re.compile(r"[Ee][Rr]{2}[Oo][Rr][ :]") -WARNING_REGEX = re.compile(r"[Ww][Aa][Rr][Nn][Ii][Nn][Gg][ :]") -INFO_REGEX = re.compile(r"[Ii][Nn][Ff][Oo][ :]") - - -def analyse_log_line(line): - if ERROR_REGEX.search(line) is not None: - flag = ERROR_FLAG - elif WARNING_REGEX.search(line) is not None: - flag = WARNING_FLAG - elif INFO_REGEX.search(line) is not None: - flag = INFO_FLAG - else: - flag = DEFAULT_FLAG - return line, flag - - -############################################################################### -# [Console class] - -class Console(Core.QObject): - """ Class to define a Console object.""" - def __init__(self, q_text_edit_widget): - super(Console, self).__init__() - - self.edit = q_text_edit_widget - - def write(self, line, font_color=DEFAULT_FONT_QCOLOR, - backgroud_color=DEFAULT_BACKGROUND_QCOLOR): - - self.edit.setTextColor(font_color) - self.edit.setTextBackgroundColor(backgroud_color) - self.edit.append(line) - - -############################################################################### -# [LogFilter class] - -class LogFilter(object): - """Class to define a LogFilter object to manage the messages written in the - integrated console.""" - def __init__(self, init_level_str, init_default_bool, init_info_bool, - init_warning_bool, init_error_bool): - """ - -> 'level' sets what sort of messages to display in the console and is - linked to the HMI radio-button choice. - -> 'info', 'warning' and 'error' are booleans to set what logs to - display in the console and is linked to the HMI check-boxes. - """ - self.level = init_level_str - - self.default = init_default_bool - self.info = init_info_bool - self.warning = init_warning_bool - self.error = init_error_bool - - def __repr__(self): - string = "\t| level = {!s:<10} | default = {!s:<5} | info = {!s:<5} |"\ - " warning = {!s:<5} | error = {!s:<5} |" - format_string = string.format(self.level, self.default, self.info, - self.warning, self.error) - return format_string - - def set_level(self, level): - """ - :param level: - -> level = 'minimum' (only important messages) - 'basic' (customized messages) - 'all' (all messages emitted by Makefiles and compilers). - """ - self.level = level - - def set_sensitivity_filter(self, default, info, warning, error): - """ - :param default: - :param info: - :param warning: - :param error: - -> info, warnings and error are booleans. - """ - self.default = default - self.info = info - self.warning = warning - self.error = error - - def write_line_decision(self, flag): - if flag == ERROR_FLAG and self.error: - return True - elif flag == WARNING_FLAG and self.warning: - return True - elif flag == INFO_FLAG and self.info: - return True - elif flag == DEFAULT_FLAG and self.default: - return True - else: - return False diff --git a/sw/supervision/python/lib/database.py b/sw/supervision/python/lib/database.py deleted file mode 100644 index f773ba314b..0000000000 --- a/sw/supervision/python/lib/database.py +++ /dev/null @@ -1,163 +0,0 @@ -# Paparazzi center utilities -# -# Copyright (C) 2016 ENAC, Florian BITARD (intern student) -# -# This file is part of paparazzi. -# -# paparazzi is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# paparazzi is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with paparazzi; see the file COPYING. If not, write to -# the Free Software Foundation, 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -############################################################################### -# [Imports] - - -############################################################################### -# [Configuration class] - -class Configuration(object): - """Class to define a Configuration (old aircraft) object.""" - def __init__(self, name, config_id, airframes, targets): - # Necessary parameters : - self.name = name - self.id = config_id - self.airframes = airframes - - # Not necessary parameters : - self.settings = [] - self.modules = [] - self.flight_plan = [] - self.radio = [] - self.telemetry = [] - - self.color = [] - - self.targets = targets - - def __repr__(self): - string = "| name = {!s:<25} | id = {!s:<3} | airframe = {!s:<65} |" + \ - "targets = {!s:<250} | color = {!s:<15} | " + \ - "radio = {!s:<40} | telemetry = {!s:<45} | " + \ - "flight_plan = {!s:<75} | settings = {!s:<265} | " + \ - "modules = {!s:<265} |" - format_string = string.format(self.name, self.id, self.airframes, - [_ for _ in self.targets.values()], - self.color, self.radio, - self.telemetry, self.flight_plan, - self.settings, self.modules) - return format_string - - -############################################################################### -# [Set class] - -class Set(object): - """Class to define a Set (old configuration) object.""" - def __init__(self, name): - self.name = name - self.configs_names = [] - - def __repr__(self): - string = "| name = {!s:<75} | configs_names = {!s:<680} |" - format_string = string.format(self.name, self.configs_names) - return format_string - - def is_config_in_set(self, config): - return config.id in self.configs_names - - -############################################################################### -# [Target class] - -class Target(object): - """Class to define a Target object.""" - def __init__(self, name, board, ): - self.name = name - self.board = board - - self.defines = None - - def __repr__(self): - string = "| name = {!s:<15} | board = {!s:<20} |" - format_string = string.format(self.name, self.board) - return format_string - - -############################################################################### -# [Device class] - -class Device(object): - """Class to define a Device (old flash mode) object.""" - def __init__(self, name, variable_name="", variable_value=""): - self.name = name - self.variable = (variable_name, variable_value) - self.boards_regex = [] - - def __repr__(self): - string = "| name = {!s:<25} | variable = {!s:<35} | " + \ - "boards_regex = {!s:<125} |" - format_string = string.format(self.name, self.variable, - self.boards_regex) - return format_string - - -############################################################################### -# [Session class] - -class Session(object): - """Class to define a Session object.""" - def __init__(self, name, programs): - self.name = name - self.programs = programs - - def __repr__(self): - string = "| name = {!s:<30} | programs = {!s:<1300} |" - format_string = string.format(self.name, - [_ for _ in self.programs.values()]) - return format_string - - -############################################################################### -# [Program class] - -class Program(object): - """Class to define a Program (old tool) object.""" - def __init__(self, name, command, options, icon=None, favorite=None, blacklisted=None): - self.name = name - self.command = command - self.options = options - self.icon = icon - self.favorite = favorite - self.blacklisted = blacklisted - - def __repr__(self): - string = "\t| name = {!s:<30} | command = {!s:<60} | options = {!s:<70} | icon={!s} |" - format_string = string.format(self.name, self.command, self.options, self.icon) - return format_string - - -############################################################################### -# [Cache class] - -class Cache(object): - """Class to define a Cache (old %gconf) object.""" - def __init__(self, last_update_time): - self.last_update = last_update_time - - self.main_window_shape = (0, 0) - self.last_set = None - self.last_configuration = None - self.last_target = None - self.last_session = None - self.last_device = None diff --git a/sw/supervision/python/lib/default_cache.xml b/sw/supervision/python/lib/default_cache.xml deleted file mode 100644 index 0201937d78..0000000000 --- a/sw/supervision/python/lib/default_cache.xml +++ /dev/null @@ -1,15 +0,0 @@ - -- -- -- -- -- -- -- -- -- -- -- -- -- -- diff --git a/sw/supervision/python/lib/environment.py b/sw/supervision/python/lib/environment.py deleted file mode 100644 index 6315673439..0000000000 --- a/sw/supervision/python/lib/environment.py +++ /dev/null @@ -1,91 +0,0 @@ -# Paparazzi center utilities -# -# Copyright (C) 2016 ENAC, Florian BITARD (intern student) -# -# This file is part of paparazzi. -# -# paparazzi is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# paparazzi is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with paparazzi; see the file COPYING. If not, write to -# the Free Software Foundation, 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -############################################################################### -# [Imports] - -import os -from sys import platform as os_name -import logging - - -############################################################################### -# [Constants] - -LOGGER = logging.getLogger("[ENV]") -OS = os_name - -SRC_NAME = "PAPARAZZI_SRC" -HERE_TO_SRC = "../../../.." -CONF_NAME = "PAPARAZZI_CONF" -HOME_TO_CONF = "conf" -HOME_NAME = "PAPARAZZI_HOME" -HOME_TO_VAR = "var" -IVY_BUS_NAME = "IVY_BUS" - - -def get_src_dir(src_name): - current_dir = os.path.dirname(os.path.abspath(__file__)) - src_dir = os.path.normpath(os.path.join(current_dir, HERE_TO_SRC)) - return os.getenv(src_name, src_dir) - -PAPARAZZI_SRC = get_src_dir(SRC_NAME) -LOGGER.debug("%s=%s", SRC_NAME, PAPARAZZI_SRC) - - -def get_home_dir(home_name): - return os.getenv(home_name, get_src_dir(SRC_NAME)) - -PAPARAZZI_HOME = get_home_dir(HOME_NAME) -LOGGER.info("%s=%s", HOME_NAME, PAPARAZZI_HOME) - - -def get_conf_dir(conf_name): - conf_dir = os.path.join(PAPARAZZI_HOME, HOME_TO_CONF) - if os.path.exists(conf_dir): - return os.getenv(conf_name, conf_dir) - else: - LOGGER.error("'%s' directory doesn't exist !", conf_dir) - -PAPARAZZI_CONF = get_conf_dir(CONF_NAME) - - -def get_ivy_bus(ivy_bus_name): - supposed_ivy_bus = os.getenv(ivy_bus_name) - if supposed_ivy_bus is not None: - return supposed_ivy_bus - elif OS == 'linux': - return "127.255.255.255:2010" - elif OS == 'linux2': - return "127.255.255.255:2010" - elif OS == 'darwin': - return "224.5.6.7:8910" - LOGGER.error("Unknown Ivy bus for the current OS !") - -IVY_BUS = get_ivy_bus(IVY_BUS_NAME) -LOGGER.debug("%s=%s", HOME_NAME, PAPARAZZI_HOME) - -RUN_VERSION_EXE_NAME = "paparazzi_version" -RUN_VERSION_EXE = os.path.join(PAPARAZZI_HOME, RUN_VERSION_EXE_NAME) - -BUILD_VERSION_FILE_NAME = "build_version.txt" -BUILD_VERSION_FILE = os.path.join(PAPARAZZI_HOME, HOME_TO_VAR, - BUILD_VERSION_FILE_NAME) diff --git a/sw/supervision/python/lib/gui.py b/sw/supervision/python/lib/gui.py deleted file mode 100644 index cd9c2f19ee..0000000000 --- a/sw/supervision/python/lib/gui.py +++ /dev/null @@ -1,69 +0,0 @@ -# Paparazzi center utilities -# -# Copyright (C) 2016 ENAC, Florian BITARD (intern student) -# -# This file is part of paparazzi. -# -# paparazzi is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# paparazzi is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with paparazzi; see the file COPYING. If not, write to -# the Free Software Foundation, 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -############################################################################### -# [Imports] - -import PyQt5.QtGui as Gui - - -############################################################################### -# [Constants] - -NORMAL_CURSOR_SHAPE = "normal" -WAIT_CURSOR_SHAPE = "wait" - - -############################################################################### -# [Functions] - -def generate_qcolor(color): - qcolor = Gui.QColor() - qcolor.setNamedColor(color) - return qcolor - - -def generate_widget_palette(widget, qcolor): - qpalette = Gui.QPalette(widget.palette()) - qpalette.setColor(Gui.QPalette.Background, qcolor) - return qpalette - - -def generate_qcursor(shape): - qcursor = Gui.QCursor() - if shape == WAIT_CURSOR_SHAPE: - qcursor.setShape(16) - elif shape == NORMAL_CURSOR_SHAPE: - qcursor.setShape(0) - else: - qcursor.setShape(0) - return qcursor - - -def generate_qpixmap(picture_path=""): - return Gui.QPixmap(picture_path) - - -def generate_qicon(icon_path=None): - if icon_path is not None: - return Gui.QIcon(icon_path) - else: - return Gui.QIcon() diff --git a/sw/supervision/python/main.py b/sw/supervision/python/main.py deleted file mode 100755 index f5a87f3f29..0000000000 --- a/sw/supervision/python/main.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python3 - -# Paparazzi center utilities -# -# Copyright (C) 2016 ENAC, Florian BITARD (intern student) -# -# This file is part of paparazzi. -# -# paparazzi is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# paparazzi is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with paparazzi; see the file COPYING. If not, write to -# the Free Software Foundation, 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -############################################################################### -# [Imports] - -import lib.environment as env -import hmi - -import PyQt5.QtWidgets as Widgets -import sys -import os - - -############################################################################### -# [Main function] -def main(): - """Main program : creates the main window and starts the main loop.""" - - # Set this file's location as working directory - os.chdir(os.path.dirname(os.path.abspath(__file__))) - - # Set the environment variables (useful for some processes) : - os.putenv(env.HOME_NAME, env.PAPARAZZI_HOME) - os.putenv(env.SRC_NAME, env.PAPARAZZI_SRC) - - app = Widgets.QApplication(sys.argv) - - # TODO : SET APPLICATION ICON IN THE LAUNCHER (UBUNTU : UNITY) - - main_window = hmi.Hmi() - main_window.init_all_hmi() - main_window.show() - - sys.exit(app.exec_()) - - -if __name__ == "__main__": - main() diff --git a/sw/supervision/python/operation_panel.py b/sw/supervision/python/operation_panel.py new file mode 100644 index 0000000000..db0601844d --- /dev/null +++ b/sw/supervision/python/operation_panel.py @@ -0,0 +1,13 @@ +# Copyright (C) 2008-2022 The Paparazzi Team +# released under GNU GPLv2 or later. See COPYING file. + +from generated.ui_operation_panel import Ui_OperationPanel +from PyQt5.QtWidgets import * + + +class OperationPanel(QWidget, Ui_OperationPanel): + + def __init__(self, parent=None): + QWidget.__init__(self, parent=parent) + self.setupUi(self) + self.session.set_console(self.console) diff --git a/sw/supervision/python/paparazzicenter.py b/sw/supervision/python/paparazzicenter.py new file mode 100755 index 0000000000..22bd241f5e --- /dev/null +++ b/sw/supervision/python/paparazzicenter.py @@ -0,0 +1,128 @@ +#!/usr/bin/python3 +# Copyright (C) 2008-2022 The Paparazzi Team +# released under GNU GPLv2 or later. See COPYING file. +import os +import conf +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 app_settings import AppSettings + + +class PprzCenter(QMainWindow): + def __init__(self, parent=None): + QMainWindow.__init__(self, parent=parent) + self.setWindowTitle("Paparazzi Center") + 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.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.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() + + 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 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)) + + self.setMenuBar(menubar) + + def closeEvent(self, e: QtGui.QCloseEvent) -> None: + if self.operation_panel.session.any_program_running(): + 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: + if utils.get_settings().value("always_keep_changes", False, bool): + self.configuration_panel.conf.save() + 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): + 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() + self.save_gconf() + e.accept() + + 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_session", self.operation_panel.session.get_current_session()) + + def update_left_pane_width(self, pos, index): + utils.get_settings().setValue("ui/left_pane_width", pos) + + def fill_status_bar(self): + home_widget = QWidget() + home_lay = QHBoxLayout(home_widget) + home_lay.addWidget(QLabel("HOME: ", home_widget)) + home_button = QPushButton(utils.PAPARAZZI_HOME, home_widget) + home_lay.addWidget(home_button) + home_button.clicked.connect(lambda: utils.open_terminal(utils.PAPARAZZI_HOME)) + self.statusBar().addPermanentWidget(home_widget) + self.statusBar().addPermanentWidget(utils.make_line(None, True)) + label_version = QLabel("Version={}".format(utils.get_version())) + self.statusBar().addPermanentWidget(label_version) + self.statusBar().addPermanentWidget(utils.make_line(None, True)) + label_build = QLabel("Build={}".format(utils.get_build_version())) + self.statusBar().addPermanentWidget(label_build) + + def handle_error(self, msg): + self.status_msg.setText(msg) + self.statusBar().setStyleSheet("background-color: red;") + # self.statusBar().showMessage(msg) + + def clear_error(self): + self.status_msg.setText("") + self.statusBar().setStyleSheet("") + + +if __name__ == "__main__": + import sys + app = QApplication(sys.argv) + main_window = PprzCenter() + main_window.show() + # qApp.aboutToQuit.connect(main_window.quit) + sys.exit(app.exec_()) + diff --git a/sw/supervision/python/parser.py b/sw/supervision/python/parser.py deleted file mode 100644 index edcec8f21d..0000000000 --- a/sw/supervision/python/parser.py +++ /dev/null @@ -1,855 +0,0 @@ -# Paparazzi center utilities -# -# Copyright (C) 2016 ENAC, Florian BITARD (intern student) -# -# This file is part of paparazzi. -# -# paparazzi is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# paparazzi is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with paparazzi; see the file COPYING. If not, write to -# the Free Software Foundation, 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -############################################################################### -# [Imports] - -import lib.database as db -import lib.environment as env - -import xml.etree.ElementTree as Et -import os -import re -import logging - -from typing import List, Dict -import shutil - - -############################################################################### -# [Constants] - -STRINGS_FALSE = ["False", "false", None, "0"] - -LOGGER = logging.getLogger("[PARSER]") - -XML_EXT = ".xml" -TEST_XML = "test.xml" - -# GLOBAL XML TREE REFERENCES : -NAME_REF = "name" -VALUE_REF = "value" -CONSTANT_REF = "constant" -VARIABLE_REF = "variable" -MODE_REF = "mode" -FAVORITE_REF = "favorite" - -# REFERENCES AND STRUCTURES OF CONF XML FILES : -# CONF_STRUCTURE = [(node_name, [node_attributes], -# [(child_name, [child_attributes], -# [children_of_child...]), -# (...) -# ]) -# ] - -# CACHE : -CACHE = "cache" -CACHE_FILE = "." + CACHE + XML_EXT -DEFAULT_CACHE_FILE = "default_cache" + XML_EXT -DEFAULT_CACHE_PATH = os.path.join("lib", DEFAULT_CACHE_FILE) - -LAST_GEOMETRY = "last_geometry" -LAST_GEOMETRY_REF = "system/window/geometry" -LAST_SET = "last_set" -LAST_SET_REF = "data/set" -LAST_CONFIG = "last_config" -LAST_CONFIG_REF = "data/config" -LAST_TARGET = "last target" -LAST_TARGET_REF = "data/target" -LAST_LOG_FILTERS = "last log filters" -LAST_LOG_FILTERS_REF = "system/filters" -LAST_DEVICE = "last device" -LAST_DEVICE_REF = "data/device" -LAST_SESSION = "last session" -LAST_SESSION_REF = "data/session" - -# SET : -SET = "conf" -SET_REGEX = re.compile(r"" + SET + "([_-][\w]*)?\.xml$") - -CONF_REF = "aircraft" -ID_REF = "ac_id" -AIRFRAME_REF = "airframe" -SETTINGS_REF = "settings" -MODULES_REF = "module" -FP_REF = "flight_plan" -RADIO_REF = "radio" -TELEMETRY_REF = "telemetry" -SETTINGS_MODULES_REF = "settings_modules" -COLOR_REF = "gui_color" - -CONFIG_TAG_REF = CONF_REF - -SET_STRUCTURE = [(SET, [], - [(CONF_REF, [NAME_REF, ID_REF, AIRFRAME_REF, RADIO_REF, - TELEMETRY_REF, FP_REF, SETTINGS_REF, - SETTINGS_MODULES_REF, COLOR_REF], - []) - ]) - ] - - -# DEVICE : -DEVICE = "flash_modes" -DEVICES_FILE = DEVICE + XML_EXT - -BOARD_REF = "board" -BOARDS_REF = "boards" - -DEVICE_TAG_REF = MODE_REF - -DEVICE_STRUCTURE = [(DEVICE, [], - [(MODE_REF, [NAME_REF], - [(VARIABLE_REF, [NAME_REF, VALUE_REF], - [(BOARDS_REF, [], - [(BOARD_REF, [NAME_REF], - []) - ]) - ]) - ]) - ]) - ] - -# DEFAULT DEVICE : -DEFAULT_DEVICE_NAME = " __Default__ " -DEFAULT_DEVICE = db.Device(DEFAULT_DEVICE_NAME) - -# TOOLS -TOOLS = "tools" - -# CONTROL_PANEL : -CONTROL_PANEL = "control_panel" -CONTROL_PANEL_FILE = CONTROL_PANEL + XML_EXT - -SECTION_REF = "section" -PROGRAM_REF = "program" -SESSION_REF = "session" -COMMAND_REF = "command" -ICON_REF = "icon" -FLAG_REF = "flag" -OPTION_REF = "arg" - -SESSION_TAG_REF = "/".join((SECTION_REF, SESSION_REF)) - -CONTROL_PANEL_STRUCTURE = [(CONTROL_PANEL, [NAME_REF], - [(SECTION_REF, [NAME_REF], - [(PROGRAM_REF, [NAME_REF, COMMAND_REF], - [(OPTION_REF, [FLAG_REF, CONSTANT_REF], - []) - ]) - ]), - (SECTION_REF, [NAME_REF], - [(SESSION_REF, [NAME_REF], - [(PROGRAM_REF, [NAME_REF], - [(OPTION_REF, [FLAG_REF, CONSTANT_REF], - []) - ]) - ]) - ]) - ]) - ] - -# DEFAULT SESSIONS : -SIMULATOR_OBJECT = db.Program("Simulator", "sw/simulator/pprzsim-launch", - [("-a", "@AIRCRAFT"), ("-t", "@TARGET"), - "--boot", "--norc"]) -GCS_OBJECT = db.Program("GCS", "sw/ground_segment/cockpit/gcs", []) -SERVER_OBJECT = db.Program("Server", "sw/ground_segment/tmtc/server", ["-n"]) -PLAYER_OBJECT = db.Program("Log File Player", "sw/logalizer/play", []) - -SIMULATION_NAME = "Simulation" -SIMULATION_SESSION = db.Session(SIMULATION_NAME, - {SIMULATOR_OBJECT.name: SIMULATOR_OBJECT, - GCS_OBJECT.name: GCS_OBJECT, - SERVER_OBJECT.name: SERVER_OBJECT}) -SESSIONS_COMBO_SEP = " - - - - - - - - - - " -REPLAY_NAME = "Replay" -REPLAY_SESSION = db.Session(REPLAY_NAME, - {PLAYER_OBJECT.name: PLAYER_OBJECT, - SERVER_OBJECT.name: SERVER_OBJECT, - GCS_OBJECT.name: GCS_OBJECT}) - -# AIRFRAME : -FIRMWARE_REF = "firmware" -TARGET_REF = "target" -BOARD_REF = "board" - -TARGET_TAG_REF = "/".join((FIRMWARE_REF, TARGET_REF)) - -AIRFRAME_STRUCTURE = [] # TODO - - -############################################################################### -# [Functions] - -def full_path_to_filename(path): - return os.path.basename(path) - - -def full_to_conf_path(full_path): - return os.path.relpath(full_path, start=env.PAPARAZZI_CONF) - - -def filename_to_conf_path(filename): - return os.path.join(env.PAPARAZZI_CONF, filename) - - -def find_unused_item_name(dictionary, name): - new_name = name - nb = 0 - while new_name in dictionary.keys(): - nb += 1 - new_name = new_name.split("[")[0] + "[" + str(nb) + "]" - return new_name - - -############################################################################### -# [Functions] Data management functions - -def sorted_sets_names(sets): - sets_names = [set_object.name for set_object in sets.values()] - return sorted(sets_names) - - -def sorted_current_configs_names(configurations, current_set): - configs_names = [configurations[config_name].name - for config_name in current_set.configs_names] - return sorted(configs_names) - - -def sorted_current_targets_names(targets): - target_names = [target.name for target in targets.values()] - return sorted(target_names) - - -def sorted_sessions_names(sessions): - sessions_names = [session.name for session in sessions.values()] - sorted_names = sorted(sessions_names) - old_simulation_index = sorted_names.index(SIMULATION_NAME) - sorted_names.insert(0, sorted_names.pop(old_simulation_index)) - old_replay_index = sorted_names.index(REPLAY_NAME) - sorted_names.insert(1, sorted_names.pop(old_replay_index)) - sorted_names.insert(2, SESSIONS_COMBO_SEP) - return sorted_names - - -def sorted_current_programs_names(current_session): - programs_names = [program.name for program - in current_session.programs.values()] - return sorted(programs_names) - - -def sorted_current_devices_names(devices): - devices_names = [device.name for device in devices] - return sorted(devices_names) - - -def sorted_tools_names(tools): - tools_names = [tool.name for tool in tools.values()] - return sorted(tools_names) - - -############################################################################### -# [Functions] Load cache from '.cache' file - -def parse_cache_file(mode, cache_file, - geometry_str=None, set_str=None, config_str=None, - target_str=None, log_filters_str=None, - device_str=None, session_str=None): - """ - :param mode: - :param cache_file: - :param geometry_str: - :param set_str: - :param config_str: - :param target_str: - :param log_filters_str: - :param device_str: - :param session_str: - -> Scan 'cache_file' to get tags by name reference. - -> Read values of tags in 'r' mode. - -> Write new values of tags in 'w' mode. - -> Except an incorrect XML format and raise ERROR. - """ - cache_dict = {} - try: - try: - cache_tree = Et.parse(cache_file) - except FileNotFoundError: - cache_tree = Et.parse(DEFAULT_CACHE_PATH) - - last_geometry_tag = cache_tree.find(LAST_GEOMETRY_REF) - last_set_tag = cache_tree.find(LAST_SET_REF) - last_config_tag = cache_tree.find(LAST_CONFIG_REF) - last_target_tag = cache_tree.find(LAST_TARGET_REF) - last_log_filters_tag = cache_tree.find(LAST_LOG_FILTERS_REF) - last_device_tag = cache_tree.find(LAST_DEVICE_REF) - last_session_tag = cache_tree.find(LAST_SESSION_REF) - - last_tags_list = [last_geometry_tag, last_set_tag, - last_config_tag, last_target_tag, - last_log_filters_tag, last_device_tag, - last_session_tag] - if mode == "r": - for key, tag in zip([LAST_GEOMETRY, LAST_SET, - LAST_CONFIG, LAST_TARGET, - LAST_LOG_FILTERS, LAST_DEVICE, - LAST_SESSION], - last_tags_list): - cache_dict[key] = tag.get(VALUE_REF) - return cache_dict - - elif mode == "w": - for tag, string in zip(last_tags_list, - [geometry_str, set_str, - config_str, target_str, - log_filters_str, device_str, - session_str]): - tag.set(VALUE_REF, string) - cache_tree.write(cache_file) - - except Et.ParseError as msg: - LOGGER.error("ERROR in syntax of XML file : '%s'. " - "Original message : '%s'.", cache_file, msg) - - -def load_cache(): - """ - -> Scan the 'python' current directory to find the '.cache.xml' file. - -> Parse the cache file withe the 'w' mode to load the last values. - -> Except multiple cache files and raise an ERROR if so. - """ - cache_file = None - for root, dirs, files in os.walk("./"): - for file in files: - ext = os.path.splitext(file)[1] - if ext == XML_EXT and file == CACHE_FILE: - cache_file = os.path.join(root, file) - break - if cache_file is not None: - cache = parse_cache_file("r", cache_file) - else: - cache = parse_cache_file("r", DEFAULT_CACHE_PATH) - cache_file = CACHE_FILE - - LOGGER.error("No cache file found ! Default cache '%s' loaded.", - DEFAULT_CACHE_PATH) - print("No cache file found ! Default cache '%s' loaded." % - DEFAULT_CACHE_PATH) - - if logging.DEBUG: - LOGGER.debug("Cache dictionary :\n%s", cache) - return cache, cache_file - -def delete_cache(): - """ - -> Scan the 'python' current directory to find the '.cache.xml' file. - -> Remove if found - """ - cache_file = None - for root, dirs, files in os.walk("./"): - for file in files: - ext = os.path.splitext(file)[1] - if ext == XML_EXT and file == CACHE_FILE: - cache_file = os.path.join(root, file) - break - if cache_file is not None: - cache = os.remove(cache_file) - LOGGER.debug("Deleting cache file '%s'\n", cache_file) - else: - LOGGER.debug("No cache to delete\n") - - -############################################################################### -# [Functions] Load files to init HMI - -def load_init_files(conf_path): - """ - :param conf_path: - -> Scan the conf directory to find the configuration files : all files - matching with '*conf*.xml', 'control_panel.xml' and 'flash_modes.xml'. - -> Show the result of scan if DEBUG mode is on (main.py) - """ - conf_files, devices_files = [], [] - cp_file = None - - cp_path = conf_path + "/" + CONTROL_PANEL + XML_EXT - if os.path.exists(cp_path): - cp_file = cp_path - else: - raise Exception("%s not found!"% conf_path) - - tools_path = conf_path + "/" + TOOLS - if not os.path.exists(tools_path): - raise Exception("%s not found!" % tools_path) - - for root, dirs, files in os.walk(conf_path): - for file in files: - ext = os.path.splitext(file)[1] - if ext == XML_EXT: - xml_file = os.path.join(root, file) - if SET_REGEX.search(file) is not None \ - and file != "%gconf.xml"\ - and xml_file != env.PAPARAZZI_CONF+"/conf.xml": - conf_files.append(xml_file) - elif file == CONTROL_PANEL_FILE and "airframes" not in root: - pass - elif file == DEVICES_FILE: - devices_files.append(xml_file) - - result = "{} startup files found." # exclude control_panel.xml - files_nb = sum((len(conf_files), len(devices_files))) - info = result.format(files_nb) - - if logging.DEBUG: - LOGGER.debug("'conf' files :") - for file in conf_files: - LOGGER.debug(file) - LOGGER.debug("'devices' file(s) :") - for file in devices_files: - LOGGER.debug(file) - LOGGER.debug("'control_panel' file(s) :") - LOGGER.debug(cp_file) - return conf_files, cp_file, tools_path, devices_files, info - - -############################################################################### -# [Functions] Load sets and configurations from 'conf' files - -def set_config_details(config_object, tag): - """ - :param config_object: - :param tag: - -> Parse values of a configuration in the given XML tag element. - -> Fills attributes of the given configuration object. - """ - variables = [[] for _ in range(6)] - keys = [SETTINGS_REF, SETTINGS_MODULES_REF, FP_REF, RADIO_REF, - TELEMETRY_REF, COLOR_REF] - for i, key in zip(range(6), keys): - items = tag.get(key) - if items: - for item in items.split(" "): - variables[i].append(item) - - config_object.settings = variables[0] - config_object.modules = variables[1] - config_object.flight_plan = variables[2] - config_object.radio = variables[3] - config_object.telemetry = variables[4] - config_object.color = variables[5] - - -def parse_targets(airframe_file): - """ - :param airframe_file: - -> Parse values of a target in the airframe file given. - -> Except an incorrect XML format and raise ERROR. - """ - available_targets = {} - try: - airframe_tree = Et.parse(filename_to_conf_path(airframe_file)) - targets_tags = airframe_tree.findall(TARGET_TAG_REF) - for target_tag in targets_tags: - name = target_tag.get(NAME_REF) - board = target_tag.get(BOARD_REF) - target_object = db.Target(name, board) - available_targets[target_object.name] = target_object - - except Et.ParseError as msg: - LOGGER.error("ERROR in syntax of XML file : '%s'. " - "Original message : '%s'.", airframe_file, msg) - except (FileNotFoundError, IOError) as msg: - LOGGER.error("ERROR file '%s' not found or IO error" - "Original message : '%s'.", airframe_file, msg) - return available_targets - - -def parse_conf_files(set_files): - """ - :param set_files: - -> Parse values of a target in the airframe file given. - -> Except an incorrect XML format and raise ERROR. - """ - configs, sets = {}, {} - for set_file in set_files: - try: - set_name = full_to_conf_path(set_file) - set_object = db.Set(set_name) - set_tree = Et.parse(set_file) - config_tags = set_tree.findall(CONFIG_TAG_REF) - for tag in config_tags: - config_name = tag.get(NAME_REF) - config_id = tag.get(ID_REF) - config_airframes = tag.get(AIRFRAME_REF).split(" ") - config_targets = parse_targets(config_airframes[0]) - config_object = db.Configuration(config_name, config_id, - config_airframes, - config_targets) - if config_object.id not in set_object.configs_names: - set_config_details(config_object, tag) - configs[config_object.name] = config_object - set_object.configs_names.append(config_object.name) - else: - LOGGER.error("'%s' configuration can't be loaded in " - "'%s' set because ID already exists !", - config_object.name, set_object.name) - sets[set_name] = set_object - - except Et.ParseError as msg: - LOGGER.error("ERROR in syntax of XML file : '%s'. " - "Original message : '%s'.", set_file, msg) - return configs, sets - - -def load_sets_and_configurations(set_files): - """ - :param set_files: - -> Parse the sets and the configurations from the '*conf*.xml' files. - -> Show the result of scan if DEBUG mode is on (main.py) - """ - configurations, sets = parse_conf_files(set_files) - result = "{} sets and {} configurations found." - sets_nb, configs_nb = len(sets), len(configurations) - info = result.format(sets_nb, configs_nb) - - if logging.DEBUG: - sets_str = "Sets :\n" - for set_object in sets.values(): - sets_str += str(set_object) + "\n" - LOGGER.debug(sets_str) - configs_str = "Configurations :\n" - for config_object in configurations.values(): - configs_str += str(config_object) + "\n" - LOGGER.debug(configs_str) - return sets, configurations, info - - -def save_configuration(conf_file, config_object): - """ - :param conf_file: - :param config_object: - -> Set the new values of the configuration object given into the - corresponding XML file. - """ - conf_file_path = filename_to_conf_path(conf_file) - - conf_tree = Et.parse(conf_file_path) - config_tags = conf_tree.findall(CONFIG_TAG_REF) - for tag in config_tags: - if tag.get(NAME_REF) == config_object.name: - attributes = [AIRFRAME_REF, SETTINGS_REF, - SETTINGS_MODULES_REF, FP_REF, - RADIO_REF, TELEMETRY_REF] - new_values = [config_object.airframes, config_object.settings, - config_object.modules, config_object.flight_plan, - config_object.radio, config_object.telemetry] - for attribute, values in zip(attributes, new_values): - string = " ".join(values) - tag.set(attribute, string) - conf_tree.write(conf_file_path) - - -############################################################################### -# [Functions] Load sets devices from 'flash_modes' file - -def parse_devices_file(devices_file): - """ - :param devices_file: - -> Parse values of a device in the 'flash_modes' file given. - -> Except an incorrect XML format and raise ERROR. - """ - devices = {} - try: - devices_tree = Et.parse(devices_file) - devices_tags = devices_tree.findall(DEVICE_TAG_REF) - for device_tag in devices_tags: - device_name = device_tag.get(NAME_REF) - variable_tag = device_tag.find(VARIABLE_REF) - variable_name = variable_tag.get(NAME_REF) - variable_value = variable_tag.get(VALUE_REF) - device_object = db.Device(device_name, - variable_name, variable_value) - for board_tag in device_tag.find(BOARDS_REF): - board_name = board_tag.get(NAME_REF) - device_object.boards_regex.append(board_name) - devices[device_name] = device_object - except Et.ParseError as msg: - LOGGER.error("ERROR in syntax of XML file : '%s'. " - "Original message : '%s'.", devices_file, msg) - return devices - - -def load_devices(devices_file): - """ - :param devices_file: - -> Parse the devices from the 'flash_modes.xml' files. - -> Show the result of scan if DEBUG mode is on (main.py) - """ - devices = parse_devices_file(devices_file) - default_object = db.Device("Default") - devices[default_object.name] = default_object - - devices[DEFAULT_DEVICE.name] = DEFAULT_DEVICE - - result = "{} devices found." - devices_nb = len(devices) - info = result.format(devices_nb) - - if logging.DEBUG: - devices_str = "Devices :\n" - for device_object in devices.values(): - devices_str += str(device_object) + "\n" - LOGGER.debug(devices_str) - - return devices, info - - -############################################################################### -# [Functions] Load tools and sessions from 'control_panel' file - -def parse_arg_option(option_tag): - """ - :param option_tag: - -> Fill an option triplet (flag, argument type : 'constant' or 'variable', - value of the argument) from an option tag in the XML tree. - """ - option_flag = option_tag.get(FLAG_REF) - constant = option_tag.get(CONSTANT_REF) - variable = option_tag.get(VARIABLE_REF) - if constant is not None: - option = (option_flag, constant) - elif variable is not None: - option = (option_flag, variable) - else: - option = option_flag - return option - - -def parse_tools(tools_path): - """ - :param tools_path: - -> Parse all tools files in the 'tools_path' directory. - -> Except an incorrect XML format and raise ERROR. - """ - tools = {} - blacklisted_tools = [] - blacklist = tools_path + "/" + "blacklisted" - if os.path.exists(blacklist): - with open(blacklist, 'r') as blacklist_fic: - for line in blacklist_fic: - line = line.strip() - if line != "" and line[0] != "#": - blacklisted_tools.append(line) - - for file in os.listdir(tools_path): - if file.endswith(".xml"): - file_path = tools_path + "/" + file - try: - tree = Et.parse(file_path) - tool_tag = tree.getroot() - if tool_tag.tag == PROGRAM_REF: - tool_name = tool_tag.get(NAME_REF) - tool_command = tool_tag.get(COMMAND_REF) - icon = tool_tag.get(ICON_REF) - fav = tool_tag.get(FAVORITE_REF) - favorite = fav if fav is None else (fav not in STRINGS_FALSE) - - options = [] - for option_tag in tool_tag: - option = parse_arg_option(option_tag) - options.append(option) - blacklisted = True if tool_name in blacklisted_tools else False - tool_object = db.Program(tool_name, tool_command, options, icon, favorite=favorite, blacklisted=blacklisted) - tools[tool_name] = tool_object - - except Et.ParseError as msg: - LOGGER.error("ERROR in syntax of XML file : '%s'. " - "Original message : '%s'.", file, msg) - return tools - - -def parse_sessions(cp_file, tools): - """ - :param cp_file: - :param tools: - -> Parse all sessions in the 'control_panel.xml' file given. - -> Except an incorrect XML format and raise ERROR. - """ - sessions = {} - try: - cp_tree = Et.parse(cp_file) - sessions_tags = cp_tree.findall(SESSION_TAG_REF) - for session_tag in sessions_tags: - session_name = session_tag.get(NAME_REF) - session_programs = {} - for program_tag in session_tag: - program_name = program_tag.get(NAME_REF) - command = tools[program_name].command - options = [] - for option_tag in program_tag: - option = parse_arg_option(option_tag) - options.append(option) - program_object = db.Program(program_name, command, options) - session_programs[program_name] = program_object - session_object = db.Session(session_name, session_programs) - sessions[session_name] = session_object - - except Et.ParseError as msg: - LOGGER.error("ERROR in syntax of XML file : '%s'. " - "Original message : '%s'.", cp_file, msg) - return sessions - - -def load_sessions_and_programs(cp_file, tools_path): - """ - :param cp_file: - :param tools_path: - -> Parse the tools and sessions from the 'tools:*xml' files. - -> Add the default sessions 'simulation' & replay. - -> Show the result of scan if DEBUG mode is on (main.py) - """ - tools = parse_tools(tools_path) - sessions = parse_sessions(cp_file, tools) - - sessions[SIMULATION_SESSION.name] = SIMULATION_SESSION - sessions[REPLAY_SESSION.name] = REPLAY_SESSION - - result = "{} tools and {} sessions found." - tools_nb, sessions_nb = len(tools), len(sessions) - info = result.format(tools_nb, sessions_nb) - - if logging.DEBUG: - tools_str = "Tools :\n" - for tool_object in tools.values(): - tools_str += str(tool_object) + "\n" - LOGGER.debug(tools_str) - sessions_str = "Sessions :\n" - for session_object in sessions.values(): - sessions_str += str(session_object) + "\n" - LOGGER.debug(sessions_str) - - return tools, sessions, info - - -def save_session(cp_file, session_object): - """ - :param cp_file: - :param session_object: - -> Set the new values of the session object given into the - corresponding XML file. - """ - cp_file_path = filename_to_conf_path(cp_file) - - cp_tree = Et.parse(cp_file_path) - cp_tags = cp_tree.findall(SESSION_TAG_REF) - for session_tag in cp_tags: - if session_tag.get(NAME_REF) == session_object.name: - session_tag.clear() - session_tag.set(NAME_REF, session_object.name) - for program in session_object.programs.values(): - program_tag = Et.SubElement(session_tag, PROGRAM_REF, - {NAME_REF: program.name}) - for option in program.options: - attributes = {} - if type(option) is tuple: - attributes[FLAG_REF] = option[0] - attributes[CONSTANT_REF] = option[1] - else: - attributes[FLAG_REF] = option - _option_tag = Et.SubElement(program_tag, OPTION_REF, - attributes) - cp_tree.write(cp_file_path) - - -############################################################################### -# [Data class] - -class Data(object): - """Class to manage a Data meta-object that gathers all the useful data - parsed in the various XML files of the /conf directory.""" - def __init__(self, conf_path): - self.conf_path = conf_path - - self.cache_file = None - self.conf_files = [] - self.devices_file = None - self.cp_file = None - self.tools_path = None - - self.cache = {} - self.configurations = {} - self.sets = {} - self.devices = {} - self.tools = {} - self.sessions = {} - - self.init_data() - -############################################################################### -# [Data methods] Init data methods - - def init_data(self): - self.load_cache() - self.load_conf_files() - self.load_sets_and_configs() - self.load_devices() - self.load_sessions_and_programs() - - LOGGER.info("All data loaded.\n") - - def load_cache(self): - LOGGER.info("Loading cache...") - self.cache, self.cache_file = load_cache() - LOGGER.info("Cache loaded.\n") - - def load_conf_files(self): - LOGGER.info("Scanning current directory...") - self.conf_files, self.cp_file, self.tools_path, self.devices_file, load_info = \ - load_init_files(self.conf_path) - LOGGER.debug(load_info) - LOGGER.info("End of scan.\n") - - def load_sets_and_configs(self): - LOGGER.info("Loading sets and configurations...") - self.sets, self.configurations, \ - load_info = load_sets_and_configurations(self.conf_files) - LOGGER.debug(load_info) - LOGGER.info("Sets and configurations loaded.\n") - - def load_devices(self): - LOGGER.info("Loading devices...") - if len(self.devices_file) == 1: - self.devices, load_info = load_devices(self.devices_file[0]) - LOGGER.debug(load_info) - LOGGER.info("Devices loaded.\n") - else: - LOGGER.error("Multiple '%s' XML files !", DEVICE) - - def load_sessions_and_programs(self): - LOGGER.info("Loading programs and sessions...") - if self.cp_file is not None and self.tools_path is not None: - self.tools, self.sessions, \ - load_info = load_sessions_and_programs(self.cp_file, self.tools_path) - LOGGER.debug(load_info) - LOGGER.info("Programs and sessions loaded.\n") - else: - LOGGER.error("ERROR : control_panel.xml or tools.xml not found!") diff --git a/sw/supervision/python/processes.py b/sw/supervision/python/processes.py deleted file mode 100644 index 0a8b2c0096..0000000000 --- a/sw/supervision/python/processes.py +++ /dev/null @@ -1,238 +0,0 @@ -# Paparazzi center utilities -# -# Copyright (C) 2016 ENAC, Florian BITARD (intern student) -# -# This file is part of paparazzi. -# -# paparazzi is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# paparazzi is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with paparazzi; see the file COPYING. If not, write to -# the Free Software Foundation, 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -############################################################################### -# [Imports] - -import lib.environment as env -import lib.console as cs - -import PyQt5.QtCore as Core -import logging -import os -import signal - - -############################################################################### -# [Constants] - -LOGGER = logging.getLogger("[PROCESSES]") - -AC_MAKEFILE_NAME = "Makefile.ac" -CONF_FLAG_NAME = "AIRCRAFT" -DEVICE_FLAG_NAME = "FLASH_MODE" - -DEFAULT_EXIT_CODE = 2 -INTERRUPTED_EXIT_CODE = -1 -SUCCESS_EXIT_CODE = 0 - -CLEAN = "clean" -BUILD = "build" -UPLOAD = "upload" -PROGRAM = "program" -TOOL = "tool" - -CLEAN_TARGET_KEY = "clean_ac" -BUILD_TARGET_KEY = ".compile" -UPLOAD_TARGET_KEY = ".upload" - -CONF_FLAG = "@" + CONF_FLAG_NAME -TARGET_FLAG = "@TARGET" -CONF_ID_FLAG = "@AC_ID" - - -############################################################################### -# [Stream class] - -class LoggerStream(Core.QObject): - """ Class to define a Stream object.""" - logger_log_sent = Core.pyqtSignal(str, str, str) - - def __init__(self): - super(LoggerStream, self).__init__() - - # Reimplemented method in order to write the logs in the console : - def write(self, line): - log, flag = cs.analyse_log_line(line) - log_type = cs.APPLICATION_MESSAGE_TYPE - self.logger_log_sent.emit(log, flag, log_type) - - -############################################################################### -# [Process class] - -class Process(Core.QObject): - """Class to upload the built code to a device.""" - process_killed = Core.pyqtSignal() - process_log_sent = Core.pyqtSignal(str, str, str) - - def __init__(self, process_type, - configuration=None, target=None, device=None, program=None): - """ - :param process_type: - :param configuration: - :param target: - :param device: - :param program: - -> Declare a Process object as a QObject derivative. - -> Give it a name and the necessary parameters for its type. - -> Generate a command for the system call by the Popen object that - manages the subprocess and allows to redirect the output. - -> The process runs into an independent thread. - -> A queue is used to collect the logs from the Popen output and - an other one is used to send it to the QTextEdit integrated console. - -> Logs flags are collected for information. - -> Exit code is initialized to default value. Must change in case of - normal exit, error or user interruption. - """ - super(Process, self).__init__() - - self.type = process_type - self.name = None - - self.config = configuration - self.target = target - self.device = device - self.program = program - - if self.type == CLEAN: - self.command = self.generate_make_command(CLEAN_TARGET_KEY) - self.name = " - ".join([self.type.upper(), - self.config.name]) - elif self.type == BUILD: - self.command = self.generate_make_command(BUILD_TARGET_KEY) - self.name = " - ".join([self.type.upper(), self.config.name, - self.target.name]) - elif self.type == UPLOAD: - self.command = self.generate_make_command(UPLOAD_TARGET_KEY) - self.name = " - ".join([self.type.upper(), self.config.name, - self.target.name, self.device.name]) - else: - self.command = self.generate_program_command() - self.name = " - ".join([self.type.upper(), - self.program.name]) - - self.subprocess = Core.QProcess() - self.subprocess.setProcessChannelMode(Core.QProcess.MergedChannels) - self.subprocess.setReadChannel(Core.QProcess.StandardOutput) - - self.process_killed.connect(self.emergency_stop) - self.exit_code = DEFAULT_EXIT_CODE - - self.flags = {cs.ERROR_FLAG: 0, - cs.WARNING_FLAG: 0, - cs.INFO_FLAG: 0} - - def generate_make_command(self, target_key): - """ - :param target_key: - -> Generate a system command to compile files by a Makefile and - putting the right arguments if given. - """ - if self.config is not None: - aircraft_term = CONF_FLAG_NAME + "=" + self.config.name - - if self.target is not None: - target_key = self.target.name + target_key - - command_terms = ["make", "-C", env.PAPARAZZI_HOME, "-f", - AC_MAKEFILE_NAME, - aircraft_term, target_key] - - if self.device is not None and self.device.variable[1]: - device_term = DEVICE_FLAG_NAME + "=" + self.device.variable[1] - command_terms.insert(-1, device_term) - - return " ".join(command_terms) - - def generate_program_command(self): - """ - -> Generate a system command to run a program and add its options - if it has some. - """ - if self.program is not None: - full_command = os.path.join(env.PAPARAZZI_HOME, - self.program.command) - - for option in self.program.options: - if type(option) is tuple: - flag, value = option - if value == CONF_FLAG: - full_command += " " + flag + " " + self.config.name - elif value == TARGET_FLAG: - full_command += " " + flag + " " + self.target.name - elif value == CONF_ID_FLAG: - full_command += " " + flag + " " + self.config.id - else: - full_command += " " + flag + " " + value - else: - full_command += " " + option - - return full_command - - def check_before_start(self): - # TODO IF NECESSARY !!! - return self == self - - def start(self): - """ - -> Start the thread => start the worker => call the run method. - """ - LOGGER.info("'%s' process running ... (command='%s')", - self.name, self.command) - self.subprocess.start(self.command) - self.subprocess.readyReadStandardOutput.connect(self.send_text) - self.subprocess.finished.connect(self.finish_process) - - def send_text(self): - """ - -> Analyse an process output line to find a flag in it. - -> Send the item by the sending queue object. - -> Collect the flag found. - """ - q_byte_array = self.subprocess.readAllStandardOutput() - string = str(q_byte_array, encoding="utf-8").strip() - for line in string.split("\n"): - log, flag = cs.analyse_log_line(line) - log_type = cs.PROCESS_MESSAGE_TYPE - self.process_log_sent.emit(log, flag, log_type) - if flag != cs.DEFAULT_FLAG: - self.flags[flag] += 1 - - def finish_process(self): - """ - -> If the process finished, get the exit code. - -> Else, the process crashed... - """ - if self.subprocess.exitStatus() == Core.QProcess.NormalExit: - self.exit_code = self.subprocess.exitCode() - LOGGER.info("'%s' process finished with exit code %s.\n", - self.name, self.exit_code) - else: - self.exit_code = INTERRUPTED_EXIT_CODE - LOGGER.error("'%s' process crashed, probably stopped by user !\n", - self.name) - - def emergency_stop(self): - """ - -> Kill the subprocess by getting its ProcessID. - """ - os.kill(self.subprocess.pid(), signal.SIGKILL) diff --git a/sw/supervision/python/program_widget.py b/sw/supervision/python/program_widget.py new file mode 100644 index 0000000000..986031087d --- /dev/null +++ b/sw/supervision/python/program_widget.py @@ -0,0 +1,89 @@ +# Copyright (C) 2008-2022 The Paparazzi Team +# released under GNU GPLv2 or later. See COPYING file. +import os.path + +from generated.ui_program import Ui_Program +from PyQt5.QtWidgets import * +from PyQt5 import QtCore +from PyQt5.QtCore import QProcess +from PyQt5.QtGui import QIcon +import utils +from typing import List + + +class ProgramWidget(QWidget, Ui_Program): + + ready_read_stdout = QtCore.pyqtSignal() + ready_read_stderr = QtCore.pyqtSignal() + finished = QtCore.pyqtSignal(int, QProcess.ExitStatus) + remove = QtCore.pyqtSignal() + + def __init__(self, shortname: str, cmd: List[str], icon=None, parent=None): + QWidget.__init__(self, parent=parent) + self.setupUi(self) + self.cmd = cmd + self.shortname = shortname + self.process = QProcess(self) + self.program_lineedit.setText(" ".join(cmd)) + self.program_lineedit.returnPressed.connect(self.handle_cmd_return) + self.run_button.clicked.connect(self.handle_run) + self.remove_button.clicked.connect(self.handle_remove) + self.process.readyReadStandardOutput.connect(self.ready_read_stdout) + self.process.readyReadStandardError.connect(self.ready_read_stderr) + self.process.finished.connect(self.handle_finished) + self.process.started.connect(self.handle_started) + self.process.errorOccurred.connect(self.handle_error) + i = QIcon(os.path.join(utils.PAPARAZZI_HOME, "data", "pictures", "tools_icons", icon)) + self.icon_label.setPixmap(i.pixmap(20, 20)) + self.icon_label.setToolTip(shortname) + + def start_program(self): + if self.process.state() == QProcess.NotRunning: + self.process.start(self.cmd[0], self.cmd[1:]) + + def handle_cmd_return(self): + if self.process.state() == QProcess.NotRunning: + self.cmd = self.program_lineedit.text().split(" ") + self.start_program() + + def handle_run(self): + if self.process.state() == QProcess.NotRunning: + self.cmd = self.program_lineedit.text().split(" ") + self.start_program() + elif self.process.state() == QProcess.Running: + self.process.terminate() + + def handle_remove(self): + if self.process.state() == QProcess.NotRunning: + self.remove.emit() + elif self.process.state() == QProcess.Running: + self.process.finished.connect(self.remove) + self.process.terminate() + + def handle_started(self): + icon = QIcon.fromTheme("media-playback-stop") + self.run_button.setIcon(icon) + self.program_lineedit.setReadOnly(True) + + def handle_finished(self, exit_code: int, exit_status: QProcess.ExitStatus): + icon = QIcon.fromTheme("media-playback-start") + self.run_button.setIcon(icon) + self.program_lineedit.setReadOnly(False) + self.finished.emit(exit_code, exit_status) + + def handle_error(self, error: QProcess.ProcessError): + if error == QProcess.FailedToStart: + self.handle_finished(-1, QProcess.CrashExit) + # FailedToStart + # Crashed + # Timedout + # ReadError + # WriteError + # UnknownError + + def terminate(self): + if self.process.state() != QProcess.NotRunning: + self.process.terminate() + + def state(self): + return self.process.state() diff --git a/sw/supervision/python/programs_conf.py b/sw/supervision/python/programs_conf.py new file mode 100644 index 0000000000..390441d9b8 --- /dev/null +++ b/sw/supervision/python/programs_conf.py @@ -0,0 +1,132 @@ +# Copyright (C) 2008-2022 The Paparazzi Team +# released under GNU GPLv2 or later. See COPYING file. +from __future__ import annotations +from dataclasses import dataclass, field +from typing import List, Optional, Tuple, Dict +from lxml import etree as ET +from conf import * +from copy import deepcopy + + +@dataclass +class Arg: + flag: str + constant: Optional[str] + + @staticmethod + def parse(xml_arg): + flag = xml_arg.get("flag") + constant = xml_arg.get("constant") + return Arg(flag, constant) + + def args(self, ac: Aircraft = None) -> List[str]: + if self.constant is not None: + constant = self.constant + if "@AIRCRAFT" in self.constant: + constant = self.constant.replace("@AIRCRAFT", ac.name) + if "@AC_ID" in self.constant: + constant = constant.replace("@AC_ID", str(ac.ac_id)) + return [self.flag, constant] + else: + return [self.flag] + + def to_xml(self) -> ET.Element: + xml = ET.Element("arg") + xml.set("flag", self.flag) + if self.constant is not None: + xml.set("constant", self.constant) + return xml + + +@dataclass +class Program: + name: str + args: List[Arg] = field(default_factory=list) + + @staticmethod + def parse(xml_program): + name = xml_program.get("name") + args = [Arg.parse(xml_arg) for xml_arg in xml_program.findall("arg")] + return Program(name, args) + + @staticmethod + def from_tool(t: Tool): + return Program(t.name, deepcopy(t.args)) + + def to_xml(self) -> ET.Element: + xml: ET._Element = ET.Element("program") + xml.set("name", self.name) + for arg in self.args: + xml.append(arg.to_xml()) + return xml + + +@dataclass +class Session: + name: str + programs: List[Program] = field(default_factory=list) + + @staticmethod + def parse(xml_session): + name = xml_session.get("name") + programs = [Program.parse(xml_program) for xml_program in xml_session.findall("program")] + return Session(name, programs) + + def to_xml(self) -> ET.Element: + xml = ET.Element("session") + xml.set("name", self.name) + for p in self.programs: + xml.append(p.to_xml()) + return xml + + +@dataclass +class Tool: + name: str + command: str + icon: Optional[str] + args: List[Arg] + favorite: bool + + @staticmethod + def parse(xml_program) -> Tuple[str, Tool]: + name = xml_program.get("name") + command = xml_program.get("command") + icon = xml_program.get("icon") + if icon is None: + icon = "default_tool_icon.svg" + favorite = True if xml_program.get("favorite") is not None else False + args = [Arg.parse(xml_arg) for xml_arg in xml_program.findall("arg")] + return name, Tool(name, command, icon, args, favorite) + + +def parse_tools() -> Dict[str, Tool]: + tools = {} + tools_dir = os.path.join(utils.CONF_DIR, "tools") + for file in os.listdir(tools_dir): + if file.endswith(".xml"): + path = os.path.join(utils.CONF_DIR, "tools", file) + xml = ET.parse(path).getroot() + if xml.tag == "program": + name, tool = Tool.parse(xml) + tools[name] = tool + else: + print("unexpected tag ", xml.tag) + + # programs from control_panel.xml + # override programs from conf/tools/*.xml + control_panel = ET.parse(os.path.join(utils.CONF_DIR, "control_panel.xml")) + for xml_section in control_panel.getroot().findall("section"): + if xml_section.get("name") == "programs": + for xml_program in xml_section.findall("program"): + name, tool = Tool.parse(xml_program) + tools[name] = tool + + return tools + + +def parse_sessions() -> List[Session]: + control_panel = ET.parse(os.path.join(utils.CONF_DIR, "control_panel.xml")) + for xml_section in control_panel.getroot().findall("section"): + if xml_section.get("name") == "sessions": + return [Session.parse(xml_session) for xml_session in xml_section.findall("session")] diff --git a/sw/supervision/python/requirements.txt b/sw/supervision/python/requirements.txt new file mode 100644 index 0000000000..92adab28d1 --- /dev/null +++ b/sw/supervision/python/requirements.txt @@ -0,0 +1,3 @@ +PyQt5 +lxml + diff --git a/sw/supervision/python/session_widget.py b/sw/supervision/python/session_widget.py new file mode 100644 index 0000000000..49fd17914e --- /dev/null +++ b/sw/supervision/python/session_widget.py @@ -0,0 +1,291 @@ +# Copyright (C) 2008-2022 The Paparazzi Team +# released under GNU GPLv2 or later. See COPYING file. +import os.path + +import console_widget +from generated.ui_session import Ui_Session +from PyQt5.QtWidgets import * +from PyQt5 import QtCore +import utils +import lxml.etree as ET + +from typing import List, Optional, Tuple, Dict +from program_widget import ProgramWidget +from tools_menu import ToolMenu +from programs_conf import * +from conf import * +from console_widget import ConsoleWidget + + +class SessionWidget(QWidget, Ui_Session): + + programs_all_stopped = QtCore.pyqtSignal() + program_spawned = QtCore.pyqtSignal() + + def __init__(self, parent=None): + QWidget.__init__(self, parent=parent) + self.setupUi(self) + self.program_widgets: List[ProgramWidget] = [] + self.console: ConsoleWidget = None + self.ac: Aircraft = None + self.sessions = [] + self.tools = [] + self.tools_menu = ToolMenu() + self.sessions_combo.addItems(["Simulation", "Replay"]) + self.sessions_combo.insertSeparator(2) + self.menu_button.addAction(self.save_session_action) + self.menu_button.addAction(self.save_as_action) + self.menu_button.addAction(self.rename_session_action) + self.menu_button.addAction(self.remove_session_action) + self.tools_menu.tool_clicked.connect(self.handle_new_tool) + self.start_session_button.clicked.connect(self.start_session) + self.startall_button.clicked.connect(self.start_all) + self.removeall_button.clicked.connect(self.remove_all) + self.stopall_button.clicked.connect(self.stop_all) + self.add_tool_button.clicked.connect(self.open_tools) + self.save_session_action.triggered.connect(self.handle_save) + self.save_as_action.triggered.connect(self.handle_save_as) + self.rename_session_action.triggered.connect(self.handle_rename) + self.remove_session_action.triggered.connect(self.remove_session) + + def set_console(self, console: console_widget.ConsoleWidget): + self.console = console + + def set_aircraft(self, ac: Aircraft): + self.ac = ac + + def init(self): + self.sessions = parse_sessions() + self.tools = parse_tools() + self.init_tools_menu() + sessions_names = [session.name for session in self.sessions] + self.sessions_combo.addItems(sessions_names) + last_session = utils.get_settings().value("ui/last_session", None, str) + if last_session is not None: + self.sessions_combo.setCurrentText(last_session) + + def get_current_session(self) -> str: + """ + :return: current session name in comboBox. + """ + return self.sessions_combo.currentText() + + def start_session(self): + combo_text = self.sessions_combo.currentText() + if combo_text == "Simulation": + self.start_simulation() + elif combo_text == "Replay": + self.start_replay() + else: + for session in self.sessions: + if session.name == combo_text: + for program in session.programs: + self.launch_program(program) + + def start_replay(self): + lfp = Program.from_tool(self.tools["Log File Player"]) + server = Program.from_tool(self.tools["Server"]) + server.args.append(Arg("-n", None)) + gcs = Program.from_tool(self.tools["GCS"]) + self.launch_program(lfp) + self.launch_program(server) + self.launch_program(gcs) + + def start_simulation(self): + if "nps" not in self.ac.boards and "sim" not in self.ac.boards: + self.console.post_message(None, "No simulation target for {}.".format(self.ac.name)) + return + + elif "nps" in self.ac.boards and "sim" in self.ac.boards: + simulator, ok = QInputDialog.getItem(self, "Simulator", "Please choose the simulator:", + ["nps", "sim"], editable=False) + if not ok: + return + elif "nps" in self.ac.boards: + simulator = "nps" + else: + # simulator is "sim" + simulator = "sim" + + if simulator == "nps": + t = self.tools["Simulator"] + simu = Program.from_tool(t) + simu.args.append(Arg("-t", "nps")) + self.launch_program(simu) + datalink = Program.from_tool(self.tools["Data Link"]) + datalink.args = [Arg("-udp", None), Arg("-udp_broadcast", None)] + self.launch_program(datalink) + else: + # simulator is "sim" + sim = Program.from_tool(self.tools["Simulator"]) + sim.args.extend([Arg("-t", "sim"), Arg("--boot", None), Arg("--norc", None)]) + self.launch_program(sim) + + server = Program.from_tool(self.tools["Server"]) + server.args.append(Arg("-n", None)) + gcs = Program.from_tool(self.tools["GCS"]) + self.launch_program(server) + self.launch_program(gcs) + + def launch_program(self, program: Program): + if self.console is None: + raise Exception("Console not set!") + tool = self.tools[program.name] + args = [arg.args(self.ac) for arg in program.args] + flat_args = [item for sublist in args for item in sublist] + if tool.command.startswith("$"): + cmd = [tool.command[1:]] + flat_args + else: + cmd = [os.path.join(utils.PAPARAZZI_SRC, tool.command)] + flat_args + + pw = ProgramWidget(tool.name, cmd, tool.icon, self.programs_widget) + self.program_widgets.append(pw) + lay: QVBoxLayout = self.programs_widget.layout() + lay.insertWidget(lay.count()-1, pw) + pw.ready_read_stderr.connect(lambda: self.console.handle_stderr(pw)) + pw.ready_read_stdout.connect(lambda: self.console.handle_stdout(pw)) + pw.finished.connect(lambda c, s: self.handle_program_finished(pw, c, s)) + pw.remove.connect(lambda: self.remove_program(pw)) + # if REMOVE_PROGRAMS_FINISHED: + # pw.finished.connect(lambda: self.remove_program(pw)) + pw.start_program() + self.console.new_program(pw) + self.program_spawned.emit() + + def remove_program(self, pw: ProgramWidget): + self.console.remove_program(pw) + pw.setParent(None) + # self.programs_widget.layout().removeWidget(pw) + self.program_widgets.remove(pw) + if len(self.program_widgets) == 0: + self.programs_all_stopped.emit() + # pw.deleteLater() + + def any_program_running(self): + return any([pw.state() == QtCore.QProcess.Running for pw in self.program_widgets]) + + def handle_program_finished(self, pw, c, s): + self.console.handle_program_finished(pw, c, s) + if not self.any_program_running(): + self.programs_all_stopped.emit() + + def stop_all(self): + for pw in self.program_widgets: + pw.terminate() + + def start_all(self): + for pw in self.program_widgets: + pw.start_program() + + def remove_all(self): + for pw in list(self.program_widgets): + pw.handle_remove() + + def init_tools_menu(self): + for t in self.tools.values(): + self.tools_menu.add_tool(t) + + def handle_new_tool(self, name): + p = Program.from_tool(self.tools[name]) + self.launch_program(p) + + def open_tools(self): + if self.tools_menu.isVisible(): + self.tools_menu.close() + else: + bottomLeft = self.mapToGlobal(self.add_tool_button.geometry().bottomLeft()) + self.tools_menu.move(bottomLeft) + self.tools_menu.show() + self.tools_menu.setFocus(QtCore.Qt.PopupFocusReason) + + def handle_save(self): + session_name = self.sessions_combo.currentText() + programs = self.get_programs() + session = Session(session_name, programs) + self.replace_session(session) + self.save_sessions() + + def handle_save_as(self): + session_name, ok = QInputDialog.getText(self, "Session name", "enter the session name:") + if not ok: + return + for session in self.sessions: + if session.name == session_name: + QMessageBox.warning(self, "Error", "A session with this name already exits.\nTry again with a new name.") + return + programs = self.get_programs() + session = Session(session_name, programs) + self.sessions.append(session) + self.save_sessions() + + def handle_rename(self): + for session_orig in self.sessions: + if session_orig.name == self.sessions_combo.currentText(): + break + else: + print("session not found") + return + session_name, ok = QInputDialog.getText(self, "Session name", "enter the session name:") + if not ok: + return + for session in self.sessions: + if session.name == session_name: + QMessageBox.warning(self, "Error", "A session with this name already exits.\nTry again with a new name.") + return + session_orig.name = session_name + self.save_sessions() + + def remove_session(self): + for session in self.sessions: + if session.name == self.sessions_combo.currentText(): + self.sessions.remove(session) + i = self.sessions_combo.currentIndex() + self.sessions_combo.removeItem(i) + self.save_sessions() + return + print("session {} not found".format(self.sessions_combo.currentText())) + + def replace_session(self, session): + for i, s in enumerate(self.sessions): + if s.name == session.name: + self.sessions[i] = session + break + + def save_sessions(self): + ctrl_panel_path = os.path.join(utils.CONF_DIR, "control_panel.xml") + parser = ET.XMLParser(remove_blank_text=True) + control_panel = ET.parse(ctrl_panel_path, parser) + xml_sessions = ET.Element("section") + xml_sessions.set("name", "sessions") + for session in self.sessions: + xml_sessions.append(session.to_xml()) + for xml_section in control_panel.getroot().findall("section"): + if xml_section.get("name") == "sessions": + control_panel.getroot().replace(xml_section, xml_sessions) + break + control_panel.write(ctrl_panel_path, pretty_print=True) + print("sessions saved to {}".format(ctrl_panel_path)) + + def get_programs(self): + programs = [] + for p in self.program_widgets: + name = p.shortname + args = [] + if len(p.cmd) > 0: + arg = None + for param in p.cmd[1:]: + if param.startswith("-"): + # if it start with "-", make a new arg + arg = Arg(param, None) + args.append(arg) + else: + if arg is not None and arg.flag.startswith("-"): + # if it don't starts with -, but the previous did, fill the constant + arg.constant = param + else: + # if it don't starts with -, nor the previous, its probably a mandatory argument + arg = Arg(param, None) + args.append(arg) + program = Program(name, args) + programs.append(program) + return programs diff --git a/sw/supervision/python/tools_menu.py b/sw/supervision/python/tools_menu.py index 4ce7e2832a..5afb50a963 100644 --- a/sw/supervision/python/tools_menu.py +++ b/sw/supervision/python/tools_menu.py @@ -1,89 +1,54 @@ -from PyQt5 import QtCore, QtGui, QtWidgets +# Copyright (C) 2008-2022 The Paparazzi Team +# released under GNU GPLv2 or later. See COPYING file. +from PyQt5 import QtCore, QtGui +from programs_conf import * +import os +import utils +from PyQt5.QtWidgets import * +from PyQt5.QtCore import Qt +from generated.ui_tools_list import Ui_ToolsList -ICON_SIZE = (60, 60) -POPUP_SIZE = (1000, 400) -POPUP_GRID_WIDTH = 4 -SC_MINIMUM_SIZE = (200, 130) -ICON_NUMBER = 6 +ICON_SIZE = (40, 40) -class ToolList(QtWidgets.QScrollArea): + +class ToolMenu(QWidget, Ui_ToolsList): + + tool_clicked = QtCore.pyqtSignal(str) def __init__(self): - super(ToolList, self).__init__() - self.frame = QtWidgets.QFrame() - self.gridLayout = QtWidgets.QGridLayout() - self.frame.setLayout(self.gridLayout) - self.setWidget(self.frame) - self.setWidgetResizable(True) + super(ToolMenu, self).__init__() + self.setupUi(self) + self.setWindowFlags(QtCore.Qt.FramelessWindowHint | QtCore.Qt.Popup) + self.tools_buttons: Dict[str, QToolButton] = {} + self.filter_lineedit.textChanged.connect(self.filter) + self.setFocusProxy(self.filter_lineedit) + # self.gridLayout.setContentsMargins(10, 10, 24, 10) + # self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) + # self.setWidgetResizable(True) - def add(self, button): - count = self.gridLayout.count() - row = count // POPUP_GRID_WIDTH - col = count % POPUP_GRID_WIDTH - self.gridLayout.addWidget(button, row, col) - - def focusOutEvent(self, QFocusEvent): - self.close() - - -class ToolsMenu(QtWidgets.QFrame): - def __init__(self, parent): - super(ToolsMenu, self).__init__(parent) - self.hlayout = QtWidgets.QHBoxLayout(self) - self.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) - - self.toolsFrame = QtWidgets.QFrame() - self.toolsLayout = QtWidgets.QHBoxLayout(self.toolsFrame) - self.scrollArea = QtWidgets.QScrollArea() - self.scrollArea.setWidget(self.toolsFrame) - self.hlayout.addWidget(self.scrollArea) - self.scrollArea.setMinimumSize(*SC_MINIMUM_SIZE) - self.setMinimumSize(SC_MINIMUM_SIZE[0] + 10, SC_MINIMUM_SIZE[1] + 100) - - self.toolsLayout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize) - - self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) - self.scrollArea.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) - self.scrollArea.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) - - self.button_more = None - self.popup = ToolList() - self.popup.setWindowFlags(QtCore.Qt.FramelessWindowHint) - self.popup.setMinimumSize(*POPUP_SIZE) - self.buttons = [] - self.toolsLayout.addStretch(0) - - self._add_more_button() - - def _add_more_button(self): - if self.button_more is None: - self.button_more = QtWidgets.QToolButton() - more_icon = QtGui.QIcon("ui/icons/tools_more.svg") - self.button_more.setIcon(more_icon) - self.button_more.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Expanding) - self.hlayout.addWidget(self.button_more, QtCore.Qt.AlignRight) - self.button_more.clicked.connect(self.open_popup) - - def add_item(self, name, image_path, callback): - button = QtWidgets.QToolButton() - button.setText(name) - button.setIcon(QtGui.QIcon(image_path)) + def add_tool(self, t: Tool): + button = QToolButton() + button.setText(t.name) + icon = QtGui.QIcon(os.path.join(utils.PAPARAZZI_HOME, "data", "pictures", "tools_icons", t.icon)) + button.setIcon(icon) button.setIconSize(QtCore.QSize(*ICON_SIZE)) - button.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) - button.clicked.connect(callback) + # button.setToolButtonStyle(QtCore.Qt.ToolButtonTextUnderIcon) + button.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon) + button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + button.clicked.connect(lambda: self.tool_clicked.emit(button.text())) + self.tools_buttons[t.name] = button + self.content_widget.layout().addWidget(button) - self.buttons.append(button) + def filter(self, txt: str): + for name, button in self.tools_buttons.items(): + show = txt.lower() in name.lower() + button.setVisible(show) - if self.toolsLayout.count() <= ICON_NUMBER: - self.toolsLayout.insertWidget(self.toolsLayout.count() - 1, button, QtCore.Qt.AlignLeft) - else: - self.popup.add(button) - button.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - button.show() - self.popup.adjustSize() + def keyPressEvent(self, e: QtGui.QKeyEvent) -> None: + if e.key() == Qt.Key_Escape: + self.releaseMouse() + self.close() - def open_popup(self): - bottomLeft = self.mapToGlobal(self.hlayout.geometry().bottomLeft()) - self.popup.move(bottomLeft) - self.popup.show() - self.popup.setFocus(QtCore.Qt.PopupFocusReason) + def show(self) -> None: + super(ToolMenu, self).show() + self.filter_lineedit.clear() diff --git a/sw/supervision/python/ui/app_settings.ui b/sw/supervision/python/ui/app_settings.ui new file mode 100644 index 0000000000..95036026ab --- /dev/null +++ b/sw/supervision/python/ui/app_settings.ui @@ -0,0 +1,98 @@ + + + AppSettingsDialog + + + + 0 + 0 + 381 + 131 + + + + Settings + + + + + + Text editor + + + + + + + + + + Terminal Emulator + + + + + + + + + + Keep changes on exit + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + AppSettingsDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + AppSettingsDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/sw/supervision/python/ui/build.ui b/sw/supervision/python/ui/build.ui new file mode 100644 index 0000000000..1b22973b16 --- /dev/null +++ b/sw/supervision/python/ui/build.ui @@ -0,0 +1,139 @@ + + + Build + + + + 0 + 0 + 437 + 87 + + + + Form + + + + + + Build + + + + + + + 0 + 0 + + + + Target + + + + + + + + + + false + + + + + + + Clean + + + ... + + + + .. + + + + + + + Build + + + ... + + + + .. + + + Qt::ToolButtonIconOnly + + + + + + + + 0 + 0 + + + + print config at build time + + + + + + + + + + + + + Flash + + + + + + + 0 + 0 + + + + Device + + + + + + + + + + Upload + + + Flash + + + + .. + + + + + + + + + + + diff --git a/sw/supervision/python/ui/conf_header.ui b/sw/supervision/python/ui/conf_header.ui new file mode 100644 index 0000000000..6d8ad9b53f --- /dev/null +++ b/sw/supervision/python/ui/conf_header.ui @@ -0,0 +1,169 @@ + + + ConfHeader + + + + 0 + 0 + 664 + 192 + + + + Form + + + + + + 255 + + + + + + + + + + + + + + + + + + 0 + 0 + + + + false + + + + + + + Qt::ActionsContextMenu + + + + + + + .. + + + + + + + refresh Aircraft + + + ... + + + + .. + + + + + + + save conf + + + ... + + + + .. + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Set + + + + + + + + + + + .. + + + New AC + + + + + + .. + + + Remove + + + + + + .. + + + Duplicate + + + + + + .. + + + Rename + + + + + + + menu_button + clicked() + menu_button + showMenu() + + + 302 + 95 + + + 302 + 95 + + + + + diff --git a/sw/supervision/python/ui/conf_item.ui b/sw/supervision/python/ui/conf_item.ui new file mode 100644 index 0000000000..b5628897f8 --- /dev/null +++ b/sw/supervision/python/ui/conf_item.ui @@ -0,0 +1,72 @@ + + + FileConf + + + + 0 + 0 + 306 + 129 + + + + Form + + + + + + + + font-weight: bold; + + + Flight Plan + + + + + + + Edit alt + + + + + + + Edit + + + + + + + Select + + + + + + + + + /path/to/file.xml + + + true + + + false + + + Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + + + diff --git a/sw/supervision/python/ui/configuration_panel.ui b/sw/supervision/python/ui/configuration_panel.ui new file mode 100644 index 0000000000..cb057069b7 --- /dev/null +++ b/sw/supervision/python/ui/configuration_panel.ui @@ -0,0 +1,114 @@ + + + ConfigurationPanel + + + + 0 + 0 + 562 + 480 + + + + Form + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + + + + Qt::Horizontal + + + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + + + + + + Save configuration + + + Ctrl+S + + + + + + ConfWidget + QWidget +
conf_widget.h
+ 1 +
+ + BuildWidget + QWidget +
build_widget.h
+ 1 +
+ + HeaderWidget + QWidget +
header_widget.h
+ 1 +
+ + ConsoleWidget + QWidget +
console_widget.h
+ 1 +
+
+ + +
diff --git a/sw/supervision/python/ui/console.ui b/sw/supervision/python/ui/console.ui new file mode 100644 index 0000000000..f2a0fdda38 --- /dev/null +++ b/sw/supervision/python/ui/console.ui @@ -0,0 +1,168 @@ + + + Console + + + + 0 + 0 + 709 + 647 + + + + Form + + + + + + Qt::Horizontal + + + + true + + + + + + + + + 0 + 0 + + + + Filters + + + + + + + Programs + + + false + + + + + + + true + + + + + 0 + 0 + 382 + 524 + + + + + + + Qt::Vertical + + + + 1 + 167 + + + + + + + + + + + + + + + + + + + 0 + 0 + + + + Log level: + + + + + + + + 100 + 16777215 + + + + 3 + + + 1 + + + 3 + + + Qt::Horizontal + + + QSlider::TicksBelow + + + 1 + + + + + + + All + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Clear console + + + + .. + + + + + + + + + + diff --git a/sw/supervision/python/ui/credits.html b/sw/supervision/python/ui/credits.html deleted file mode 100644 index e97422d6fd..0000000000 --- a/sw/supervision/python/ui/credits.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - -
- Paparazzi UAV icon unreachable... -

Paparazzi Center

-

(Python/Qt version)

-
-

Copyright (C) 2007-2008 ENAC, Pascal Brisset

-

License GPLv2

-

http://paparazziuav.org

- - diff --git a/sw/supervision/python/ui/data_changed.html b/sw/supervision/python/ui/data_changed.html deleted file mode 100644 index ba8ef77ead..0000000000 --- a/sw/supervision/python/ui/data_changed.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - -
- /!\ WARNING : -
-

Values have been modified locally but not into the original XML files...

-

Do you want to save or ignore them ?

- - diff --git a/sw/supervision/python/ui/icons/accessories-text-editor.svg b/sw/supervision/python/ui/icons/accessories-text-editor.svg deleted file mode 100644 index 03db109a64..0000000000 --- a/sw/supervision/python/ui/icons/accessories-text-editor.svg +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/ui/icons/dialog-apply.svg b/sw/supervision/python/ui/icons/dialog-apply.svg deleted file mode 100644 index f009b90ee3..0000000000 --- a/sw/supervision/python/ui/icons/dialog-apply.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/ui/icons/dialog-error.svg b/sw/supervision/python/ui/icons/dialog-error.svg deleted file mode 100644 index a3d6de4d72..0000000000 --- a/sw/supervision/python/ui/icons/dialog-error.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/ui/icons/dialog-warning-symbolic.svg b/sw/supervision/python/ui/icons/dialog-warning-symbolic.svg deleted file mode 100644 index e9474a9d14..0000000000 --- a/sw/supervision/python/ui/icons/dialog-warning-symbolic.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - image/svg+xml - - Gnome Symbolic Icon Theme - - - - Gnome Symbolic Icon Theme - - - - diff --git a/sw/supervision/python/ui/icons/dialog-warning.png b/sw/supervision/python/ui/icons/dialog-warning.png deleted file mode 100644 index d1020c6d9e..0000000000 Binary files a/sw/supervision/python/ui/icons/dialog-warning.png and /dev/null differ diff --git a/sw/supervision/python/ui/icons/edit-clear.svg b/sw/supervision/python/ui/icons/edit-clear.svg deleted file mode 100644 index 568fe9de66..0000000000 --- a/sw/supervision/python/ui/icons/edit-clear.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/ui/icons/go-up.svg b/sw/supervision/python/ui/icons/go-up.svg deleted file mode 100644 index e5e58672cd..0000000000 --- a/sw/supervision/python/ui/icons/go-up.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/ui/icons/gtk-info.svg b/sw/supervision/python/ui/icons/gtk-info.svg deleted file mode 100644 index f1ec53786a..0000000000 --- a/sw/supervision/python/ui/icons/gtk-info.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/ui/icons/list-add.svg b/sw/supervision/python/ui/icons/list-add.svg deleted file mode 100644 index f40a948324..0000000000 --- a/sw/supervision/python/ui/icons/list-add.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/ui/icons/list-remove.svg b/sw/supervision/python/ui/icons/list-remove.svg deleted file mode 100644 index ebc6bdbe8f..0000000000 --- a/sw/supervision/python/ui/icons/list-remove.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/ui/icons/media-playback-pause.svg b/sw/supervision/python/ui/icons/media-playback-pause.svg deleted file mode 100644 index fde2760829..0000000000 --- a/sw/supervision/python/ui/icons/media-playback-pause.svg +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/ui/icons/media-playback-start.svg b/sw/supervision/python/ui/icons/media-playback-start.svg deleted file mode 100644 index 87c34d3025..0000000000 --- a/sw/supervision/python/ui/icons/media-playback-start.svg +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/ui/icons/penguin_icon.png b/sw/supervision/python/ui/icons/penguin_icon.png deleted file mode 100644 index f61d8024e9..0000000000 Binary files a/sw/supervision/python/ui/icons/penguin_icon.png and /dev/null differ diff --git a/sw/supervision/python/ui/icons/process-stop.svg b/sw/supervision/python/ui/icons/process-stop.svg deleted file mode 100644 index 1c9162caab..0000000000 --- a/sw/supervision/python/ui/icons/process-stop.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/ui/icons/search_field.png b/sw/supervision/python/ui/icons/search_field.png deleted file mode 100644 index c3264f66d9..0000000000 Binary files a/sw/supervision/python/ui/icons/search_field.png and /dev/null differ diff --git a/sw/supervision/python/ui/icons/system-run.png b/sw/supervision/python/ui/icons/system-run.png deleted file mode 100644 index ad6d80b0de..0000000000 Binary files a/sw/supervision/python/ui/icons/system-run.png and /dev/null differ diff --git a/sw/supervision/python/ui/icons/tools_more.svg b/sw/supervision/python/ui/icons/tools_more.svg deleted file mode 100644 index 77f5bdd499..0000000000 --- a/sw/supervision/python/ui/icons/tools_more.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - diff --git a/sw/supervision/python/ui/icons/utilities-terminal.svg b/sw/supervision/python/ui/icons/utilities-terminal.svg deleted file mode 100644 index add2893910..0000000000 --- a/sw/supervision/python/ui/icons/utilities-terminal.svg +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - diff --git a/sw/supervision/python/ui/main_window.py b/sw/supervision/python/ui/main_window.py deleted file mode 100644 index 4c0f35c378..0000000000 --- a/sw/supervision/python/ui/main_window.py +++ /dev/null @@ -1,1715 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'main_window.ui' -# -# Created by: PyQt5 UI code generator 5.5.1 -# -# WARNING! All changes made in this file will be lost! - -from PyQt5 import QtCore, QtGui, QtWidgets - -class Ui_MainWindow(object): - def setupUi(self, MainWindow): - MainWindow.setObjectName("MainWindow") - MainWindow.resize(833, 568) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth()) - MainWindow.setSizePolicy(sizePolicy) - MainWindow.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.centralwidget = QtWidgets.QWidget(MainWindow) - self.centralwidget.setObjectName("centralwidget") - self.gridLayout_10 = QtWidgets.QGridLayout(self.centralwidget) - self.gridLayout_10.setObjectName("gridLayout_10") - self.current_set_and_configuration = QtWidgets.QFrame(self.centralwidget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.current_set_and_configuration.sizePolicy().hasHeightForWidth()) - self.current_set_and_configuration.setSizePolicy(sizePolicy) - self.current_set_and_configuration.setMinimumSize(QtCore.QSize(0, 40)) - self.current_set_and_configuration.setMaximumSize(QtCore.QSize(16777215, 40)) - self.current_set_and_configuration.setAutoFillBackground(False) - self.current_set_and_configuration.setStyleSheet("") - self.current_set_and_configuration.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.current_set_and_configuration.setFrameShadow(QtWidgets.QFrame.Plain) - self.current_set_and_configuration.setObjectName("current_set_and_configuration") - self.gridLayout = QtWidgets.QGridLayout(self.current_set_and_configuration) - self.gridLayout.setObjectName("gridLayout") - self.label = QtWidgets.QLabel(self.current_set_and_configuration) - self.label.setToolTip("") - self.label.setObjectName("label") - self.gridLayout.addWidget(self.label, 0, 0, 1, 1) - self.current_configuration = QtWidgets.QComboBox(self.current_set_and_configuration) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.current_configuration.sizePolicy().hasHeightForWidth()) - self.current_configuration.setSizePolicy(sizePolicy) - self.current_configuration.setMinimumSize(QtCore.QSize(0, 20)) - self.current_configuration.setObjectName("current_configuration") - self.gridLayout.addWidget(self.current_configuration, 0, 3, 1, 1) - self.current_color = QtWidgets.QLabel(self.current_set_and_configuration) - self.current_color.setEnabled(True) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.current_color.sizePolicy().hasHeightForWidth()) - self.current_color.setSizePolicy(sizePolicy) - self.current_color.setMinimumSize(QtCore.QSize(30, 0)) - self.current_color.setMaximumSize(QtCore.QSize(40, 16777215)) - self.current_color.setMouseTracking(False) - self.current_color.setFocusPolicy(QtCore.Qt.NoFocus) - self.current_color.setAutoFillBackground(True) - self.current_color.setStyleSheet("") - self.current_color.setFrameShape(QtWidgets.QFrame.Box) - self.current_color.setMidLineWidth(1) - self.current_color.setText("") - self.current_color.setAlignment(QtCore.Qt.AlignCenter) - self.current_color.setObjectName("current_color") - self.gridLayout.addWidget(self.current_color, 0, 7, 1, 1) - self.label_2 = QtWidgets.QLabel(self.current_set_and_configuration) - self.label_2.setToolTip("") - self.label_2.setObjectName("label_2") - self.gridLayout.addWidget(self.label_2, 0, 2, 1, 1) - self.label_3 = QtWidgets.QLabel(self.current_set_and_configuration) - self.label_3.setToolTip("") - self.label_3.setObjectName("label_3") - self.gridLayout.addWidget(self.label_3, 0, 4, 1, 1) - self.current_id = QtWidgets.QLabel(self.current_set_and_configuration) - self.current_id.setEnabled(True) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.current_id.sizePolicy().hasHeightForWidth()) - self.current_id.setSizePolicy(sizePolicy) - self.current_id.setMinimumSize(QtCore.QSize(30, 0)) - self.current_id.setMaximumSize(QtCore.QSize(40, 16777215)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.current_id.setFont(font) - self.current_id.setMouseTracking(False) - self.current_id.setFocusPolicy(QtCore.Qt.NoFocus) - self.current_id.setAutoFillBackground(True) - self.current_id.setStyleSheet("") - self.current_id.setFrameShape(QtWidgets.QFrame.Box) - self.current_id.setMidLineWidth(1) - self.current_id.setText("") - self.current_id.setAlignment(QtCore.Qt.AlignCenter) - self.current_id.setObjectName("current_id") - self.gridLayout.addWidget(self.current_id, 0, 5, 1, 1) - self.label_27 = QtWidgets.QLabel(self.current_set_and_configuration) - self.label_27.setToolTip("") - self.label_27.setObjectName("label_27") - self.gridLayout.addWidget(self.label_27, 0, 6, 1, 1) - self.current_set = QtWidgets.QComboBox(self.current_set_and_configuration) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.current_set.sizePolicy().hasHeightForWidth()) - self.current_set.setSizePolicy(sizePolicy) - self.current_set.setMinimumSize(QtCore.QSize(0, 20)) - self.current_set.setObjectName("current_set") - self.gridLayout.addWidget(self.current_set, 0, 1, 1, 1) - self.gridLayout_10.addWidget(self.current_set_and_configuration, 0, 0, 1, 1) - self.main_tab = QtWidgets.QTabWidget(self.centralwidget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.main_tab.sizePolicy().hasHeightForWidth()) - self.main_tab.setSizePolicy(sizePolicy) - self.main_tab.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.main_tab.setToolTip("") - self.main_tab.setLayoutDirection(QtCore.Qt.LeftToRight) - self.main_tab.setTabPosition(QtWidgets.QTabWidget.North) - self.main_tab.setTabShape(QtWidgets.QTabWidget.Triangular) - self.main_tab.setElideMode(QtCore.Qt.ElideNone) - self.main_tab.setUsesScrollButtons(True) - self.main_tab.setDocumentMode(False) - self.main_tab.setTabsClosable(False) - self.main_tab.setObjectName("main_tab") - self.equipment_tab = QtWidgets.QWidget() - self.equipment_tab.setObjectName("equipment_tab") - self.gridLayout_11 = QtWidgets.QGridLayout(self.equipment_tab) - self.gridLayout_11.setObjectName("gridLayout_11") - spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout_11.addItem(spacerItem, 6, 2, 1, 1) - self.search_item = QtWidgets.QLineEdit(self.equipment_tab) - self.search_item.setEnabled(False) - self.search_item.setMinimumSize(QtCore.QSize(0, 0)) - self.search_item.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.search_item.setObjectName("search_item") - self.gridLayout_11.addWidget(self.search_item, 0, 1, 1, 1) - self.all_items_tree = QtWidgets.QTreeWidget(self.equipment_tab) - self.all_items_tree.setEnabled(False) - self.all_items_tree.setObjectName("all_items_tree") - self.gridLayout_11.addWidget(self.all_items_tree, 1, 0, 7, 2) - self.frame_4 = QtWidgets.QFrame(self.equipment_tab) - self.frame_4.setMinimumSize(QtCore.QSize(0, 40)) - self.frame_4.setMaximumSize(QtCore.QSize(16777215, 40)) - self.frame_4.setFrameShape(QtWidgets.QFrame.NoFrame) - self.frame_4.setFrameShadow(QtWidgets.QFrame.Raised) - self.frame_4.setObjectName("frame_4") - self.gridLayout_9 = QtWidgets.QGridLayout(self.frame_4) - self.gridLayout_9.setObjectName("gridLayout_9") - self.quick_target = QtWidgets.QComboBox(self.frame_4) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.quick_target.sizePolicy().hasHeightForWidth()) - self.quick_target.setSizePolicy(sizePolicy) - self.quick_target.setMinimumSize(QtCore.QSize(0, 20)) - self.quick_target.setMaximumSize(QtCore.QSize(16777215, 20)) - self.quick_target.setObjectName("quick_target") - self.gridLayout_9.addWidget(self.quick_target, 0, 2, 1, 1) - self.label_19 = QtWidgets.QLabel(self.frame_4) - self.label_19.setMaximumSize(QtCore.QSize(16777215, 20)) - self.label_19.setObjectName("label_19") - self.gridLayout_9.addWidget(self.label_19, 0, 0, 1, 1) - self.quick_build = QtWidgets.QPushButton(self.frame_4) - self.quick_build.setMinimumSize(QtCore.QSize(0, 20)) - self.quick_build.setMaximumSize(QtCore.QSize(16777215, 20)) - self.quick_build.setLayoutDirection(QtCore.Qt.LeftToRight) - icon = QtGui.QIcon() - icon.addPixmap(QtGui.QPixmap("icons/system-run.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.quick_build.setIcon(icon) - self.quick_build.setObjectName("quick_build") - self.gridLayout_9.addWidget(self.quick_build, 0, 3, 1, 1) - self.gridLayout_11.addWidget(self.frame_4, 7, 3, 1, 1) - self.remove_item = QtWidgets.QPushButton(self.equipment_tab) - self.remove_item.setEnabled(True) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.remove_item.sizePolicy().hasHeightForWidth()) - self.remove_item.setSizePolicy(sizePolicy) - self.remove_item.setMinimumSize(QtCore.QSize(50, 50)) - self.remove_item.setMaximumSize(QtCore.QSize(50, 50)) - self.remove_item.setText("") - icon1 = QtGui.QIcon() - icon1.addPixmap(QtGui.QPixmap("icons/list-remove.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.remove_item.setIcon(icon1) - self.remove_item.setAutoDefault(False) - self.remove_item.setObjectName("remove_item") - self.gridLayout_11.addWidget(self.remove_item, 4, 2, 1, 1) - spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout_11.addItem(spacerItem1, 1, 2, 1, 1) - self.edit = QtWidgets.QPushButton(self.equipment_tab) - self.edit.setMinimumSize(QtCore.QSize(50, 50)) - self.edit.setMaximumSize(QtCore.QSize(50, 50)) - self.edit.setText("") - icon2 = QtGui.QIcon() - icon2.addPixmap(QtGui.QPixmap("icons/accessories-text-editor.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.edit.setIcon(icon2) - self.edit.setIconSize(QtCore.QSize(24, 24)) - self.edit.setObjectName("edit") - self.gridLayout_11.addWidget(self.edit, 5, 2, 1, 1) - self.add_item = QtWidgets.QPushButton(self.equipment_tab) - self.add_item.setEnabled(True) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.add_item.sizePolicy().hasHeightForWidth()) - self.add_item.setSizePolicy(sizePolicy) - self.add_item.setMinimumSize(QtCore.QSize(50, 50)) - self.add_item.setMaximumSize(QtCore.QSize(50, 50)) - self.add_item.setText("") - icon3 = QtGui.QIcon() - icon3.addPixmap(QtGui.QPixmap("icons/list-add.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.add_item.setIcon(icon3) - self.add_item.setAutoDefault(False) - self.add_item.setObjectName("add_item") - self.gridLayout_11.addWidget(self.add_item, 2, 2, 1, 1) - self.scrollArea_3 = QtWidgets.QScrollArea(self.equipment_tab) - self.scrollArea_3.setWidgetResizable(True) - self.scrollArea_3.setObjectName("scrollArea_3") - self.scrollAreaWidgetContents_3 = QtWidgets.QWidget() - self.scrollAreaWidgetContents_3.setGeometry(QtCore.QRect(0, 0, 162, 607)) - self.scrollAreaWidgetContents_3.setObjectName("scrollAreaWidgetContents_3") - self.gridLayout_4 = QtWidgets.QGridLayout(self.scrollAreaWidgetContents_3) - self.gridLayout_4.setObjectName("gridLayout_4") - self.current_flight_plan = QtWidgets.QListWidget(self.scrollAreaWidgetContents_3) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.current_flight_plan.sizePolicy().hasHeightForWidth()) - self.current_flight_plan.setSizePolicy(sizePolicy) - self.current_flight_plan.setMinimumSize(QtCore.QSize(0, 0)) - self.current_flight_plan.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.current_flight_plan.setObjectName("current_flight_plan") - self.gridLayout_4.addWidget(self.current_flight_plan, 5, 1, 1, 1) - self.current_airframes = QtWidgets.QListWidget(self.scrollAreaWidgetContents_3) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.current_airframes.sizePolicy().hasHeightForWidth()) - self.current_airframes.setSizePolicy(sizePolicy) - self.current_airframes.setMinimumSize(QtCore.QSize(0, 0)) - self.current_airframes.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.current_airframes.setObjectName("current_airframes") - self.gridLayout_4.addWidget(self.current_airframes, 1, 1, 1, 1) - self.current_telemetry = QtWidgets.QListWidget(self.scrollAreaWidgetContents_3) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.current_telemetry.sizePolicy().hasHeightForWidth()) - self.current_telemetry.setSizePolicy(sizePolicy) - self.current_telemetry.setMinimumSize(QtCore.QSize(0, 0)) - self.current_telemetry.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.current_telemetry.setObjectName("current_telemetry") - self.gridLayout_4.addWidget(self.current_telemetry, 11, 1, 1, 1) - self.current_flight_plan_label = QtWidgets.QLabel(self.scrollAreaWidgetContents_3) - self.current_flight_plan_label.setMinimumSize(QtCore.QSize(0, 20)) - self.current_flight_plan_label.setMaximumSize(QtCore.QSize(16777215, 20)) - self.current_flight_plan_label.setObjectName("current_flight_plan_label") - self.gridLayout_4.addWidget(self.current_flight_plan_label, 4, 1, 1, 1) - self.current_airframes_label = QtWidgets.QLabel(self.scrollAreaWidgetContents_3) - self.current_airframes_label.setMinimumSize(QtCore.QSize(0, 20)) - self.current_airframes_label.setMaximumSize(QtCore.QSize(16777215, 20)) - self.current_airframes_label.setObjectName("current_airframes_label") - self.gridLayout_4.addWidget(self.current_airframes_label, 0, 1, 1, 1) - self.current_settings = QtWidgets.QListWidget(self.scrollAreaWidgetContents_3) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.current_settings.sizePolicy().hasHeightForWidth()) - self.current_settings.setSizePolicy(sizePolicy) - self.current_settings.setMinimumSize(QtCore.QSize(0, 0)) - self.current_settings.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.current_settings.setObjectName("current_settings") - self.gridLayout_4.addWidget(self.current_settings, 3, 1, 1, 1) - self.current_radio_label = QtWidgets.QLabel(self.scrollAreaWidgetContents_3) - self.current_radio_label.setMinimumSize(QtCore.QSize(0, 20)) - self.current_radio_label.setMaximumSize(QtCore.QSize(16777215, 20)) - self.current_radio_label.setObjectName("current_radio_label") - self.gridLayout_4.addWidget(self.current_radio_label, 8, 1, 1, 1) - self.select_kml = QtWidgets.QPushButton(self.scrollAreaWidgetContents_3) - self.select_kml.setEnabled(False) - self.select_kml.setMinimumSize(QtCore.QSize(0, 24)) - self.select_kml.setObjectName("select_kml") - self.gridLayout_4.addWidget(self.select_kml, 7, 1, 1, 1) - self.current_radio = QtWidgets.QListWidget(self.scrollAreaWidgetContents_3) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.current_radio.sizePolicy().hasHeightForWidth()) - self.current_radio.setSizePolicy(sizePolicy) - self.current_radio.setMinimumSize(QtCore.QSize(0, 0)) - self.current_radio.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.current_radio.setObjectName("current_radio") - self.gridLayout_4.addWidget(self.current_radio, 9, 1, 1, 1) - self.open_gui = QtWidgets.QPushButton(self.scrollAreaWidgetContents_3) - self.open_gui.setEnabled(False) - self.open_gui.setMinimumSize(QtCore.QSize(0, 24)) - self.open_gui.setObjectName("open_gui") - self.gridLayout_4.addWidget(self.open_gui, 6, 1, 1, 1) - self.current_settings_label = QtWidgets.QLabel(self.scrollAreaWidgetContents_3) - self.current_settings_label.setMinimumSize(QtCore.QSize(0, 20)) - self.current_settings_label.setMaximumSize(QtCore.QSize(16777215, 20)) - self.current_settings_label.setObjectName("current_settings_label") - self.gridLayout_4.addWidget(self.current_settings_label, 2, 1, 1, 1) - self.current_telemetry_label = QtWidgets.QLabel(self.scrollAreaWidgetContents_3) - self.current_telemetry_label.setMinimumSize(QtCore.QSize(0, 20)) - self.current_telemetry_label.setMaximumSize(QtCore.QSize(16777215, 20)) - self.current_telemetry_label.setObjectName("current_telemetry_label") - self.gridLayout_4.addWidget(self.current_telemetry_label, 10, 1, 1, 1) - self.scrollArea_3.setWidget(self.scrollAreaWidgetContents_3) - self.gridLayout_11.addWidget(self.scrollArea_3, 0, 3, 7, 1) - self.search_item_icon = QtWidgets.QLabel(self.equipment_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.search_item_icon.sizePolicy().hasHeightForWidth()) - self.search_item_icon.setSizePolicy(sizePolicy) - self.search_item_icon.setMinimumSize(QtCore.QSize(0, 0)) - self.search_item_icon.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.search_item_icon.setToolTip("") - self.search_item_icon.setFrameShape(QtWidgets.QFrame.NoFrame) - self.search_item_icon.setText("") - self.search_item_icon.setPixmap(QtGui.QPixmap("icons/search_field.png")) - self.search_item_icon.setObjectName("search_item_icon") - self.gridLayout_11.addWidget(self.search_item_icon, 0, 0, 1, 1) - self.main_tab.addTab(self.equipment_tab, "") - self.build_flash_tab = QtWidgets.QWidget() - self.build_flash_tab.setObjectName("build_flash_tab") - self.gridLayout_3 = QtWidgets.QGridLayout(self.build_flash_tab) - self.gridLayout_3.setObjectName("gridLayout_3") - self.label_28 = QtWidgets.QLabel(self.build_flash_tab) - self.label_28.setMinimumSize(QtCore.QSize(20, 20)) - self.label_28.setMaximumSize(QtCore.QSize(20, 20)) - self.label_28.setText("") - self.label_28.setPixmap(QtGui.QPixmap("icons/gtk-info.svg")) - self.label_28.setObjectName("label_28") - self.gridLayout_3.addWidget(self.label_28, 11, 0, 1, 1) - self.build_result = QtWidgets.QLabel(self.build_flash_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.build_result.sizePolicy().hasHeightForWidth()) - self.build_result.setSizePolicy(sizePolicy) - self.build_result.setMinimumSize(QtCore.QSize(0, 20)) - self.build_result.setMaximumSize(QtCore.QSize(16777215, 20)) - self.build_result.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.build_result.setText("") - self.build_result.setObjectName("build_result") - self.gridLayout_3.addWidget(self.build_result, 3, 3, 1, 9) - self.info_nb = QtWidgets.QLabel(self.build_flash_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.info_nb.sizePolicy().hasHeightForWidth()) - self.info_nb.setSizePolicy(sizePolicy) - self.info_nb.setMinimumSize(QtCore.QSize(30, 20)) - self.info_nb.setMaximumSize(QtCore.QSize(30, 20)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.info_nb.setFont(font) - self.info_nb.setStyleSheet("border:2px solid #00ff00;") - self.info_nb.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.info_nb.setText("") - self.info_nb.setObjectName("info_nb") - self.gridLayout_3.addWidget(self.info_nb, 11, 2, 1, 1) - self.flash_resut_icon = QtWidgets.QLabel(self.build_flash_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.flash_resut_icon.sizePolicy().hasHeightForWidth()) - self.flash_resut_icon.setSizePolicy(sizePolicy) - self.flash_resut_icon.setMinimumSize(QtCore.QSize(30, 0)) - self.flash_resut_icon.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.flash_resut_icon.setToolTip("") - self.flash_resut_icon.setFrameShape(QtWidgets.QFrame.NoFrame) - self.flash_resut_icon.setText("") - self.flash_resut_icon.setObjectName("flash_resut_icon") - self.gridLayout_3.addWidget(self.flash_resut_icon, 7, 2, 1, 1) - self.flash_result = QtWidgets.QLabel(self.build_flash_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.flash_result.sizePolicy().hasHeightForWidth()) - self.flash_result.setSizePolicy(sizePolicy) - self.flash_result.setMinimumSize(QtCore.QSize(0, 20)) - self.flash_result.setMaximumSize(QtCore.QSize(16777215, 20)) - self.flash_result.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.flash_result.setText("") - self.flash_result.setObjectName("flash_result") - self.gridLayout_3.addWidget(self.flash_result, 7, 3, 1, 8) - self.label_25 = QtWidgets.QLabel(self.build_flash_tab) - font = QtGui.QFont() - font.setPointSize(14) - font.setBold(True) - font.setWeight(75) - self.label_25.setFont(font) - self.label_25.setObjectName("label_25") - self.gridLayout_3.addWidget(self.label_25, 5, 0, 1, 2) - self.label_10 = QtWidgets.QLabel(self.build_flash_tab) - self.label_10.setObjectName("label_10") - self.gridLayout_3.addWidget(self.label_10, 11, 8, 1, 1) - self.line_3 = QtWidgets.QFrame(self.build_flash_tab) - self.line_3.setFrameShape(QtWidgets.QFrame.HLine) - self.line_3.setFrameShadow(QtWidgets.QFrame.Sunken) - self.line_3.setObjectName("line_3") - self.gridLayout_3.addWidget(self.line_3, 4, 0, 1, 12) - self.label_26 = QtWidgets.QLabel(self.build_flash_tab) - self.label_26.setMinimumSize(QtCore.QSize(0, 0)) - self.label_26.setMaximumSize(QtCore.QSize(60, 16777215)) - self.label_26.setObjectName("label_26") - self.gridLayout_3.addWidget(self.label_26, 1, 0, 1, 2) - self.label_11 = QtWidgets.QLabel(self.build_flash_tab) - self.label_11.setObjectName("label_11") - self.gridLayout_3.addWidget(self.label_11, 11, 5, 1, 1) - self.label_13 = QtWidgets.QLabel(self.build_flash_tab) - self.label_13.setMinimumSize(QtCore.QSize(0, 0)) - self.label_13.setMaximumSize(QtCore.QSize(60, 16777215)) - self.label_13.setObjectName("label_13") - self.gridLayout_3.addWidget(self.label_13, 7, 0, 1, 2) - self.warnings_nb = QtWidgets.QLabel(self.build_flash_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.warnings_nb.sizePolicy().hasHeightForWidth()) - self.warnings_nb.setSizePolicy(sizePolicy) - self.warnings_nb.setMinimumSize(QtCore.QSize(30, 20)) - self.warnings_nb.setMaximumSize(QtCore.QSize(30, 20)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.warnings_nb.setFont(font) - self.warnings_nb.setStyleSheet("border:2px solid #ffaa00;") - self.warnings_nb.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.warnings_nb.setText("") - self.warnings_nb.setObjectName("warnings_nb") - self.gridLayout_3.addWidget(self.warnings_nb, 11, 6, 1, 1) - self.label_23 = QtWidgets.QLabel(self.build_flash_tab) - font = QtGui.QFont() - font.setPointSize(14) - font.setBold(True) - font.setWeight(75) - self.label_23.setFont(font) - self.label_23.setObjectName("label_23") - self.gridLayout_3.addWidget(self.label_23, 0, 0, 1, 2) - self.label_12 = QtWidgets.QLabel(self.build_flash_tab) - self.label_12.setMinimumSize(QtCore.QSize(0, 0)) - self.label_12.setMaximumSize(QtCore.QSize(60, 16777215)) - self.label_12.setObjectName("label_12") - self.gridLayout_3.addWidget(self.label_12, 6, 0, 1, 2) - spacerItem2 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.gridLayout_3.addItem(spacerItem2, 11, 10, 1, 1) - self.label_14 = QtWidgets.QLabel(self.build_flash_tab) - self.label_14.setObjectName("label_14") - self.gridLayout_3.addWidget(self.label_14, 11, 1, 1, 1) - self.label_15 = QtWidgets.QLabel(self.build_flash_tab) - self.label_15.setMinimumSize(QtCore.QSize(20, 20)) - self.label_15.setMaximumSize(QtCore.QSize(20, 20)) - self.label_15.setText("") - self.label_15.setPixmap(QtGui.QPixmap("icons/dialog-error.svg")) - self.label_15.setObjectName("label_15") - self.gridLayout_3.addWidget(self.label_15, 11, 7, 1, 1) - self.target = QtWidgets.QComboBox(self.build_flash_tab) - self.target.setMinimumSize(QtCore.QSize(0, 30)) - self.target.setMaximumSize(QtCore.QSize(16777215, 30)) - self.target.setObjectName("target") - self.gridLayout_3.addWidget(self.target, 1, 2, 1, 8) - self.label_16 = QtWidgets.QLabel(self.build_flash_tab) - self.label_16.setMinimumSize(QtCore.QSize(20, 20)) - self.label_16.setMaximumSize(QtCore.QSize(20, 20)) - self.label_16.setText("") - self.label_16.setPixmap(QtGui.QPixmap("icons/dialog-warning.png")) - self.label_16.setObjectName("label_16") - self.gridLayout_3.addWidget(self.label_16, 11, 4, 1, 1) - self.clean = QtWidgets.QPushButton(self.build_flash_tab) - self.clean.setMinimumSize(QtCore.QSize(130, 30)) - self.clean.setMaximumSize(QtCore.QSize(130, 30)) - self.clean.setLayoutDirection(QtCore.Qt.LeftToRight) - icon4 = QtGui.QIcon() - icon4.addPixmap(QtGui.QPixmap("icons/edit-clear.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.clean.setIcon(icon4) - self.clean.setObjectName("clean") - self.gridLayout_3.addWidget(self.clean, 1, 11, 1, 1) - self.line_4 = QtWidgets.QFrame(self.build_flash_tab) - self.line_4.setFrameShape(QtWidgets.QFrame.HLine) - self.line_4.setFrameShadow(QtWidgets.QFrame.Sunken) - self.line_4.setObjectName("line_4") - self.gridLayout_3.addWidget(self.line_4, 9, 0, 1, 12) - self.errors_nb = QtWidgets.QLabel(self.build_flash_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.errors_nb.sizePolicy().hasHeightForWidth()) - self.errors_nb.setSizePolicy(sizePolicy) - self.errors_nb.setMinimumSize(QtCore.QSize(30, 20)) - self.errors_nb.setMaximumSize(QtCore.QSize(30, 20)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.errors_nb.setFont(font) - self.errors_nb.setAutoFillBackground(False) - self.errors_nb.setStyleSheet("border:2px solid #ff0000;") - self.errors_nb.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.errors_nb.setText("") - self.errors_nb.setObjectName("errors_nb") - self.gridLayout_3.addWidget(self.errors_nb, 11, 9, 1, 1) - self.device = QtWidgets.QComboBox(self.build_flash_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.device.sizePolicy().hasHeightForWidth()) - self.device.setSizePolicy(sizePolicy) - self.device.setMinimumSize(QtCore.QSize(0, 30)) - self.device.setMaximumSize(QtCore.QSize(16777215, 30)) - self.device.setObjectName("device") - self.gridLayout_3.addWidget(self.device, 6, 2, 1, 8) - self.build = QtWidgets.QPushButton(self.build_flash_tab) - self.build.setMinimumSize(QtCore.QSize(130, 30)) - self.build.setMaximumSize(QtCore.QSize(130, 30)) - self.build.setLayoutDirection(QtCore.Qt.LeftToRight) - self.build.setIcon(icon) - self.build.setObjectName("build") - self.gridLayout_3.addWidget(self.build, 2, 11, 1, 1) - self.show_console = QtWidgets.QPushButton(self.build_flash_tab) - self.show_console.setMinimumSize(QtCore.QSize(0, 30)) - self.show_console.setMaximumSize(QtCore.QSize(16777215, 20)) - self.show_console.setLayoutDirection(QtCore.Qt.LeftToRight) - icon5 = QtGui.QIcon() - icon5.addPixmap(QtGui.QPixmap("icons/utilities-terminal.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.show_console.setIcon(icon5) - self.show_console.setObjectName("show_console") - self.gridLayout_3.addWidget(self.show_console, 11, 11, 1, 1, QtCore.Qt.AlignVCenter) - spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout_3.addItem(spacerItem3, 12, 11, 1, 1) - self.build_result_icon = QtWidgets.QLabel(self.build_flash_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.build_result_icon.sizePolicy().hasHeightForWidth()) - self.build_result_icon.setSizePolicy(sizePolicy) - self.build_result_icon.setMinimumSize(QtCore.QSize(0, 0)) - self.build_result_icon.setMaximumSize(QtCore.QSize(30, 16777215)) - self.build_result_icon.setToolTip("") - self.build_result_icon.setFrameShape(QtWidgets.QFrame.NoFrame) - self.build_result_icon.setText("") - self.build_result_icon.setObjectName("build_result_icon") - self.gridLayout_3.addWidget(self.build_result_icon, 3, 2, 1, 1) - self.upload = QtWidgets.QPushButton(self.build_flash_tab) - self.upload.setEnabled(True) - self.upload.setMinimumSize(QtCore.QSize(130, 30)) - self.upload.setMaximumSize(QtCore.QSize(130, 30)) - icon6 = QtGui.QIcon() - icon6.addPixmap(QtGui.QPixmap("icons/go-up.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.upload.setIcon(icon6) - self.upload.setObjectName("upload") - self.gridLayout_3.addWidget(self.upload, 6, 11, 1, 1) - self.label_9 = QtWidgets.QLabel(self.build_flash_tab) - self.label_9.setMinimumSize(QtCore.QSize(0, 30)) - self.label_9.setMaximumSize(QtCore.QSize(60, 16777215)) - self.label_9.setObjectName("label_9") - self.gridLayout_3.addWidget(self.label_9, 3, 0, 1, 2) - self.main_tab.addTab(self.build_flash_tab, "") - self.sessions_tab = QtWidgets.QWidget() - self.sessions_tab.setObjectName("sessions_tab") - self.gridLayout_2 = QtWidgets.QGridLayout(self.sessions_tab) - self.gridLayout_2.setObjectName("gridLayout_2") - self.label_7 = QtWidgets.QLabel(self.sessions_tab) - self.label_7.setObjectName("label_7") - self.gridLayout_2.addWidget(self.label_7, 5, 0, 1, 2) - self.programs = QtWidgets.QListWidget(self.sessions_tab) - self.programs.setMinimumSize(QtCore.QSize(0, 0)) - self.programs.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.programs.setLayoutDirection(QtCore.Qt.LeftToRight) - self.programs.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) - self.programs.setIconSize(QtCore.QSize(10, 10)) - self.programs.setObjectName("programs") - self.gridLayout_2.addWidget(self.programs, 2, 2, 3, 1) - self.label_8 = QtWidgets.QLabel(self.sessions_tab) - self.label_8.setObjectName("label_8") - self.gridLayout_2.addWidget(self.label_8, 2, 0, 1, 2) - spacerItem4 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout_2.addItem(spacerItem4, 3, 3, 1, 1) - self.start_all_button = QtWidgets.QPushButton(self.sessions_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.start_all_button.sizePolicy().hasHeightForWidth()) - self.start_all_button.setSizePolicy(sizePolicy) - self.start_all_button.setMinimumSize(QtCore.QSize(0, 50)) - self.start_all_button.setMaximumSize(QtCore.QSize(16777215, 50)) - font = QtGui.QFont() - font.setBold(True) - font.setItalic(False) - font.setUnderline(False) - font.setWeight(75) - font.setStrikeOut(False) - font.setKerning(True) - self.start_all_button.setFont(font) - icon7 = QtGui.QIcon() - icon7.addPixmap(QtGui.QPixmap("icons/media-playback-start.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.start_all_button.setIcon(icon7) - self.start_all_button.setObjectName("start_all_button") - self.gridLayout_2.addWidget(self.start_all_button, 5, 3, 1, 1) - spacerItem5 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout_2.addItem(spacerItem5, 7, 2, 1, 1) - self.play_stop_program = QtWidgets.QPushButton(self.sessions_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.play_stop_program.sizePolicy().hasHeightForWidth()) - self.play_stop_program.setSizePolicy(sizePolicy) - self.play_stop_program.setMinimumSize(QtCore.QSize(0, 50)) - self.play_stop_program.setMaximumSize(QtCore.QSize(16777215, 50)) - self.play_stop_program.setIcon(icon7) - self.play_stop_program.setAutoDefault(False) - self.play_stop_program.setObjectName("play_stop_program") - self.gridLayout_2.addWidget(self.play_stop_program, 2, 3, 1, 1) - self.options = QtWidgets.QListWidget(self.sessions_tab) - self.options.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.options.setObjectName("options") - self.gridLayout_2.addWidget(self.options, 5, 2, 2, 1) - self.remove_program = QtWidgets.QPushButton(self.sessions_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.remove_program.sizePolicy().hasHeightForWidth()) - self.remove_program.setSizePolicy(sizePolicy) - self.remove_program.setMinimumSize(QtCore.QSize(30, 30)) - self.remove_program.setMaximumSize(QtCore.QSize(30, 30)) - self.remove_program.setText("") - self.remove_program.setIcon(icon1) - self.remove_program.setAutoDefault(False) - self.remove_program.setObjectName("remove_program") - self.gridLayout_2.addWidget(self.remove_program, 4, 0, 1, 1) - self.session = QtWidgets.QComboBox(self.sessions_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.session.sizePolicy().hasHeightForWidth()) - self.session.setSizePolicy(sizePolicy) - self.session.setObjectName("session") - self.gridLayout_2.addWidget(self.session, 1, 2, 1, 1) - self.kill_all_button = QtWidgets.QPushButton(self.sessions_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.kill_all_button.sizePolicy().hasHeightForWidth()) - self.kill_all_button.setSizePolicy(sizePolicy) - self.kill_all_button.setMinimumSize(QtCore.QSize(0, 50)) - self.kill_all_button.setMaximumSize(QtCore.QSize(16777215, 50)) - font = QtGui.QFont() - font.setBold(True) - font.setItalic(False) - font.setUnderline(False) - font.setWeight(75) - font.setStrikeOut(False) - font.setKerning(True) - self.kill_all_button.setFont(font) - self.kill_all_button.setLayoutDirection(QtCore.Qt.LeftToRight) - icon8 = QtGui.QIcon() - icon8.addPixmap(QtGui.QPixmap("icons/process-stop.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.kill_all_button.setIcon(icon8) - self.kill_all_button.setObjectName("kill_all_button") - self.gridLayout_2.addWidget(self.kill_all_button, 4, 3, 1, 1) - self.label_4 = QtWidgets.QLabel(self.sessions_tab) - self.label_4.setObjectName("label_4") - self.gridLayout_2.addWidget(self.label_4, 1, 0, 1, 2) - self.add_program = QtWidgets.QPushButton(self.sessions_tab) - self.add_program.setEnabled(False) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.add_program.sizePolicy().hasHeightForWidth()) - self.add_program.setSizePolicy(sizePolicy) - self.add_program.setMinimumSize(QtCore.QSize(30, 30)) - self.add_program.setMaximumSize(QtCore.QSize(30, 30)) - self.add_program.setText("") - self.add_program.setIcon(icon3) - self.add_program.setAutoDefault(False) - self.add_program.setObjectName("add_program") - self.gridLayout_2.addWidget(self.add_program, 4, 1, 1, 1) - self.remove_option = QtWidgets.QPushButton(self.sessions_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.remove_option.sizePolicy().hasHeightForWidth()) - self.remove_option.setSizePolicy(sizePolicy) - self.remove_option.setMinimumSize(QtCore.QSize(30, 30)) - self.remove_option.setMaximumSize(QtCore.QSize(30, 30)) - self.remove_option.setText("") - self.remove_option.setIcon(icon1) - self.remove_option.setAutoDefault(False) - self.remove_option.setObjectName("remove_option") - self.gridLayout_2.addWidget(self.remove_option, 6, 0, 1, 1) - self.add_option = QtWidgets.QPushButton(self.sessions_tab) - self.add_option.setEnabled(True) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.add_option.sizePolicy().hasHeightForWidth()) - self.add_option.setSizePolicy(sizePolicy) - self.add_option.setMinimumSize(QtCore.QSize(30, 30)) - self.add_option.setMaximumSize(QtCore.QSize(30, 30)) - self.add_option.setText("") - self.add_option.setIcon(icon3) - self.add_option.setAutoDefault(False) - self.add_option.setObjectName("add_option") - self.gridLayout_2.addWidget(self.add_option, 6, 1, 1, 1) - self.tools_menu = ToolsMenu(self.sessions_tab) - self.tools_menu.setMinimumSize(QtCore.QSize(0, 0)) - self.tools_menu.setBaseSize(QtCore.QSize(200, 140)) - self.tools_menu.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.tools_menu.setFrameShadow(QtWidgets.QFrame.Raised) - self.tools_menu.setObjectName("tools_menu") - self.gridLayout_2.addWidget(self.tools_menu, 0, 2, 1, 1) - self.main_tab.addTab(self.sessions_tab, "") - self.console_tab = QtWidgets.QWidget() - self.console_tab.setObjectName("console_tab") - self.gridLayout_5 = QtWidgets.QGridLayout(self.console_tab) - self.gridLayout_5.setObjectName("gridLayout_5") - self.line_7 = QtWidgets.QFrame(self.console_tab) - self.line_7.setFrameShape(QtWidgets.QFrame.HLine) - self.line_7.setFrameShadow(QtWidgets.QFrame.Sunken) - self.line_7.setObjectName("line_7") - self.gridLayout_5.addWidget(self.line_7, 10, 1, 1, 1) - self.console = QtWidgets.QTextEdit(self.console_tab) - self.console.setEnabled(True) - font = QtGui.QFont() - font.setFamily("Ubuntu") - self.console.setFont(font) - self.console.setLayoutDirection(QtCore.Qt.LeftToRight) - self.console.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) - self.console.setTextInteractionFlags(QtCore.Qt.TextSelectableByKeyboard|QtCore.Qt.TextSelectableByMouse) - self.console.setObjectName("console") - self.gridLayout_5.addWidget(self.console, 0, 0, 13, 1) - self.label_24 = QtWidgets.QLabel(self.console_tab) - font = QtGui.QFont() - font.setPointSize(14) - font.setBold(True) - font.setWeight(75) - self.label_24.setFont(font) - self.label_24.setObjectName("label_24") - self.gridLayout_5.addWidget(self.label_24, 0, 1, 1, 1) - self.important = QtWidgets.QRadioButton(self.console_tab) - self.important.setToolTip("") - self.important.setChecked(False) - self.important.setObjectName("important") - self.gridLayout_5.addWidget(self.important, 2, 1, 1, 1) - self.custom = QtWidgets.QRadioButton(self.console_tab) - self.custom.setToolTip("") - self.custom.setChecked(True) - self.custom.setObjectName("custom") - self.gridLayout_5.addWidget(self.custom, 3, 1, 1, 1) - self.all = QtWidgets.QRadioButton(self.console_tab) - self.all.setToolTip("") - self.all.setChecked(False) - self.all.setObjectName("all") - self.gridLayout_5.addWidget(self.all, 4, 1, 1, 1) - self.clean_console = QtWidgets.QPushButton(self.console_tab) - self.clean_console.setIcon(icon4) - self.clean_console.setObjectName("clean_console") - self.gridLayout_5.addWidget(self.clean_console, 12, 1, 1, 1) - self.horizontalLayout_2 = QtWidgets.QHBoxLayout() - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.display_info = QtWidgets.QCheckBox(self.console_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.display_info.sizePolicy().hasHeightForWidth()) - self.display_info.setSizePolicy(sizePolicy) - icon9 = QtGui.QIcon() - icon9.addPixmap(QtGui.QPixmap("icons/gtk-info.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.display_info.setIcon(icon9) - self.display_info.setObjectName("display_info") - self.horizontalLayout_2.addWidget(self.display_info) - self.gridLayout_5.addLayout(self.horizontalLayout_2, 7, 1, 1, 1) - self.horizontalLayout_4 = QtWidgets.QHBoxLayout() - self.horizontalLayout_4.setObjectName("horizontalLayout_4") - self.display_warnings = QtWidgets.QCheckBox(self.console_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.display_warnings.sizePolicy().hasHeightForWidth()) - self.display_warnings.setSizePolicy(sizePolicy) - icon10 = QtGui.QIcon() - icon10.addPixmap(QtGui.QPixmap("icons/dialog-warning.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.display_warnings.setIcon(icon10) - self.display_warnings.setChecked(False) - self.display_warnings.setObjectName("display_warnings") - self.horizontalLayout_4.addWidget(self.display_warnings) - self.gridLayout_5.addLayout(self.horizontalLayout_4, 8, 1, 1, 1) - spacerItem6 = QtWidgets.QSpacerItem(20, 261, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout_5.addItem(spacerItem6, 11, 1, 1, 1) - self.line_5 = QtWidgets.QFrame(self.console_tab) - self.line_5.setFrameShape(QtWidgets.QFrame.HLine) - self.line_5.setFrameShadow(QtWidgets.QFrame.Sunken) - self.line_5.setObjectName("line_5") - self.gridLayout_5.addWidget(self.line_5, 5, 1, 1, 1) - self.horizontalLayout_5 = QtWidgets.QHBoxLayout() - self.horizontalLayout_5.setObjectName("horizontalLayout_5") - self.display_errors = QtWidgets.QCheckBox(self.console_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.display_errors.sizePolicy().hasHeightForWidth()) - self.display_errors.setSizePolicy(sizePolicy) - icon11 = QtGui.QIcon() - icon11.addPixmap(QtGui.QPixmap("icons/dialog-error.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.display_errors.setIcon(icon11) - self.display_errors.setChecked(False) - self.display_errors.setObjectName("display_errors") - self.horizontalLayout_5.addWidget(self.display_errors) - self.gridLayout_5.addLayout(self.horizontalLayout_5, 9, 1, 1, 1) - self.line_6 = QtWidgets.QFrame(self.console_tab) - self.line_6.setFrameShape(QtWidgets.QFrame.HLine) - self.line_6.setFrameShadow(QtWidgets.QFrame.Sunken) - self.line_6.setObjectName("line_6") - self.gridLayout_5.addWidget(self.line_6, 1, 1, 1, 1) - self.horizontalLayout_6 = QtWidgets.QHBoxLayout() - self.horizontalLayout_6.setObjectName("horizontalLayout_6") - self.display_default = QtWidgets.QCheckBox(self.console_tab) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.display_default.sizePolicy().hasHeightForWidth()) - self.display_default.setSizePolicy(sizePolicy) - self.display_default.setObjectName("display_default") - self.horizontalLayout_6.addWidget(self.display_default) - self.gridLayout_5.addLayout(self.horizontalLayout_6, 6, 1, 1, 1) - self.main_tab.addTab(self.console_tab, "") - self.gridLayout_10.addWidget(self.main_tab, 1, 0, 1, 1) - self.frame = QtWidgets.QFrame(self.centralwidget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.frame.sizePolicy().hasHeightForWidth()) - self.frame.setSizePolicy(sizePolicy) - self.frame.setMaximumSize(QtCore.QSize(16777215, 20)) - self.frame.setFrameShape(QtWidgets.QFrame.NoFrame) - self.frame.setFrameShadow(QtWidgets.QFrame.Raised) - self.frame.setLineWidth(0) - self.frame.setObjectName("frame") - self.gridLayout_6 = QtWidgets.QGridLayout(self.frame) - self.gridLayout_6.setContentsMargins(-1, 0, -1, 0) - self.gridLayout_6.setVerticalSpacing(0) - self.gridLayout_6.setObjectName("gridLayout_6") - self.line_2 = QtWidgets.QFrame(self.frame) - self.line_2.setFrameShape(QtWidgets.QFrame.VLine) - self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken) - self.line_2.setObjectName("line_2") - self.gridLayout_6.addWidget(self.line_2, 0, 5, 1, 1) - self.label_20 = QtWidgets.QLabel(self.frame) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.label_20.sizePolicy().hasHeightForWidth()) - self.label_20.setSizePolicy(sizePolicy) - self.label_20.setMinimumSize(QtCore.QSize(0, 20)) - self.label_20.setMaximumSize(QtCore.QSize(16777215, 20)) - self.label_20.setObjectName("label_20") - self.gridLayout_6.addWidget(self.label_20, 0, 0, 1, 1) - self.open_home_terminal = QtWidgets.QPushButton(self.frame) - self.open_home_terminal.setMinimumSize(QtCore.QSize(0, 20)) - self.open_home_terminal.setMaximumSize(QtCore.QSize(16777215, 20)) - self.open_home_terminal.setText("") - self.open_home_terminal.setDefault(False) - self.open_home_terminal.setFlat(False) - self.open_home_terminal.setObjectName("open_home_terminal") - self.gridLayout_6.addWidget(self.open_home_terminal, 0, 1, 1, 1) - self.run_version = QtWidgets.QLabel(self.frame) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.run_version.sizePolicy().hasHeightForWidth()) - self.run_version.setSizePolicy(sizePolicy) - self.run_version.setMinimumSize(QtCore.QSize(0, 20)) - self.run_version.setMaximumSize(QtCore.QSize(16777215, 20)) - self.run_version.setFrameShape(QtWidgets.QFrame.NoFrame) - self.run_version.setText("") - self.run_version.setObjectName("run_version") - self.gridLayout_6.addWidget(self.run_version, 0, 7, 1, 1) - self.label_29 = QtWidgets.QLabel(self.frame) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.label_29.sizePolicy().hasHeightForWidth()) - self.label_29.setSizePolicy(sizePolicy) - self.label_29.setMinimumSize(QtCore.QSize(0, 20)) - self.label_29.setMaximumSize(QtCore.QSize(16777215, 20)) - self.label_29.setObjectName("label_29") - self.gridLayout_6.addWidget(self.label_29, 0, 9, 1, 1) - self.build_version = QtWidgets.QLabel(self.frame) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.build_version.sizePolicy().hasHeightForWidth()) - self.build_version.setSizePolicy(sizePolicy) - self.build_version.setMinimumSize(QtCore.QSize(0, 20)) - self.build_version.setMaximumSize(QtCore.QSize(16777215, 20)) - self.build_version.setFrameShape(QtWidgets.QFrame.NoFrame) - self.build_version.setText("") - self.build_version.setObjectName("build_version") - self.gridLayout_6.addWidget(self.build_version, 0, 10, 1, 1) - self.label_22 = QtWidgets.QLabel(self.frame) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.label_22.sizePolicy().hasHeightForWidth()) - self.label_22.setSizePolicy(sizePolicy) - self.label_22.setMinimumSize(QtCore.QSize(0, 20)) - self.label_22.setMaximumSize(QtCore.QSize(16777215, 20)) - self.label_22.setObjectName("label_22") - self.gridLayout_6.addWidget(self.label_22, 0, 6, 1, 1) - self.switch_mode = QtWidgets.QPushButton(self.frame) - self.switch_mode.setEnabled(False) - self.switch_mode.setMinimumSize(QtCore.QSize(0, 20)) - self.switch_mode.setMaximumSize(QtCore.QSize(16777215, 20)) - self.switch_mode.setText("") - self.switch_mode.setFlat(False) - self.switch_mode.setObjectName("switch_mode") - self.gridLayout_6.addWidget(self.switch_mode, 0, 4, 1, 1) - self.line_8 = QtWidgets.QFrame(self.frame) - self.line_8.setFrameShape(QtWidgets.QFrame.VLine) - self.line_8.setFrameShadow(QtWidgets.QFrame.Sunken) - self.line_8.setObjectName("line_8") - self.gridLayout_6.addWidget(self.line_8, 0, 8, 1, 1) - self.line = QtWidgets.QFrame(self.frame) - self.line.setFrameShape(QtWidgets.QFrame.VLine) - self.line.setFrameShadow(QtWidgets.QFrame.Sunken) - self.line.setObjectName("line") - self.gridLayout_6.addWidget(self.line, 0, 2, 1, 1) - self.label_21 = QtWidgets.QLabel(self.frame) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.label_21.sizePolicy().hasHeightForWidth()) - self.label_21.setSizePolicy(sizePolicy) - self.label_21.setMinimumSize(QtCore.QSize(0, 20)) - self.label_21.setMaximumSize(QtCore.QSize(16777215, 20)) - self.label_21.setObjectName("label_21") - self.gridLayout_6.addWidget(self.label_21, 0, 3, 1, 1) - spacerItem7 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) - self.gridLayout_6.addItem(spacerItem7, 0, 11, 1, 1) - self.gridLayout_10.addWidget(self.frame, 2, 0, 1, 2) - MainWindow.setCentralWidget(self.centralwidget) - self.menubar = QtWidgets.QMenuBar(MainWindow) - self.menubar.setGeometry(QtCore.QRect(0, 0, 833, 25)) - self.menubar.setObjectName("menubar") - self.menuSet = QtWidgets.QMenu(self.menubar) - self.menuSet.setObjectName("menuSet") - self.menuConfiguration = QtWidgets.QMenu(self.menubar) - self.menuConfiguration.setObjectName("menuConfiguration") - self.menuMenu = QtWidgets.QMenu(self.menubar) - self.menuMenu.setObjectName("menuMenu") - self.menuView = QtWidgets.QMenu(self.menubar) - self.menuView.setObjectName("menuView") - self.menuHelp = QtWidgets.QMenu(self.menubar) - self.menuHelp.setObjectName("menuHelp") - self.menuSession = QtWidgets.QMenu(self.menubar) - self.menuSession.setObjectName("menuSession") - MainWindow.setMenuBar(self.menubar) - self.statusbar = QtWidgets.QStatusBar(MainWindow) - self.statusbar.setObjectName("statusbar") - MainWindow.setStatusBar(self.statusbar) - self.dockWidget = QtWidgets.QDockWidget(MainWindow) - self.dockWidget.setObjectName("dockWidget") - self.dockWidgetContents = QtWidgets.QWidget() - self.dockWidgetContents.setObjectName("dockWidgetContents") - self.horizontalLayout = QtWidgets.QHBoxLayout(self.dockWidgetContents) - self.horizontalLayout.setObjectName("horizontalLayout") - self.stackedWidget = QtWidgets.QStackedWidget(self.dockWidgetContents) - self.stackedWidget.setEnabled(True) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.stackedWidget.sizePolicy().hasHeightForWidth()) - self.stackedWidget.setSizePolicy(sizePolicy) - self.stackedWidget.setMinimumSize(QtCore.QSize(200, 0)) - self.stackedWidget.setMaximumSize(QtCore.QSize(200, 16777215)) - self.stackedWidget.setToolTip("") - self.stackedWidget.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.stackedWidget.setFrameShadow(QtWidgets.QFrame.Plain) - self.stackedWidget.setObjectName("stackedWidget") - self.widget_2 = QtWidgets.QWidget() - self.widget_2.setObjectName("widget_2") - self.gridLayout_7 = QtWidgets.QGridLayout(self.widget_2) - self.gridLayout_7.setObjectName("gridLayout_7") - self.quick_restart = QtWidgets.QPushButton(self.widget_2) - self.quick_restart.setEnabled(True) - font = QtGui.QFont() - font.setBold(True) - font.setItalic(False) - font.setUnderline(False) - font.setWeight(75) - font.setStrikeOut(False) - font.setKerning(True) - self.quick_restart.setFont(font) - self.quick_restart.setIcon(icon7) - self.quick_restart.setObjectName("quick_restart") - self.gridLayout_7.addWidget(self.quick_restart, 6, 0, 1, 1) - self.label_33 = QtWidgets.QLabel(self.widget_2) - self.label_33.setObjectName("label_33") - self.gridLayout_7.addWidget(self.label_33, 3, 0, 1, 1) - self.programs_overview_1 = QtWidgets.QListWidget(self.widget_2) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.programs_overview_1.sizePolicy().hasHeightForWidth()) - self.programs_overview_1.setSizePolicy(sizePolicy) - self.programs_overview_1.setMinimumSize(QtCore.QSize(0, 0)) - self.programs_overview_1.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.programs_overview_1.setObjectName("programs_overview_1") - self.gridLayout_7.addWidget(self.programs_overview_1, 4, 0, 1, 1) - self.label_32 = QtWidgets.QLabel(self.widget_2) - self.label_32.setObjectName("label_32") - self.gridLayout_7.addWidget(self.label_32, 1, 0, 1, 1) - self.session_overview_1 = QtWidgets.QComboBox(self.widget_2) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.session_overview_1.sizePolicy().hasHeightForWidth()) - self.session_overview_1.setSizePolicy(sizePolicy) - self.session_overview_1.setObjectName("session_overview_1") - self.gridLayout_7.addWidget(self.session_overview_1, 2, 0, 1, 1) - self.label_6 = QtWidgets.QLabel(self.widget_2) - self.label_6.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.label_6.setTextFormat(QtCore.Qt.AutoText) - self.label_6.setScaledContents(False) - self.label_6.setWordWrap(False) - self.label_6.setObjectName("label_6") - self.gridLayout_7.addWidget(self.label_6, 0, 0, 1, 1) - spacerItem8 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout_7.addItem(spacerItem8, 10, 0, 1, 1) - self.quick_kill = QtWidgets.QPushButton(self.widget_2) - self.quick_kill.setEnabled(True) - font = QtGui.QFont() - font.setBold(True) - font.setItalic(False) - font.setUnderline(False) - font.setWeight(75) - font.setStrikeOut(False) - font.setKerning(True) - self.quick_kill.setFont(font) - self.quick_kill.setIcon(icon8) - self.quick_kill.setObjectName("quick_kill") - self.gridLayout_7.addWidget(self.quick_kill, 5, 0, 1, 1) - self.stackedWidget.addWidget(self.widget_2) - self.area = QtWidgets.QWidget() - self.area.setObjectName("area") - self.gridLayout_8 = QtWidgets.QGridLayout(self.area) - self.gridLayout_8.setObjectName("gridLayout_8") - self.scrollArea = QtWidgets.QScrollArea(self.area) - self.scrollArea.setWidgetResizable(True) - self.scrollArea.setObjectName("scrollArea") - self.scrollAreaWidgetContents = QtWidgets.QWidget() - self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 151, 583)) - self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents") - self.gridLayout_13 = QtWidgets.QGridLayout(self.scrollAreaWidgetContents) - self.gridLayout_13.setObjectName("gridLayout_13") - self.label_5 = QtWidgets.QLabel(self.scrollAreaWidgetContents) - self.label_5.setMinimumSize(QtCore.QSize(0, 30)) - self.label_5.setMaximumSize(QtCore.QSize(16777215, 30)) - self.label_5.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.label_5.setTextFormat(QtCore.Qt.AutoText) - self.label_5.setScaledContents(False) - self.label_5.setObjectName("label_5") - self.gridLayout_13.addWidget(self.label_5, 0, 0, 1, 1) - self.label_35 = QtWidgets.QLabel(self.scrollAreaWidgetContents) - self.label_35.setMinimumSize(QtCore.QSize(0, 20)) - self.label_35.setMaximumSize(QtCore.QSize(16777215, 20)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_35.setFont(font) - self.label_35.setObjectName("label_35") - self.gridLayout_13.addWidget(self.label_35, 1, 0, 1, 1) - self.airframes_overview = QtWidgets.QListWidget(self.scrollAreaWidgetContents) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.airframes_overview.sizePolicy().hasHeightForWidth()) - self.airframes_overview.setSizePolicy(sizePolicy) - self.airframes_overview.setMinimumSize(QtCore.QSize(0, 0)) - self.airframes_overview.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.airframes_overview.setToolTip("") - self.airframes_overview.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.airframes_overview.setAutoScroll(True) - self.airframes_overview.setTextElideMode(QtCore.Qt.ElideLeft) - self.airframes_overview.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerItem) - self.airframes_overview.setResizeMode(QtWidgets.QListView.Adjust) - self.airframes_overview.setLayoutMode(QtWidgets.QListView.SinglePass) - self.airframes_overview.setObjectName("airframes_overview") - self.gridLayout_13.addWidget(self.airframes_overview, 2, 0, 1, 1) - self.label_34 = QtWidgets.QLabel(self.scrollAreaWidgetContents) - self.label_34.setMinimumSize(QtCore.QSize(0, 20)) - self.label_34.setMaximumSize(QtCore.QSize(16777215, 20)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_34.setFont(font) - self.label_34.setObjectName("label_34") - self.gridLayout_13.addWidget(self.label_34, 3, 0, 1, 1) - self.settings_overview = QtWidgets.QListWidget(self.scrollAreaWidgetContents) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.settings_overview.sizePolicy().hasHeightForWidth()) - self.settings_overview.setSizePolicy(sizePolicy) - self.settings_overview.setMinimumSize(QtCore.QSize(0, 0)) - self.settings_overview.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.settings_overview.setToolTip("") - self.settings_overview.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.settings_overview.setAutoScroll(True) - self.settings_overview.setTextElideMode(QtCore.Qt.ElideLeft) - self.settings_overview.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerItem) - self.settings_overview.setResizeMode(QtWidgets.QListView.Adjust) - self.settings_overview.setLayoutMode(QtWidgets.QListView.SinglePass) - self.settings_overview.setObjectName("settings_overview") - self.gridLayout_13.addWidget(self.settings_overview, 4, 0, 1, 1) - self.label_36 = QtWidgets.QLabel(self.scrollAreaWidgetContents) - self.label_36.setMinimumSize(QtCore.QSize(0, 20)) - self.label_36.setMaximumSize(QtCore.QSize(16777215, 20)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_36.setFont(font) - self.label_36.setObjectName("label_36") - self.gridLayout_13.addWidget(self.label_36, 5, 0, 1, 1) - self.flight_plan_overview = QtWidgets.QListWidget(self.scrollAreaWidgetContents) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.flight_plan_overview.sizePolicy().hasHeightForWidth()) - self.flight_plan_overview.setSizePolicy(sizePolicy) - self.flight_plan_overview.setMinimumSize(QtCore.QSize(0, 0)) - self.flight_plan_overview.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.flight_plan_overview.setToolTip("") - self.flight_plan_overview.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.flight_plan_overview.setAutoScroll(True) - self.flight_plan_overview.setTextElideMode(QtCore.Qt.ElideLeft) - self.flight_plan_overview.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerItem) - self.flight_plan_overview.setResizeMode(QtWidgets.QListView.Adjust) - self.flight_plan_overview.setLayoutMode(QtWidgets.QListView.SinglePass) - self.flight_plan_overview.setObjectName("flight_plan_overview") - self.gridLayout_13.addWidget(self.flight_plan_overview, 6, 0, 1, 1) - self.label_37 = QtWidgets.QLabel(self.scrollAreaWidgetContents) - self.label_37.setMinimumSize(QtCore.QSize(0, 20)) - self.label_37.setMaximumSize(QtCore.QSize(16777215, 20)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_37.setFont(font) - self.label_37.setObjectName("label_37") - self.gridLayout_13.addWidget(self.label_37, 7, 0, 1, 1) - self.radio_overview = QtWidgets.QListWidget(self.scrollAreaWidgetContents) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.radio_overview.sizePolicy().hasHeightForWidth()) - self.radio_overview.setSizePolicy(sizePolicy) - self.radio_overview.setMinimumSize(QtCore.QSize(0, 0)) - self.radio_overview.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.radio_overview.setToolTip("") - self.radio_overview.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.radio_overview.setAutoScroll(True) - self.radio_overview.setTextElideMode(QtCore.Qt.ElideLeft) - self.radio_overview.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerItem) - self.radio_overview.setResizeMode(QtWidgets.QListView.Adjust) - self.radio_overview.setLayoutMode(QtWidgets.QListView.SinglePass) - self.radio_overview.setObjectName("radio_overview") - self.gridLayout_13.addWidget(self.radio_overview, 8, 0, 1, 1) - self.label_38 = QtWidgets.QLabel(self.scrollAreaWidgetContents) - self.label_38.setMinimumSize(QtCore.QSize(0, 20)) - self.label_38.setMaximumSize(QtCore.QSize(16777215, 20)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_38.setFont(font) - self.label_38.setObjectName("label_38") - self.gridLayout_13.addWidget(self.label_38, 9, 0, 1, 1) - self.telemetry_overview = QtWidgets.QListWidget(self.scrollAreaWidgetContents) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.telemetry_overview.sizePolicy().hasHeightForWidth()) - self.telemetry_overview.setSizePolicy(sizePolicy) - self.telemetry_overview.setMinimumSize(QtCore.QSize(0, 0)) - self.telemetry_overview.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.telemetry_overview.setToolTip("") - self.telemetry_overview.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.telemetry_overview.setAutoScroll(True) - self.telemetry_overview.setTextElideMode(QtCore.Qt.ElideLeft) - self.telemetry_overview.setVerticalScrollMode(QtWidgets.QAbstractItemView.ScrollPerItem) - self.telemetry_overview.setResizeMode(QtWidgets.QListView.Adjust) - self.telemetry_overview.setLayoutMode(QtWidgets.QListView.SinglePass) - self.telemetry_overview.setObjectName("telemetry_overview") - self.gridLayout_13.addWidget(self.telemetry_overview, 10, 0, 1, 1) - self.scrollArea.setWidget(self.scrollAreaWidgetContents) - self.gridLayout_8.addWidget(self.scrollArea, 0, 0, 1, 1) - self.stackedWidget.addWidget(self.area) - self.area_2 = QtWidgets.QWidget() - self.area_2.setObjectName("area_2") - self.gridLayout_12 = QtWidgets.QGridLayout(self.area_2) - self.gridLayout_12.setObjectName("gridLayout_12") - self.scrollArea_2 = QtWidgets.QScrollArea(self.area_2) - self.scrollArea_2.setWidgetResizable(True) - self.scrollArea_2.setObjectName("scrollArea_2") - self.scrollAreaWidgetContents_2 = QtWidgets.QWidget() - self.scrollAreaWidgetContents_2.setGeometry(QtCore.QRect(0, 0, 151, 583)) - self.scrollAreaWidgetContents_2.setObjectName("scrollAreaWidgetContents_2") - self.gridLayout_15 = QtWidgets.QGridLayout(self.scrollAreaWidgetContents_2) - self.gridLayout_15.setObjectName("gridLayout_15") - self.label_18 = QtWidgets.QLabel(self.scrollAreaWidgetContents_2) - self.label_18.setMinimumSize(QtCore.QSize(0, 30)) - self.label_18.setMaximumSize(QtCore.QSize(16777215, 30)) - self.label_18.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.label_18.setTextFormat(QtCore.Qt.AutoText) - self.label_18.setScaledContents(False) - self.label_18.setObjectName("label_18") - self.gridLayout_15.addWidget(self.label_18, 0, 0, 1, 1) - self.label_39 = QtWidgets.QLabel(self.scrollAreaWidgetContents_2) - self.label_39.setMinimumSize(QtCore.QSize(0, 20)) - self.label_39.setMaximumSize(QtCore.QSize(16777215, 20)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_39.setFont(font) - self.label_39.setObjectName("label_39") - self.gridLayout_15.addWidget(self.label_39, 1, 0, 1, 1) - self.airframes_overview_2 = QtWidgets.QListWidget(self.scrollAreaWidgetContents_2) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.airframes_overview_2.sizePolicy().hasHeightForWidth()) - self.airframes_overview_2.setSizePolicy(sizePolicy) - self.airframes_overview_2.setMinimumSize(QtCore.QSize(0, 0)) - self.airframes_overview_2.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.airframes_overview_2.setToolTip("") - self.airframes_overview_2.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.airframes_overview_2.setTextElideMode(QtCore.Qt.ElideLeft) - self.airframes_overview_2.setObjectName("airframes_overview_2") - self.gridLayout_15.addWidget(self.airframes_overview_2, 2, 0, 1, 1) - self.label_40 = QtWidgets.QLabel(self.scrollAreaWidgetContents_2) - self.label_40.setMinimumSize(QtCore.QSize(0, 20)) - self.label_40.setMaximumSize(QtCore.QSize(16777215, 20)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_40.setFont(font) - self.label_40.setObjectName("label_40") - self.gridLayout_15.addWidget(self.label_40, 3, 0, 1, 1) - self.settings_overview_2 = QtWidgets.QListWidget(self.scrollAreaWidgetContents_2) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.settings_overview_2.sizePolicy().hasHeightForWidth()) - self.settings_overview_2.setSizePolicy(sizePolicy) - self.settings_overview_2.setMinimumSize(QtCore.QSize(0, 0)) - self.settings_overview_2.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.settings_overview_2.setToolTip("") - self.settings_overview_2.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.settings_overview_2.setTextElideMode(QtCore.Qt.ElideLeft) - self.settings_overview_2.setObjectName("settings_overview_2") - self.gridLayout_15.addWidget(self.settings_overview_2, 4, 0, 1, 1) - self.label_41 = QtWidgets.QLabel(self.scrollAreaWidgetContents_2) - self.label_41.setMinimumSize(QtCore.QSize(0, 20)) - self.label_41.setMaximumSize(QtCore.QSize(16777215, 20)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_41.setFont(font) - self.label_41.setObjectName("label_41") - self.gridLayout_15.addWidget(self.label_41, 5, 0, 1, 1) - self.flight_plan_overview_2 = QtWidgets.QListWidget(self.scrollAreaWidgetContents_2) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.flight_plan_overview_2.sizePolicy().hasHeightForWidth()) - self.flight_plan_overview_2.setSizePolicy(sizePolicy) - self.flight_plan_overview_2.setMinimumSize(QtCore.QSize(0, 0)) - self.flight_plan_overview_2.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.flight_plan_overview_2.setToolTip("") - self.flight_plan_overview_2.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.flight_plan_overview_2.setTextElideMode(QtCore.Qt.ElideLeft) - self.flight_plan_overview_2.setObjectName("flight_plan_overview_2") - self.gridLayout_15.addWidget(self.flight_plan_overview_2, 6, 0, 1, 1) - self.label_42 = QtWidgets.QLabel(self.scrollAreaWidgetContents_2) - self.label_42.setMinimumSize(QtCore.QSize(0, 20)) - self.label_42.setMaximumSize(QtCore.QSize(16777215, 20)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_42.setFont(font) - self.label_42.setObjectName("label_42") - self.gridLayout_15.addWidget(self.label_42, 7, 0, 1, 1) - self.radio_overview_2 = QtWidgets.QListWidget(self.scrollAreaWidgetContents_2) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.radio_overview_2.sizePolicy().hasHeightForWidth()) - self.radio_overview_2.setSizePolicy(sizePolicy) - self.radio_overview_2.setMinimumSize(QtCore.QSize(0, 0)) - self.radio_overview_2.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.radio_overview_2.setToolTip("") - self.radio_overview_2.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.radio_overview_2.setTextElideMode(QtCore.Qt.ElideLeft) - self.radio_overview_2.setObjectName("radio_overview_2") - self.gridLayout_15.addWidget(self.radio_overview_2, 8, 0, 1, 1) - self.label_43 = QtWidgets.QLabel(self.scrollAreaWidgetContents_2) - self.label_43.setMinimumSize(QtCore.QSize(0, 20)) - self.label_43.setMaximumSize(QtCore.QSize(16777215, 20)) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.label_43.setFont(font) - self.label_43.setObjectName("label_43") - self.gridLayout_15.addWidget(self.label_43, 9, 0, 1, 1) - self.telemetry_overview_2 = QtWidgets.QListWidget(self.scrollAreaWidgetContents_2) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.telemetry_overview_2.sizePolicy().hasHeightForWidth()) - self.telemetry_overview_2.setSizePolicy(sizePolicy) - self.telemetry_overview_2.setMinimumSize(QtCore.QSize(0, 0)) - self.telemetry_overview_2.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.telemetry_overview_2.setToolTip("") - self.telemetry_overview_2.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.telemetry_overview_2.setTextElideMode(QtCore.Qt.ElideLeft) - self.telemetry_overview_2.setObjectName("telemetry_overview_2") - self.gridLayout_15.addWidget(self.telemetry_overview_2, 10, 0, 1, 1) - self.scrollArea_2.setWidget(self.scrollAreaWidgetContents_2) - self.gridLayout_12.addWidget(self.scrollArea_2, 0, 0, 1, 1) - self.stackedWidget.addWidget(self.area_2) - self.widget = QtWidgets.QWidget() - self.widget.setObjectName("widget") - self.gridLayout_14 = QtWidgets.QGridLayout(self.widget) - self.gridLayout_14.setObjectName("gridLayout_14") - self.label_17 = QtWidgets.QLabel(self.widget) - self.label_17.setFrameShape(QtWidgets.QFrame.StyledPanel) - self.label_17.setTextFormat(QtCore.Qt.AutoText) - self.label_17.setScaledContents(False) - self.label_17.setWordWrap(False) - self.label_17.setObjectName("label_17") - self.gridLayout_14.addWidget(self.label_17, 0, 0, 1, 1) - self.label_45 = QtWidgets.QLabel(self.widget) - self.label_45.setObjectName("label_45") - self.gridLayout_14.addWidget(self.label_45, 1, 0, 1, 1) - self.session_overview_2 = QtWidgets.QComboBox(self.widget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.session_overview_2.sizePolicy().hasHeightForWidth()) - self.session_overview_2.setSizePolicy(sizePolicy) - self.session_overview_2.setObjectName("session_overview_2") - self.gridLayout_14.addWidget(self.session_overview_2, 2, 0, 1, 1) - self.label_46 = QtWidgets.QLabel(self.widget) - self.label_46.setObjectName("label_46") - self.gridLayout_14.addWidget(self.label_46, 3, 0, 1, 1) - self.programs_overview_2 = QtWidgets.QListWidget(self.widget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.programs_overview_2.sizePolicy().hasHeightForWidth()) - self.programs_overview_2.setSizePolicy(sizePolicy) - self.programs_overview_2.setMinimumSize(QtCore.QSize(0, 0)) - self.programs_overview_2.setMaximumSize(QtCore.QSize(16777215, 16777215)) - self.programs_overview_2.setObjectName("programs_overview_2") - self.gridLayout_14.addWidget(self.programs_overview_2, 4, 0, 1, 1) - self.quick_kill_2 = QtWidgets.QPushButton(self.widget) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.quick_kill_2.setFont(font) - self.quick_kill_2.setIcon(icon8) - self.quick_kill_2.setObjectName("quick_kill_2") - self.gridLayout_14.addWidget(self.quick_kill_2, 5, 0, 1, 1) - self.quick_restart_3 = QtWidgets.QPushButton(self.widget) - font = QtGui.QFont() - font.setBold(True) - font.setWeight(75) - self.quick_restart_3.setFont(font) - self.quick_restart_3.setIcon(icon7) - self.quick_restart_3.setObjectName("quick_restart_3") - self.gridLayout_14.addWidget(self.quick_restart_3, 6, 0, 1, 1) - spacerItem9 = QtWidgets.QSpacerItem(20, 94, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) - self.gridLayout_14.addItem(spacerItem9, 7, 0, 1, 1) - self.stackedWidget.addWidget(self.widget) - self.horizontalLayout.addWidget(self.stackedWidget) - self.dockWidget.setWidget(self.dockWidgetContents) - MainWindow.addDockWidget(QtCore.Qt.DockWidgetArea(2), self.dockWidget) - self.actionNew = QtWidgets.QAction(MainWindow) - self.actionNew.setEnabled(False) - self.actionNew.setObjectName("actionNew") - self.actionOpen = QtWidgets.QAction(MainWindow) - self.actionOpen.setEnabled(False) - self.actionOpen.setObjectName("actionOpen") - self.actionSave = QtWidgets.QAction(MainWindow) - self.actionSave.setEnabled(False) - self.actionSave.setObjectName("actionSave") - self.actionRemove = QtWidgets.QAction(MainWindow) - self.actionRemove.setEnabled(False) - self.actionRemove.setObjectName("actionRemove") - self.actionSetManager = QtWidgets.QAction(MainWindow) - self.actionSetManager.setObjectName("actionSetManager") - self.actionNew_2 = QtWidgets.QAction(MainWindow) - self.actionNew_2.setEnabled(False) - self.actionNew_2.setObjectName("actionNew_2") - self.actionOpen_2 = QtWidgets.QAction(MainWindow) - self.actionOpen_2.setEnabled(False) - self.actionOpen_2.setObjectName("actionOpen_2") - self.actionSave_2 = QtWidgets.QAction(MainWindow) - self.actionSave_2.setObjectName("actionSave_2") - self.actionRemove_2 = QtWidgets.QAction(MainWindow) - self.actionRemove_2.setEnabled(False) - self.actionRemove_2.setObjectName("actionRemove_2") - self.actionMode = QtWidgets.QAction(MainWindow) - self.actionMode.setEnabled(False) - self.actionMode.setObjectName("actionMode") - self.actionStandard = QtWidgets.QAction(MainWindow) - self.actionStandard.setCheckable(False) - self.actionStandard.setChecked(False) - self.actionStandard.setEnabled(False) - self.actionStandard.setIconVisibleInMenu(False) - self.actionStandard.setObjectName("actionStandard") - self.actionDeveloper = QtWidgets.QAction(MainWindow) - self.actionDeveloper.setEnabled(False) - self.actionDeveloper.setObjectName("actionDeveloper") - self.actionSettings = QtWidgets.QAction(MainWindow) - self.actionSettings.setEnabled(False) - self.actionSettings.setObjectName("actionSettings") - self.actionQuit_Paparazzi_UAV = QtWidgets.QAction(MainWindow) - self.actionQuit_Paparazzi_UAV.setObjectName("actionQuit_Paparazzi_UAV") - self.actionFull_screen = QtWidgets.QAction(MainWindow) - self.actionFull_screen.setObjectName("actionFull_screen") - self.actionTutorial = QtWidgets.QAction(MainWindow) - self.actionTutorial.setEnabled(True) - self.actionTutorial.setObjectName("actionTutorial") - self.actionAbout_Paparazzi_UAV = QtWidgets.QAction(MainWindow) - self.actionAbout_Paparazzi_UAV.setEnabled(True) - self.actionAbout_Paparazzi_UAV.setObjectName("actionAbout_Paparazzi_UAV") - self.actionNew_empty_session = QtWidgets.QAction(MainWindow) - self.actionNew_empty_session.setEnabled(False) - self.actionNew_empty_session.setObjectName("actionNew_empty_session") - self.actionOpen_3 = QtWidgets.QAction(MainWindow) - self.actionOpen_3.setEnabled(False) - self.actionOpen_3.setObjectName("actionOpen_3") - self.actionSave_3 = QtWidgets.QAction(MainWindow) - self.actionSave_3.setObjectName("actionSave_3") - self.actionRemove_3 = QtWidgets.QAction(MainWindow) - self.actionRemove_3.setEnabled(False) - self.actionRemove_3.setObjectName("actionRemove_3") - self.actionUndo = QtWidgets.QAction(MainWindow) - self.actionUndo.setEnabled(False) - self.actionUndo.setObjectName("actionUndo") - self.actionRedo = QtWidgets.QAction(MainWindow) - self.actionRedo.setEnabled(False) - self.actionRedo.setObjectName("actionRedo") - self.actionSimulator = QtWidgets.QAction(MainWindow) - self.actionSimulator.setObjectName("actionSimulator") - self.actionGCS = QtWidgets.QAction(MainWindow) - self.actionGCS.setObjectName("actionGCS") - self.actionMeteo = QtWidgets.QAction(MainWindow) - self.actionMeteo.setObjectName("actionMeteo") - self.actionServer = QtWidgets.QAction(MainWindow) - self.actionServer.setObjectName("actionServer") - self.actionMessages = QtWidgets.QAction(MainWindow) - self.actionMessages.setObjectName("actionMessages") - self.action = QtWidgets.QAction(MainWindow) - self.action.setObjectName("action") - self.actionWILL_BE_AVAILABLE_LATER = QtWidgets.QAction(MainWindow) - self.actionWILL_BE_AVAILABLE_LATER.setEnabled(False) - self.actionWILL_BE_AVAILABLE_LATER.setObjectName("actionWILL_BE_AVAILABLE_LATER") - self.actionSet_default_cache_at_current_state = QtWidgets.QAction(MainWindow) - self.actionSet_default_cache_at_current_state.setObjectName("actionSet_default_cache_at_current_state") - self.actionRestore_default_state = QtWidgets.QAction(MainWindow) - self.actionRestore_default_state.setObjectName("actionRestore_default_state") - self.actionHide_overviews = QtWidgets.QAction(MainWindow) - self.actionHide_overviews.setObjectName("actionHide_overviews") - self.menuSet.addAction(self.actionSetManager) - self.menuConfiguration.addAction(self.actionNew_2) - self.menuConfiguration.addAction(self.actionOpen_2) - self.menuConfiguration.addAction(self.actionSave_2) - self.menuConfiguration.addAction(self.actionRemove_2) - self.menuMenu.addAction(self.actionMode) - self.menuMenu.addAction(self.actionStandard) - self.menuMenu.addAction(self.actionDeveloper) - self.menuMenu.addSeparator() - self.menuMenu.addAction(self.actionSettings) - self.menuMenu.addSeparator() - self.menuMenu.addAction(self.actionQuit_Paparazzi_UAV) - self.menuView.addAction(self.actionFull_screen) - self.menuView.addAction(self.actionHide_overviews) - self.menuHelp.addAction(self.actionTutorial) - self.menuHelp.addAction(self.actionAbout_Paparazzi_UAV) - self.menuSession.addAction(self.actionNew_empty_session) - self.menuSession.addAction(self.actionOpen_3) - self.menuSession.addAction(self.actionSave_3) - self.menuSession.addAction(self.actionRemove_3) - self.menubar.addAction(self.menuMenu.menuAction()) - self.menubar.addAction(self.menuSet.menuAction()) - self.menubar.addAction(self.menuConfiguration.menuAction()) - self.menubar.addAction(self.menuSession.menuAction()) - self.menubar.addAction(self.menuView.menuAction()) - self.menubar.addAction(self.menuHelp.menuAction()) - - self.retranslateUi(MainWindow) - self.main_tab.setCurrentIndex(2) - self.stackedWidget.setCurrentIndex(0) - self.main_tab.currentChanged['int'].connect(self.stackedWidget.setCurrentIndex) - QtCore.QMetaObject.connectSlotsByName(MainWindow) - - def retranslateUi(self, MainWindow): - _translate = QtCore.QCoreApplication.translate - MainWindow.setWindowTitle(_translate("MainWindow", "Paparazzi Center")) - self.label.setText(_translate("MainWindow", "Set :")) - self.current_configuration.setToolTip(_translate("MainWindow", "Current configuration")) - self.current_color.setToolTip(_translate("MainWindow", "Current configuration color")) - self.label_2.setText(_translate("MainWindow", "Configuration :")) - self.label_3.setText(_translate("MainWindow", "ID :")) - self.current_id.setToolTip(_translate("MainWindow", "Current configuration ID")) - self.label_27.setText(_translate("MainWindow", "Color :")) - self.current_set.setToolTip(_translate("MainWindow", "Current set of configurations")) - self.search_item.setToolTip(_translate("MainWindow", "Search an XML")) - self.search_item.setText(_translate("MainWindow", "COMING SOON")) - self.all_items_tree.setToolTip(_translate("MainWindow", "Select an XML file")) - self.all_items_tree.headerItem().setText(0, _translate("MainWindow", "COMING SOON")) - self.quick_target.setToolTip(_translate("MainWindow", "Select a target to build quickly")) - self.label_19.setText(_translate("MainWindow", "Quick build :")) - self.quick_build.setToolTip(_translate("MainWindow", "Clean & build quickly the current configuration")) - self.quick_build.setText(_translate("MainWindow", "Clean && build")) - self.remove_item.setToolTip(_translate("MainWindow", "Remove the XML file selected from the current configuration")) - self.edit.setToolTip(_translate("MainWindow", "Edit the selected XML file")) - self.add_item.setToolTip(_translate("MainWindow", "Add the selected XML file to the current configuration")) - self.scrollArea_3.setToolTip(_translate("MainWindow", "Current configuration")) - self.current_flight_plan.setToolTip(_translate("MainWindow", "Current flight plan (click to edit by GUI)")) - self.current_airframes.setToolTip(_translate("MainWindow", "Current airframes")) - self.current_telemetry.setToolTip(_translate("MainWindow", "Current telemetry")) - self.current_flight_plan_label.setText(_translate("MainWindow", "Flight plan :")) - self.current_airframes_label.setText(_translate("MainWindow", "Airframes :")) - self.current_settings.setToolTip(_translate("MainWindow", "Current settings")) - self.current_radio_label.setText(_translate("MainWindow", "Radio :")) - self.select_kml.setToolTip(_translate("MainWindow", "Change the flight plan by KML to XML tool")) - self.select_kml.setText(_translate("MainWindow", "Select KML (Maps)")) - self.current_radio.setToolTip(_translate("MainWindow", "Current radio")) - self.open_gui.setToolTip(_translate("MainWindow", "Change the flight plan by GCS")) - self.open_gui.setText(_translate("MainWindow", "Open a GUI (GCS)")) - self.current_settings_label.setText(_translate("MainWindow", "Settings :")) - self.current_telemetry_label.setText(_translate("MainWindow", "Telemetry :")) - self.main_tab.setTabText(self.main_tab.indexOf(self.equipment_tab), _translate("MainWindow", "Equipment")) - self.main_tab.setTabToolTip(self.main_tab.indexOf(self.equipment_tab), _translate("MainWindow", "Tab to manage the equipments of the current configuration")) - self.build_result.setToolTip(_translate("MainWindow", "Clean & build result")) - self.info_nb.setToolTip(_translate("MainWindow", "Info found during build")) - self.flash_result.setToolTip(_translate("MainWindow", "Flash result")) - self.label_25.setText(_translate("MainWindow", "Flash")) - self.label_10.setText(_translate("MainWindow", "Errors :")) - self.label_26.setText(_translate("MainWindow", "Target :")) - self.label_11.setText(_translate("MainWindow", "Warnings :")) - self.label_13.setText(_translate("MainWindow", "Result :")) - self.warnings_nb.setToolTip(_translate("MainWindow", "Warnings found during build")) - self.label_23.setText(_translate("MainWindow", "Build")) - self.label_12.setText(_translate("MainWindow", "Device :")) - self.label_14.setText(_translate("MainWindow", "Info :")) - self.target.setToolTip(_translate("MainWindow", "Current target")) - self.clean.setToolTip(_translate("MainWindow", "Clean the current configuration")) - self.clean.setText(_translate("MainWindow", "Clean")) - self.errors_nb.setToolTip(_translate("MainWindow", "Errors found during build")) - self.device.setToolTip(_translate("MainWindow", "Current device")) - self.build.setToolTip(_translate("MainWindow", "Build the current configuration")) - self.build.setText(_translate("MainWindow", "Build")) - self.show_console.setToolTip(_translate("MainWindow", "Switch to the console tab")) - self.show_console.setText(_translate("MainWindow", "Show console")) - self.upload.setToolTip(_translate("MainWindow", "Flash the current device")) - self.upload.setText(_translate("MainWindow", "Upload")) - self.label_9.setText(_translate("MainWindow", "Result :")) - self.main_tab.setTabText(self.main_tab.indexOf(self.build_flash_tab), _translate("MainWindow", "Build / Flash")) - self.main_tab.setTabToolTip(self.main_tab.indexOf(self.build_flash_tab), _translate("MainWindow", "Tab to build and flash the current configuration")) - self.label_7.setText(_translate("MainWindow", "Options :")) - self.programs.setToolTip(_translate("MainWindow", "Programs running (green) and stopped (red)")) - self.label_8.setText(_translate("MainWindow", "Programs :")) - self.start_all_button.setToolTip(_translate("MainWindow", "Kill & restart all programs")) - self.start_all_button.setText(_translate("MainWindow", "Start all")) - self.play_stop_program.setToolTip(_translate("MainWindow", "Start / stop the selected program")) - self.play_stop_program.setText(_translate("MainWindow", "Start")) - self.options.setToolTip(_translate("MainWindow", "Options of the selected program")) - self.remove_program.setToolTip(_translate("MainWindow", "Remove a programs from the session")) - self.session.setToolTip(_translate("MainWindow", "Current session")) - self.kill_all_button.setToolTip(_translate("MainWindow", "Kill all running programs")) - self.kill_all_button.setText(_translate("MainWindow", "Kill all")) - self.label_4.setText(_translate("MainWindow", "Session :")) - self.add_program.setToolTip(_translate("MainWindow", "Add a programs to the session")) - self.remove_option.setToolTip(_translate("MainWindow", "Remove the selected option")) - self.add_option.setToolTip(_translate("MainWindow", "Add an option to the selected program")) - self.main_tab.setTabText(self.main_tab.indexOf(self.sessions_tab), _translate("MainWindow", "Run session")) - self.main_tab.setTabToolTip(self.main_tab.indexOf(self.sessions_tab), _translate("MainWindow", "Tab to launch and customize the current session")) - self.console.setToolTip(_translate("MainWindow", "Console to display the logs")) - self.console.setHtml(_translate("MainWindow", "\n" -"\n" -"


")) - self.label_24.setText(_translate("MainWindow", "Logs")) - self.important.setText(_translate("MainWindow", "Important only")) - self.custom.setText(_translate("MainWindow", "Customized")) - self.all.setText(_translate("MainWindow", "All")) - self.clean_console.setToolTip(_translate("MainWindow", "Clean the console (all logs will be deleted !)")) - self.clean_console.setText(_translate("MainWindow", "Clean console")) - self.display_info.setText(_translate("MainWindow", "Info")) - self.display_warnings.setText(_translate("MainWindow", "Warnings")) - self.display_errors.setText(_translate("MainWindow", "Errors")) - self.display_default.setText(_translate("MainWindow", "Default (no flag)")) - self.main_tab.setTabText(self.main_tab.indexOf(self.console_tab), _translate("MainWindow", "Console")) - self.main_tab.setTabToolTip(self.main_tab.indexOf(self.console_tab), _translate("MainWindow", "Tab where informations are displayed in a real customizable console")) - self.label_20.setText(_translate("MainWindow", "HOME = ")) - self.open_home_terminal.setToolTip(_translate("MainWindow", "Home directory of Paparazzi UAV (click to open a terminal here)")) - self.run_version.setToolTip(_translate("MainWindow", "Current version of Paparazzi UAV")) - self.label_29.setText(_translate("MainWindow", "BUILD_VERSION = ")) - self.build_version.setToolTip(_translate("MainWindow", "Current version of Paparazzi UAV")) - self.label_22.setText(_translate("MainWindow", "RUN_VERSION = ")) - self.switch_mode.setToolTip(_translate("MainWindow", "Current mode (click to switch the mode)")) - self.label_21.setText(_translate("MainWindow", "MODE = ")) - self.menuSet.setTitle(_translate("MainWindow", "Set")) - self.menuConfiguration.setTitle(_translate("MainWindow", "Configuration")) - self.menuMenu.setTitle(_translate("MainWindow", "Menu")) - self.menuView.setTitle(_translate("MainWindow", "View")) - self.menuHelp.setTitle(_translate("MainWindow", "Help")) - self.menuSession.setTitle(_translate("MainWindow", "Session")) - self.quick_restart.setToolTip(_translate("MainWindow", "Kill & restart all programs")) - self.quick_restart.setText(_translate("MainWindow", "Start all")) - self.label_33.setText(_translate("MainWindow", "Processus :")) - self.programs_overview_1.setToolTip(_translate("MainWindow", "Programs running (green) and stopped (red)")) - self.label_32.setText(_translate("MainWindow", "Session :")) - self.session_overview_1.setToolTip(_translate("MainWindow", "Current session")) - self.label_6.setText(_translate("MainWindow", "Session overview")) - self.quick_kill.setToolTip(_translate("MainWindow", "Kill all running programs")) - self.quick_kill.setText(_translate("MainWindow", "Kill all")) - self.label_5.setText(_translate("MainWindow", "Settings overview")) - self.label_35.setText(_translate("MainWindow", "Airframes")) - self.label_34.setText(_translate("MainWindow", "Settings")) - self.label_36.setText(_translate("MainWindow", "Flight plan")) - self.label_37.setText(_translate("MainWindow", "Radio")) - self.label_38.setText(_translate("MainWindow", "Telemetry")) - self.label_18.setText(_translate("MainWindow", "Settings overview")) - self.label_39.setText(_translate("MainWindow", "Airframes")) - self.label_40.setText(_translate("MainWindow", "Settings")) - self.label_41.setText(_translate("MainWindow", "Flight plan")) - self.label_42.setText(_translate("MainWindow", "Radio")) - self.label_43.setText(_translate("MainWindow", "Telemetry")) - self.label_17.setText(_translate("MainWindow", "Session overview")) - self.label_45.setText(_translate("MainWindow", "Session :")) - self.session_overview_2.setToolTip(_translate("MainWindow", "Current session")) - self.label_46.setText(_translate("MainWindow", "Processus :")) - self.programs_overview_2.setToolTip(_translate("MainWindow", "Programs running (green) and stopped (red)")) - self.quick_kill_2.setToolTip(_translate("MainWindow", "Kill all running programs")) - self.quick_kill_2.setText(_translate("MainWindow", "Kill all")) - self.quick_restart_3.setToolTip(_translate("MainWindow", "Kill & restart all programs")) - self.quick_restart_3.setText(_translate("MainWindow", "Start all")) - self.actionNew.setText(_translate("MainWindow", "New empty set")) - self.actionNew.setShortcut(_translate("MainWindow", "Ctrl+Shift+N")) - self.actionOpen.setText(_translate("MainWindow", "Save set as...")) - self.actionSave.setText(_translate("MainWindow", "Save")) - self.actionRemove.setText(_translate("MainWindow", "Remove")) - self.actionSetManager.setText(_translate("MainWindow", "Set manager... (COMING SOON)")) - self.actionSetManager.setShortcut(_translate("MainWindow", "Ctrl+Shift+M")) - self.actionNew_2.setText(_translate("MainWindow", "New empty configuration")) - self.actionNew_2.setShortcut(_translate("MainWindow", "Ctrl+N")) - self.actionOpen_2.setText(_translate("MainWindow", "Save configuration as...")) - self.actionOpen_2.setShortcut(_translate("MainWindow", "Ctrl+S")) - self.actionSave_2.setText(_translate("MainWindow", "Save")) - self.actionRemove_2.setText(_translate("MainWindow", "Remove")) - self.actionMode.setText(_translate("MainWindow", "Active mode :")) - self.actionStandard.setText(_translate("MainWindow", "Standard")) - self.actionStandard.setToolTip(_translate("MainWindow", "Switch to standard user mode")) - self.actionDeveloper.setText(_translate("MainWindow", "Developer")) - self.actionDeveloper.setToolTip(_translate("MainWindow", "Switch to developer mode")) - self.actionSettings.setText(_translate("MainWindow", "Settings...")) - self.actionSettings.setToolTip(_translate("MainWindow", "Change global settings of the Paparazzi Center")) - self.actionQuit_Paparazzi_UAV.setText(_translate("MainWindow", "Quit Paparazzi UAV")) - self.actionQuit_Paparazzi_UAV.setShortcut(_translate("MainWindow", "Ctrl+Q")) - self.actionFull_screen.setText(_translate("MainWindow", "Full screen")) - self.actionFull_screen.setShortcut(_translate("MainWindow", "F11")) - self.actionTutorial.setText(_translate("MainWindow", "Tutorials...")) - self.actionTutorial.setShortcut(_translate("MainWindow", "Ctrl+H")) - self.actionAbout_Paparazzi_UAV.setText(_translate("MainWindow", "Credits...")) - self.actionNew_empty_session.setText(_translate("MainWindow", "New empty session")) - self.actionNew_empty_session.setShortcut(_translate("MainWindow", "Ctrl+Shift+N, Ctrl+Shift+N")) - self.actionOpen_3.setText(_translate("MainWindow", "Save session as...")) - self.actionOpen_3.setShortcut(_translate("MainWindow", "Ctrl+Shift+S")) - self.actionSave_3.setText(_translate("MainWindow", "Save")) - self.actionRemove_3.setText(_translate("MainWindow", "Remove")) - self.actionUndo.setText(_translate("MainWindow", "Undo")) - self.actionUndo.setToolTip(_translate("MainWindow", "Undo the last action")) - self.actionUndo.setShortcut(_translate("MainWindow", "Ctrl+Z")) - self.actionRedo.setText(_translate("MainWindow", "Redo")) - self.actionRedo.setToolTip(_translate("MainWindow", "Redo the last action")) - self.actionRedo.setShortcut(_translate("MainWindow", "Ctrl+Y")) - self.actionSimulator.setText(_translate("MainWindow", "Simulator")) - self.actionGCS.setText(_translate("MainWindow", "GCS")) - self.actionMeteo.setText(_translate("MainWindow", "Meteo")) - self.actionServer.setText(_translate("MainWindow", "Server")) - self.actionMessages.setText(_translate("MainWindow", "Messages")) - self.action.setText(_translate("MainWindow", "...")) - self.actionWILL_BE_AVAILABLE_LATER.setText(_translate("MainWindow", "WILL BE AVAILABLE LATER :")) - self.actionSet_default_cache_at_current_state.setText(_translate("MainWindow", "Set default app state to current")) - self.actionRestore_default_state.setText(_translate("MainWindow", "Restore default app state")) - self.actionHide_overviews.setText(_translate("MainWindow", "Hide overviews")) - -from tools_menu import ToolsMenu diff --git a/sw/supervision/python/ui/main_window.ui b/sw/supervision/python/ui/main_window.ui deleted file mode 100644 index 066dfdc126..0000000000 --- a/sw/supervision/python/ui/main_window.ui +++ /dev/null @@ -1,3868 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 833 - 568 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Paparazzi Center - - - - - - - - 0 - 0 - - - - - 0 - 40 - - - - - 16777215 - 40 - - - - false - - - - - - QFrame::StyledPanel - - - QFrame::Plain - - - - - - - - - Set : - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - Current configuration - - - - - - - true - - - - 0 - 0 - - - - - 30 - 0 - - - - - 40 - 16777215 - - - - false - - - Qt::NoFocus - - - Current configuration color - - - true - - - - - - QFrame::Box - - - 1 - - - - - - Qt::AlignCenter - - - - - - - - - - Configuration : - - - - - - - - - - ID : - - - - - - - true - - - - 0 - 0 - - - - - 30 - 0 - - - - - 40 - 16777215 - - - - - 75 - true - - - - false - - - Qt::NoFocus - - - Current configuration ID - - - true - - - - - - QFrame::Box - - - 1 - - - - - - Qt::AlignCenter - - - - - - - - - - Color : - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - Current set of configurations - - - - - - - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - - - Qt::LeftToRight - - - QTabWidget::North - - - QTabWidget::Triangular - - - 2 - - - Qt::ElideNone - - - true - - - false - - - false - - - - Equipment - - - Tab to manage the equipments of the current configuration - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - false - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Search an XML - - - COMING SOON - - - - - - - false - - - Select an XML file - - - - COMING SOON - - - - - - - - - 0 - 40 - - - - - 16777215 - 40 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - Select a target to build quickly - - - - - - - - 16777215 - 20 - - - - Quick build : - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - Clean & build quickly the current configuration - - - Qt::LeftToRight - - - Clean && build - - - - icons/system-run.pngicons/system-run.png - - - - - - - - - - true - - - - 0 - 0 - - - - - 50 - 50 - - - - - 50 - 50 - - - - Remove the XML file selected from the current configuration - - - - - - - icons/list-remove.svgicons/list-remove.svg - - - false - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 50 - 50 - - - - - 50 - 50 - - - - Edit the selected XML file - - - - - - - icons/accessories-text-editor.svgicons/accessories-text-editor.svg - - - - 24 - 24 - - - - - - - - true - - - - 0 - 0 - - - - - 50 - 50 - - - - - 50 - 50 - - - - Add the selected XML file to the current configuration - - - - - - - icons/list-add.svgicons/list-add.svg - - - false - - - - - - - Current configuration - - - true - - - - - 0 - 0 - 162 - 607 - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Current flight plan (click to edit by GUI) - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Current airframes - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Current telemetry - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - Flight plan : - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - Airframes : - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Current settings - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - Radio : - - - - - - - false - - - - 0 - 24 - - - - Change the flight plan by KML to XML tool - - - Select KML (Maps) - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Current radio - - - - - - - false - - - - 0 - 24 - - - - Change the flight plan by GCS - - - Open a GUI (GCS) - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - Settings : - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - Telemetry : - - - - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - - - QFrame::NoFrame - - - - - - icons/search_field.png - - - - - - - - Build / Flash - - - Tab to build and flash the current configuration - - - - - - - 20 - 20 - - - - - 20 - 20 - - - - - - - icons/gtk-info.svg - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - Clean & build result - - - QFrame::StyledPanel - - - - - - - - - - - 0 - 0 - - - - - 30 - 20 - - - - - 30 - 20 - - - - - 75 - true - - - - Info found during build - - - border:2px solid #00ff00; - - - QFrame::StyledPanel - - - - - - - - - - - 0 - 0 - - - - - 30 - 0 - - - - - 16777215 - 16777215 - - - - - - - QFrame::NoFrame - - - - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - Flash result - - - QFrame::StyledPanel - - - - - - - - - - - 14 - 75 - true - - - - Flash - - - - - - - Errors : - - - - - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - - 60 - 16777215 - - - - Target : - - - - - - - Warnings : - - - - - - - - 0 - 0 - - - - - 60 - 16777215 - - - - Result : - - - - - - - - 0 - 0 - - - - - 30 - 20 - - - - - 30 - 20 - - - - - 75 - true - - - - Warnings found during build - - - border:2px solid #ffaa00; - - - QFrame::StyledPanel - - - - - - - - - - - 14 - 75 - true - - - - Build - - - - - - - - 0 - 0 - - - - - 60 - 16777215 - - - - Device : - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Info : - - - - - - - - 20 - 20 - - - - - 20 - 20 - - - - - - - icons/dialog-error.svg - - - - - - - - 0 - 30 - - - - - 16777215 - 30 - - - - Current target - - - - - - - - 20 - 20 - - - - - 20 - 20 - - - - - - - icons/dialog-warning.png - - - - - - - - 130 - 30 - - - - - 130 - 30 - - - - Clean the current configuration - - - Qt::LeftToRight - - - Clean - - - - icons/edit-clear.svgicons/edit-clear.svg - - - - - - - Qt::Horizontal - - - - - - - - 0 - 0 - - - - - 30 - 20 - - - - - 30 - 20 - - - - - 75 - true - - - - Errors found during build - - - false - - - border:2px solid #ff0000; - - - QFrame::StyledPanel - - - - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - - 16777215 - 30 - - - - Current device - - - - - - - - 130 - 30 - - - - - 130 - 30 - - - - Build the current configuration - - - Qt::LeftToRight - - - Build - - - - icons/system-run.pngicons/system-run.png - - - - - - - - 0 - 30 - - - - - 16777215 - 20 - - - - Switch to the console tab - - - Qt::LeftToRight - - - Show console - - - - icons/utilities-terminal.svgicons/utilities-terminal.svg - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 30 - 16777215 - - - - - - - QFrame::NoFrame - - - - - - - - - - true - - - - 130 - 30 - - - - - 130 - 30 - - - - Flash the current device - - - Upload - - - - icons/go-up.svgicons/go-up.svg - - - - - - - - 0 - 30 - - - - - 60 - 16777215 - - - - Result : - - - - - - - - Run session - - - Tab to launch and customize the current session - - - - - - Options : - - - - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Programs running (green) and stopped (red) - - - Qt::LeftToRight - - - QAbstractItemView::SelectRows - - - - 10 - 10 - - - - - - - - Programs : - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 0 - 0 - - - - - 0 - 50 - - - - - 16777215 - 50 - - - - - 75 - false - true - false - false - true - - - - Kill & restart all programs - - - Start all - - - - icons/media-playback-start.svgicons/media-playback-start.svg - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 0 - 0 - - - - - 0 - 50 - - - - - 16777215 - 50 - - - - Start / stop the selected program - - - Start - - - - icons/media-playback-start.svgicons/media-playback-start.svg - - - false - - - - - - - - 16777215 - 16777215 - - - - Options of the selected program - - - - - - - - 0 - 0 - - - - - 30 - 30 - - - - - 30 - 30 - - - - Remove a programs from the session - - - - - - - icons/list-remove.svgicons/list-remove.svg - - - false - - - - - - - - 0 - 0 - - - - Current session - - - - - - - - 0 - 0 - - - - - 0 - 50 - - - - - 16777215 - 50 - - - - - 75 - false - true - false - false - true - - - - Kill all running programs - - - Qt::LeftToRight - - - Kill all - - - - icons/process-stop.svgicons/process-stop.svg - - - - - - - Session : - - - - - - - false - - - - 0 - 0 - - - - - 30 - 30 - - - - - 30 - 30 - - - - Add a programs to the session - - - - - - - icons/list-add.svgicons/list-add.svg - - - false - - - - - - - - 0 - 0 - - - - - 30 - 30 - - - - - 30 - 30 - - - - Remove the selected option - - - - - - - icons/list-remove.svgicons/list-remove.svg - - - false - - - - - - - true - - - - 0 - 0 - - - - - 30 - 30 - - - - - 30 - 30 - - - - Add an option to the selected program - - - - - - - icons/list-add.svgicons/list-add.svg - - - false - - - - - - - - 0 - 0 - - - - - 200 - 140 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - Console - - - Tab where informations are displayed in a real customizable console - - - - - - Qt::Horizontal - - - - - - - true - - - - Ubuntu - - - - Console to display the logs - - - Qt::LeftToRight - - - Qt::ScrollBarAsNeeded - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - - - - - - 14 - 75 - true - - - - Logs - - - - - - - - - - Important only - - - false - - - - - - - - - - Customized - - - true - - - - - - - - - - All - - - false - - - - - - - Clean the console (all logs will be deleted !) - - - Clean console - - - - icons/edit-clear.svgicons/edit-clear.svg - - - - - - - - - - 0 - 0 - - - - Info - - - - icons/gtk-info.svgicons/gtk-info.svg - - - - - - - - - - - - 0 - 0 - - - - Warnings - - - - icons/dialog-warning.pngicons/dialog-warning.png - - - false - - - - - - - - - Qt::Vertical - - - - 20 - 261 - - - - - - - - Qt::Horizontal - - - - - - - - - - 0 - 0 - - - - Errors - - - - icons/dialog-error.svgicons/dialog-error.svg - - - false - - - - - - - - - Qt::Horizontal - - - - - - - - - - 0 - 0 - - - - Default (no flag) - - - - - - - - - - - - - - 0 - 0 - - - - - 16777215 - 20 - - - - QFrame::NoFrame - - - QFrame::Raised - - - 0 - - - - 0 - - - 0 - - - 0 - - - - - Qt::Vertical - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - HOME = - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - Home directory of Paparazzi UAV (click to open a terminal here) - - - - - - false - - - false - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - Current version of Paparazzi UAV - - - QFrame::NoFrame - - - - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - BUILD_VERSION = - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - Current version of Paparazzi UAV - - - QFrame::NoFrame - - - - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - RUN_VERSION = - - - - - - - false - - - - 0 - 20 - - - - - 16777215 - 20 - - - - Current mode (click to switch the mode) - - - - - - false - - - - - - - Qt::Vertical - - - - - - - Qt::Vertical - - - - - - - - 0 - 0 - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - MODE = - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 0 - 0 - 833 - 25 - - - - - Set - - - - - - Configuration - - - - - - - - - Menu - - - - - - - - - - - - View - - - - - - - Help - - - - - - - Session - - - - - - - - - - - - - - - - - 2 - - - - - - - true - - - - 0 - 0 - - - - - 200 - 0 - - - - - 200 - 16777215 - - - - - - - QFrame::StyledPanel - - - QFrame::Plain - - - 0 - - - - - - - true - - - - 75 - false - true - false - false - true - - - - Kill & restart all programs - - - Start all - - - - icons/media-playback-start.svgicons/media-playback-start.svg - - - - - - - Processus : - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Programs running (green) and stopped (red) - - - - - - - Session : - - - - - - - - 0 - 0 - - - - Current session - - - - - - - QFrame::StyledPanel - - - Session overview - - - Qt::AutoText - - - false - - - false - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - true - - - - 75 - false - true - false - false - true - - - - Kill all running programs - - - Kill all - - - - icons/process-stop.svgicons/process-stop.svg - - - - - - - - - - - true - - - - - 0 - 0 - 151 - 583 - - - - - - - - 0 - 30 - - - - - 16777215 - 30 - - - - QFrame::StyledPanel - - - Settings overview - - - Qt::AutoText - - - false - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - - 75 - true - - - - Airframes - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - - - QFrame::StyledPanel - - - true - - - Qt::ElideLeft - - - QAbstractItemView::ScrollPerItem - - - QListView::Adjust - - - QListView::SinglePass - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - - 75 - true - - - - Settings - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - - - QFrame::StyledPanel - - - true - - - Qt::ElideLeft - - - QAbstractItemView::ScrollPerItem - - - QListView::Adjust - - - QListView::SinglePass - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - - 75 - true - - - - Flight plan - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - - - QFrame::StyledPanel - - - true - - - Qt::ElideLeft - - - QAbstractItemView::ScrollPerItem - - - QListView::Adjust - - - QListView::SinglePass - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - - 75 - true - - - - Radio - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - - - QFrame::StyledPanel - - - true - - - Qt::ElideLeft - - - QAbstractItemView::ScrollPerItem - - - QListView::Adjust - - - QListView::SinglePass - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - - 75 - true - - - - Telemetry - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - - - QFrame::StyledPanel - - - true - - - Qt::ElideLeft - - - QAbstractItemView::ScrollPerItem - - - QListView::Adjust - - - QListView::SinglePass - - - - - - - - - - - - - - - true - - - - - 0 - 0 - 151 - 583 - - - - - - - - 0 - 30 - - - - - 16777215 - 30 - - - - QFrame::StyledPanel - - - Settings overview - - - Qt::AutoText - - - false - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - - 75 - true - - - - Airframes - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - - - QFrame::StyledPanel - - - Qt::ElideLeft - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - - 75 - true - - - - Settings - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - - - QFrame::StyledPanel - - - Qt::ElideLeft - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - - 75 - true - - - - Flight plan - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - - - QFrame::StyledPanel - - - Qt::ElideLeft - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - - 75 - true - - - - Radio - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - - - QFrame::StyledPanel - - - Qt::ElideLeft - - - - - - - - 0 - 20 - - - - - 16777215 - 20 - - - - - 75 - true - - - - Telemetry - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - - - QFrame::StyledPanel - - - Qt::ElideLeft - - - - - - - - - - - - - - - QFrame::StyledPanel - - - Session overview - - - Qt::AutoText - - - false - - - false - - - - - - - Session : - - - - - - - - 0 - 0 - - - - Current session - - - - - - - Processus : - - - - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Programs running (green) and stopped (red) - - - - - - - - 75 - true - - - - Kill all running programs - - - Kill all - - - - icons/process-stop.svgicons/process-stop.svg - - - - - - - - 75 - true - - - - Kill & restart all programs - - - Start all - - - - icons/media-playback-start.svgicons/media-playback-start.svg - - - - - - - Qt::Vertical - - - - 20 - 94 - - - - - - - - - - - - - - false - - - New empty set - - - Ctrl+Shift+N - - - - - false - - - Save set as... - - - - - false - - - Save - - - - - false - - - Remove - - - - - Set manager... (COMING SOON) - - - Ctrl+Shift+M - - - - - false - - - New empty configuration - - - Ctrl+N - - - - - false - - - Save configuration as... - - - Ctrl+S - - - - - Save - - - - - false - - - Remove - - - - - false - - - Active mode : - - - - - false - - - false - - - false - - - Standard - - - Switch to standard user mode - - - false - - - - - false - - - Developer - - - Switch to developer mode - - - - - false - - - Settings... - - - Change global settings of the Paparazzi Center - - - - - Quit Paparazzi UAV - - - Ctrl+Q - - - - - Full screen - - - F11 - - - - - true - - - Tutorials... - - - Ctrl+H - - - - - true - - - Credits... - - - - - false - - - New empty session - - - Ctrl+Shift+N, Ctrl+Shift+N - - - - - false - - - Save session as... - - - Ctrl+Shift+S - - - - - Save - - - - - false - - - Remove - - - - - false - - - Undo - - - Undo the last action - - - Ctrl+Z - - - - - false - - - Redo - - - Redo the last action - - - Ctrl+Y - - - - - Simulator - - - - - GCS - - - - - Meteo - - - - - Server - - - - - Messages - - - - - ... - - - - - false - - - WILL BE AVAILABLE LATER : - - - - - Set default app state to current - - - - - Restore default app state - - - - - Hide overviews - - - - - - ToolsMenu - QFrame -
tools_menu.h
- 1 -
-
- - - - main_tab - currentChanged(int) - stackedWidget - setCurrentIndex(int) - - - 130 - 88 - - - 690 - 126 - - - - -
diff --git a/sw/supervision/python/ui/new_ac_dialog.ui b/sw/supervision/python/ui/new_ac_dialog.ui new file mode 100644 index 0000000000..013d924f74 --- /dev/null +++ b/sw/supervision/python/ui/new_ac_dialog.ui @@ -0,0 +1,62 @@ + + + Dialog + + + + 0 + 0 + 187 + 106 + + + + Dialog + + + + + + Name + + + + + + + + + + + + + + ID + + + + + + + 1 + + + 255 + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + diff --git a/sw/supervision/python/ui/operation_panel.ui b/sw/supervision/python/ui/operation_panel.ui new file mode 100644 index 0000000000..1d2cac67d1 --- /dev/null +++ b/sw/supervision/python/ui/operation_panel.ui @@ -0,0 +1,44 @@ + + + OperationPanel + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + Qt::Vertical + + + + + + + + + + ConsoleWidget + QWidget +
console_widget.h
+ 1 +
+ + SessionWidget + QWidget +
session_widget.h
+ 1 +
+
+ + +
diff --git a/sw/supervision/python/ui/popup.py b/sw/supervision/python/ui/popup.py deleted file mode 100644 index 66e119393a..0000000000 --- a/sw/supervision/python/ui/popup.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'ui/popup.ui' -# -# Created: Mon Jun 20 16:13:37 2016 -# by: PyQt5 UI code generator 5.2.1 -# -# WARNING! All changes made in this file will be lost! - -from PyQt5 import QtCore, QtGui, QtWidgets - -class Ui_Dialog(object): - def setupUi(self, Dialog): - Dialog.setObjectName("Dialog") - Dialog.resize(500, 350) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(Dialog.sizePolicy().hasHeightForWidth()) - Dialog.setSizePolicy(sizePolicy) - self.gridLayout = QtWidgets.QGridLayout(Dialog) - self.gridLayout.setObjectName("gridLayout") - self.textBrowser = QtWidgets.QTextBrowser(Dialog) - self.textBrowser.setFrameShape(QtWidgets.QFrame.NoFrame) - self.textBrowser.setObjectName("textBrowser") - self.gridLayout.addWidget(self.textBrowser, 0, 0, 1, 1) - self.buttonBox = QtWidgets.QDialogButtonBox(Dialog) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.buttonBox.sizePolicy().hasHeightForWidth()) - self.buttonBox.setSizePolicy(sizePolicy) - self.buttonBox.setMaximumSize(QtCore.QSize(16777215, 30)) - self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.NoButton) - self.buttonBox.setObjectName("buttonBox") - self.gridLayout.addWidget(self.buttonBox, 3, 0, 1, 1) - - self.retranslateUi(Dialog) - self.buttonBox.rejected.connect(Dialog.reject) - self.buttonBox.accepted.connect(Dialog.accept) - QtCore.QMetaObject.connectSlotsByName(Dialog) - - def retranslateUi(self, Dialog): - _translate = QtCore.QCoreApplication.translate - Dialog.setWindowTitle(_translate("Dialog", "Dialog")) - diff --git a/sw/supervision/python/ui/popup.ui b/sw/supervision/python/ui/popup.ui deleted file mode 100644 index 7b515cc852..0000000000 --- a/sw/supervision/python/ui/popup.ui +++ /dev/null @@ -1,86 +0,0 @@ - - - Dialog - - - - 0 - 0 - 500 - 350 - - - - - 0 - 0 - - - - Dialog - - - - - - QFrame::NoFrame - - - - - - - - 0 - 0 - - - - - 16777215 - 30 - - - - QDialogButtonBox::NoButton - - - - - - - - - buttonBox - rejected() - Dialog - reject() - - - 217 - 181 - - - 217 - 211 - - - - - buttonBox - accepted() - Dialog - accept() - - - 97 - 174 - - - 99 - 203 - - - - - diff --git a/sw/supervision/python/ui/program.ui b/sw/supervision/python/ui/program.ui new file mode 100644 index 0000000000..c3d56ac92a --- /dev/null +++ b/sw/supervision/python/ui/program.ui @@ -0,0 +1,66 @@ + + + Program + + + + 0 + 0 + 374 + 25 + + + + Form + + + + 0 + + + 0 + + + + + ... + + + + + + + + + + Qt::Vertical + + + + + + + ... + + + + .. + + + + + + + ... + + + + .. + + + + + + + + diff --git a/sw/supervision/python/ui/session.ui b/sw/supervision/python/ui/session.ui new file mode 100644 index 0000000000..1622ff14b9 --- /dev/null +++ b/sw/supervision/python/ui/session.ui @@ -0,0 +1,263 @@ + + + Session + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + + Session + + + + + + + + + + + + Start Session + + + ... + + + + .. + + + + + + + Qt::ActionsContextMenu + + + ... + + + + .. + + + + + + + + + + + + + + Programs + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Add Tool + + + Add tool + + + + .. + + + Qt::ToolButtonTextBesideIcon + + + false + + + Qt::NoArrow + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + + + + Start All + + + ... + + + + .. + + + + + + + Stop All + + + ... + + + + .. + + + + + + + Remove All + + + ... + + + + .. + + + + + + + + + true + + + + + 0 + 0 + 380 + 176 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + .. + + + Save session + + + + + + .. + + + Save as... + + + Save session as... + + + + + + .. + + + Rename session + + + + + + .. + + + Remove session + + + + + + + menu_button + clicked() + menu_button + showMenu() + + + 377 + 45 + + + 377 + 45 + + + + + diff --git a/sw/supervision/python/ui/set_manager.py b/sw/supervision/python/ui/set_manager.py deleted file mode 100644 index ddbe24e1b7..0000000000 --- a/sw/supervision/python/ui/set_manager.py +++ /dev/null @@ -1,136 +0,0 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file 'set_manager.ui' -# -# Created: Wed Mar 9 08:54:50 2016 -# by: PyQt5 UI code generator 5.2.1 -# -# WARNING! All changes made in this file will be lost! - -from PyQt5 import QtCore, QtGui, QtWidgets - -class Ui_Dialog(object): - def setupUi(self, Dialog): - Dialog.setObjectName("Dialog") - Dialog.resize(400, 300) - self.gridLayout_2 = QtWidgets.QGridLayout(Dialog) - self.gridLayout_2.setObjectName("gridLayout_2") - self.verticalLayout_3 = QtWidgets.QVBoxLayout() - self.verticalLayout_3.setObjectName("verticalLayout_3") - self.horizontalLayout = QtWidgets.QHBoxLayout() - self.horizontalLayout.setObjectName("horizontalLayout") - self.label_2 = QtWidgets.QLabel(Dialog) - self.label_2.setObjectName("label_2") - self.horizontalLayout.addWidget(self.label_2) - self.sets_combo = QtWidgets.QComboBox(Dialog) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.sets_combo.sizePolicy().hasHeightForWidth()) - self.sets_combo.setSizePolicy(sizePolicy) - self.sets_combo.setMinimumSize(QtCore.QSize(0, 40)) - self.sets_combo.setMaximumSize(QtCore.QSize(16777215, 40)) - self.sets_combo.setObjectName("sets_combo") - self.sets_combo.addItem("") - self.sets_combo.addItem("") - self.sets_combo.addItem("") - self.horizontalLayout.addWidget(self.sets_combo) - self.verticalLayout_3.addLayout(self.horizontalLayout) - self.horizontalLayout_2 = QtWidgets.QHBoxLayout() - self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.verticalLayout_2 = QtWidgets.QVBoxLayout() - self.verticalLayout_2.setObjectName("verticalLayout_2") - self.label = QtWidgets.QLabel(Dialog) - self.label.setMaximumSize(QtCore.QSize(16777215, 40)) - self.label.setObjectName("label") - self.verticalLayout_2.addWidget(self.label) - self.configs_combo = QtWidgets.QComboBox(Dialog) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.configs_combo.sizePolicy().hasHeightForWidth()) - self.configs_combo.setSizePolicy(sizePolicy) - self.configs_combo.setMinimumSize(QtCore.QSize(0, 40)) - self.configs_combo.setMaximumSize(QtCore.QSize(16777215, 40)) - self.configs_combo.setObjectName("configs_combo") - self.configs_combo.addItem("") - self.configs_combo.addItem("") - self.configs_combo.addItem("") - self.configs_combo.addItem("") - self.configs_combo.addItem("") - self.configs_combo.addItem("") - self.verticalLayout_2.addWidget(self.configs_combo) - self.verticalLayout = QtWidgets.QVBoxLayout() - self.verticalLayout.setObjectName("verticalLayout") - self.gridLayout = QtWidgets.QGridLayout() - self.gridLayout.setObjectName("gridLayout") - self.remove_button = QtWidgets.QPushButton(Dialog) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.remove_button.sizePolicy().hasHeightForWidth()) - self.remove_button.setSizePolicy(sizePolicy) - self.remove_button.setMinimumSize(QtCore.QSize(50, 50)) - self.remove_button.setMaximumSize(QtCore.QSize(50, 50)) - self.remove_button.setText("") - icon = QtGui.QIcon() - icon.addPixmap(QtGui.QPixmap("list-remove.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.remove_button.setIcon(icon) - self.remove_button.setAutoDefault(False) - self.remove_button.setObjectName("remove_button") - self.gridLayout.addWidget(self.remove_button, 0, 0, 1, 1) - self.add_button = QtWidgets.QPushButton(Dialog) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) - sizePolicy.setHorizontalStretch(0) - sizePolicy.setVerticalStretch(0) - sizePolicy.setHeightForWidth(self.add_button.sizePolicy().hasHeightForWidth()) - self.add_button.setSizePolicy(sizePolicy) - self.add_button.setMinimumSize(QtCore.QSize(50, 50)) - self.add_button.setMaximumSize(QtCore.QSize(50, 50)) - self.add_button.setText("") - icon1 = QtGui.QIcon() - icon1.addPixmap(QtGui.QPixmap("list-add.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off) - self.add_button.setIcon(icon1) - self.add_button.setAutoDefault(False) - self.add_button.setObjectName("add_button") - self.gridLayout.addWidget(self.add_button, 0, 1, 1, 1) - self.verticalLayout.addLayout(self.gridLayout) - self.remove_all = QtWidgets.QPushButton(Dialog) - self.remove_all.setMinimumSize(QtCore.QSize(0, 40)) - self.remove_all.setAutoDefault(False) - self.remove_all.setObjectName("remove_all") - self.verticalLayout.addWidget(self.remove_all) - self.verticalLayout_2.addLayout(self.verticalLayout) - self.horizontalLayout_2.addLayout(self.verticalLayout_2) - self.configs_list = QtWidgets.QListView(Dialog) - self.configs_list.setObjectName("configs_list") - self.horizontalLayout_2.addWidget(self.configs_list) - self.verticalLayout_3.addLayout(self.horizontalLayout_2) - self.buttonBox = QtWidgets.QDialogButtonBox(Dialog) - self.buttonBox.setOrientation(QtCore.Qt.Horizontal) - self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok) - self.buttonBox.setObjectName("buttonBox") - self.verticalLayout_3.addWidget(self.buttonBox) - self.gridLayout_2.addLayout(self.verticalLayout_3, 0, 0, 1, 1) - - self.retranslateUi(Dialog) - self.buttonBox.accepted.connect(Dialog.accept) - self.buttonBox.rejected.connect(Dialog.reject) - QtCore.QMetaObject.connectSlotsByName(Dialog) - - def retranslateUi(self, Dialog): - _translate = QtCore.QCoreApplication.translate - Dialog.setWindowTitle(_translate("Dialog", "Dialog")) - self.label_2.setText(_translate("Dialog", "Set :")) - self.sets_combo.setItemText(0, _translate("Dialog", "Set1")) - self.sets_combo.setItemText(1, _translate("Dialog", "Set2")) - self.sets_combo.setItemText(2, _translate("Dialog", "Set3")) - self.label.setText(_translate("Dialog", "Configurations of the set :")) - self.configs_combo.setItemText(0, _translate("Dialog", "Config1")) - self.configs_combo.setItemText(1, _translate("Dialog", "Config2")) - self.configs_combo.setItemText(2, _translate("Dialog", "Config3")) - self.configs_combo.setItemText(3, _translate("Dialog", "Config4")) - self.configs_combo.setItemText(4, _translate("Dialog", "Config5")) - self.configs_combo.setItemText(5, _translate("Dialog", "Config6")) - self.remove_all.setText(_translate("Dialog", "Remove all")) - diff --git a/sw/supervision/python/ui/set_manager.ui b/sw/supervision/python/ui/set_manager.ui deleted file mode 100644 index 06c54a3043..0000000000 --- a/sw/supervision/python/ui/set_manager.ui +++ /dev/null @@ -1,280 +0,0 @@ - - - Dialog - - - - 0 - 0 - 400 - 300 - - - - Dialog - - - - - - - - - - Set : - - - - - - - - 0 - 0 - - - - - 0 - 40 - - - - - 16777215 - 40 - - - - - Set1 - - - - - Set2 - - - - - Set3 - - - - - - - - - - - - - - - 16777215 - 40 - - - - Configurations of the set : - - - - - - - - 0 - 0 - - - - - 0 - 40 - - - - - 16777215 - 40 - - - - - Config1 - - - - - Config2 - - - - - Config3 - - - - - Config4 - - - - - Config5 - - - - - Config6 - - - - - - - - - - - - - 0 - 0 - - - - - 50 - 50 - - - - - 50 - 50 - - - - - - - - list-remove.svglist-remove.svg - - - false - - - - - - - - 0 - 0 - - - - - 50 - 50 - - - - - 50 - 50 - - - - - - - - list-add.svglist-add.svg - - - false - - - - - - - - - - 0 - 40 - - - - Remove all - - - false - - - - - - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - - - buttonBox - accepted() - Dialog - accept() - - - 258 - 289 - - - 157 - 274 - - - - - buttonBox - rejected() - Dialog - reject() - - - 326 - 289 - - - 286 - 274 - - - - - diff --git a/sw/supervision/python/ui/tools_list.ui b/sw/supervision/python/ui/tools_list.ui new file mode 100644 index 0000000000..df3ae116f9 --- /dev/null +++ b/sw/supervision/python/ui/tools_list.ui @@ -0,0 +1,46 @@ + + + ToolsList + + + + 0 + 0 + 328 + 357 + + + + Form + + + + + + true + + + + + + + true + + + + + 0 + 0 + 308 + 306 + + + + + + + + + + + diff --git a/sw/supervision/python/ui/tutorial.html b/sw/supervision/python/ui/tutorial.html deleted file mode 100644 index 47a79b9a45..0000000000 --- a/sw/supervision/python/ui/tutorial.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - -
- Paparazzi UAV icon unreachable... -

About Paparazzi UAV :

-
- - - diff --git a/sw/supervision/python/utils.py b/sw/supervision/python/utils.py new file mode 100644 index 0000000000..3c062fbc96 --- /dev/null +++ b/sw/supervision/python/utils.py @@ -0,0 +1,109 @@ +# Copyright (C) 2008-2022 The Paparazzi Team +# released under GNU GPLv2 or later. See COPYING file. +import os +import subprocess +from PyQt5.QtWidgets import * +from typing import NamedTuple +from PyQt5.QtCore import QSettings + + +class GConfEntry(NamedTuple): + name: str + value: str + application: str + + +PAPARAZZI_SRC = os.getenv("PAPARAZZI_HOME") +PAPARAZZI_HOME = os.getenv("PAPARAZZI_HOME", PAPARAZZI_SRC) +CONF_DIR = os.path.join(PAPARAZZI_HOME, "conf/") + + +# TODO: make it work with shell program such as vim. +def edit_file(file_path, prefix=CONF_DIR): + path = prefix + file_path + editor = get_settings().value("text_editor", "", str) + if editor == "": + editor = "gedit" + try: + subprocess.Popen([editor, path]) + except Exception as e: + print(e) + + +def make_line(parent: QWidget = None, vertical=False) -> QWidget: + line = QFrame(parent) + if vertical: + line.setFrameShape(QFrame.VLine) + else: + line.setFrameShape(QFrame.HLine) + line.setFrameShadow(QFrame.Sunken) + return line + + +def get_version() -> str: + run_version_exe = os.path.join(PAPARAZZI_HOME, "paparazzi_version") + proc = subprocess.run(run_version_exe, cwd=PAPARAZZI_HOME, capture_output=True) + return proc.stdout.decode().strip() + + +def get_build_version() -> str: + bv_path = os.path.join(PAPARAZZI_HOME, "var", "build_version.txt") + with open(bv_path, 'r') as f: + version = f.readline().strip() + return version + + +def open_terminal(wd, command=None): + cmd = "" + if command is not None: + cmd = " -- {}".format(command) + terminal_emulator = get_settings().value("terminal_emulator", "", str) + if terminal_emulator == "": + terminal_emulator = "gnome-terminal" + os.system("{} --working-directory {}{}".format(terminal_emulator, wd, cmd)) + + +def get_settings() -> QSettings: + return QSettings(os.path.join(CONF_DIR, "pprz_center_settings.ini"), QSettings.IniFormat) + + +ABOUT_TEXT = \ + """ +

Paparazzi Center

+

The Paparazzi Center is the home application for Paparazzi UAV.
+ Learn more about Paparazzi: +

+

+ +

Licence information:

+

+ Copyright (C) 2008-2022 The Paparazzi Team
+ Paparazzi Center is part of the Paparazzi, released under GPLv2 or any later version. + See the file COPYING, + or the licence information at http://www.gnu.org/licenses/. +

+

+ This software uses: +

+

+ + """.format(PAPARAZZI_HOME)