Qt module creator (#2479)

* Adds a GUI tool to help create new modules.
* Adds Module Creator to tools.
* Remove original OCaml create_module.
This commit is contained in:
Fabien-B
2020-01-13 21:57:43 +01:00
committed by Gautier Hattenberger
parent 8bc1f7c462
commit c5a122ec65
20 changed files with 1660 additions and 295 deletions
+3
View File
@@ -0,0 +1,3 @@
<program command="sw/tools/create_module/create_mod_qt.py" name="Module Creator">
</program>
-295
View File
@@ -1,295 +0,0 @@
#!/usr/bin/ocamlrun /usr/bin/ocaml
#load "unix.cma";;
#directory "+xml-light";;
#load "xml-light.cma";;
open Printf;;
open Scanf;;
let ask = fun text ->
printf "%s: " text;
flush stdout;
input_line stdin;;
type optional = Optional | Mandatory;;
let rec ask_param = fun text opt ->
match opt with
| Optional ->
printf " - %s (optional): " text; flush stdout;
input_line stdin;
| Mandatory ->
printf " - %s (mandatory): " text; flush stdout;
let res = input_line stdin in
if res = "" then ask_param text opt else res;
;;
let quit_with_error = fun text err ->
printf "%s\n" text;
exit err;;
printf " ##########################\n";;
printf " ## Module Creator ##\n";;
printf " ##########################\n\n";;
printf "This program will help you to create a new module for Paparazzi\n";;
printf "Not all options are accessible from this program,\n";
printf "see http://wiki.paparazziuav.org/wiki/Modules for more information.\n";
(*printf "Please follow the instruction or pass a module xml file as intput\n\n";;*)
printf "Please follow the instruction\n\n";;
let name = String.lowercase (ask "Enter your module name");;
if name = "" then quit_with_error "module name must not be empty. Leaving." 1;;
let dir = String.lowercase (ask "Enter a module directory or leave blank if same as name");;
let desc = ask "Enter a short description of your module";;
let init_list = ref [];;
let periodic_list = ref [];;
let event_list = ref [];;
let datalink_list = ref [];;
let add_to_list = fun l a ->
l := !l @ [a];;
let ask_init = fun () ->
if (List.length !init_list) > 0 then
printf "You already added an init function.\n"
else begin
printf "Initialization function to call, eg \"foo_init()\":\n";
let name = String.lowercase (ask_param "function" Mandatory) in
add_to_list init_list name
end;
true;;
let ask_periodic = fun () ->
printf "Parameters for a periodic function:\n";
let name = String.lowercase (ask_param "function name" Mandatory) in
let freq = ask_param "call frequency" Mandatory in
let start = String.lowercase (ask_param "start function" Optional) in
let stop = String.lowercase (ask_param "stop function" Optional) in
let auto = ask_param "autorun flag [TRUE, FALSE, LOCK (default)]" Optional in
add_to_list periodic_list (name, freq, start, stop, auto);
true;;
let ask_event = fun () ->
printf "Parameters for an event function:\n";
let name = String.lowercase(ask_param "function name" Mandatory) in
add_to_list event_list name;
true;;
let ask_datalink = fun () ->
printf "Parameters for a datalink event callback:\n";
let msg = ask_param "message name" Mandatory in
let name = ask_param "callback function name" Mandatory in
add_to_list datalink_list (msg, name);
true;;
let show_module = fun () ->
printf "\nModule name: %s\n" name;
if dir <> "" then printf "Module directory: %s\n" dir;
if desc <> "" then printf "Module description: %s\n" desc;
List.iter (fun n -> printf "Init function: %s\n" n) !init_list;
List.iter (fun (n, f, start, stop, auto) ->
let _start = if start <> "" then " [ Start: "^start^" ] " else "" in
let _stop = if stop <> "" then " [ Stop: "^stop^" ] " else "" in
let _auto = if auto <> "" then " [ Auto: "^auto^" ] " else "" in
printf "Periodic function: %s at %s Hz%s%s%s\n" n f _start _stop _auto;
) !periodic_list;
List.iter (fun n -> printf "Event function: %s\n" n) !event_list;
List.iter (fun (m, n) -> printf "Datalink event: %s on message %s\n" n m) !datalink_list;
flush stdout;
true;;
let choices = [
("Initialization function", ask_init);
("Periodic function", ask_periodic);
("Event function", ask_event);
("Datalink event function", ask_datalink);
("Display the current state of your module", show_module);
("End process and create module", (fun () -> false));
("Cancel and leave program", (fun () -> quit_with_error "Cancel by operator. Leaving." 2))
];;
let ask_choice = fun choices ->
printf "\nPlease select the type of function to add to your module:\n";
let rec display = fun i c ->
match c with
| (text, _) :: cl ->
printf "%d - %s\n" i text;
display (i+1) cl;
| [] -> ()
in
display 1 choices;
printf "Type number [1-%d]: " (List.length choices);
flush stdout;
try
let r = int_of_string (input_line stdin) in
let (_, f) = (Array.of_list choices).(r-1) in
f ()
with _ -> printf "Invalid entry\n"; true
;;
while ask_choice choices do () done;;
let xml_of_name = fun n d ->
if d <> "" then [("name", n); ("dir", d)]
else [("name", n)];;
let header_file = name^".h";;
let code_file = name^".c";;
let xml_header_of_name = fun n ->
[Xml.Element ("header", [], [
Xml.Element ("file", [("name", n)], [])
])];;
let xml_of_description = fun d ->
let desc = Xml.Element ("description", [], [Xml.PCData d]) in
[Xml.Element ("doc", [], [desc])];;
let xml_of_init = fun l ->
List.map (fun n -> Xml.Element ("init", [("fun", n)], [])) l;;
let xml_of_peridic = fun l ->
List.map (fun (n, f, start, stop, auto) ->
let _start = if start <> "" then [("start", start)] else [] in
let _stop = if stop <> "" then [("stop", stop)] else [] in
let _auto = if auto <> "" then [("autorun", auto)] else [] in
Xml.Element ("periodic", List.flatten [
[("fun", n)]; [("freq", f)]; _start; _stop; _auto],
[])
) l;;
let xml_of_event = fun l ->
List.map (fun n -> Xml.Element ("event", [("fun", n)], [])) l;;
let xml_of_datalink = fun l ->
List.map (fun (m, n) -> Xml.Element ("datalink", [("message", m); ("fun", n)], [])) l;;
let xml_makefile_of_name = fun n ->
[Xml.Element ("makefile", [], [
Xml.Element ("file", [("name", n)], [])
])];;
let module_xml = Xml.Element ("module", xml_of_name name dir, List.flatten [
xml_of_description desc;
xml_header_of_name header_file;
xml_of_init !init_list;
xml_of_peridic !periodic_list;
xml_of_event !event_list;
xml_of_datalink !datalink_list;
xml_makefile_of_name code_file]);;
let (//) = Filename.concat;;
let dir_name = if dir = "" then name else dir;;
let xml_name = "conf/modules" // name^".xml";;
let header_name = "sw/airborne/modules"// dir_name // name^".h";;
let code_name = "sw/airborne/modules" // dir_name // name^".c";;
let test_filename = fun () ->
let ask_confirm = ref false in
let disp_msg = fun f c ->
printf "File %s already exists\n" f;
c := true;
in
if Sys.file_exists xml_name then disp_msg xml_name ask_confirm;
if Sys.file_exists header_name then disp_msg header_name ask_confirm;
if Sys.file_exists code_name then disp_msg code_name ask_confirm;
if !ask_confirm then begin
if String.lowercase (ask "Confirm erasing files ? [y,N]") <> "y"
then quit_with_error "Not erasing existing files. Leaving" 1
end;;
let write_module_xml = fun out ->
fprintf out "<!DOCTYPE module SYSTEM \"module.dtd\">\n\n";
fprintf out "%s\n\n" (Xml.to_string_fmt module_xml);;
let write_license = fun out ->
fprintf out " * paparazzi is free software; you can redistribute it and/or modify\n";
fprintf out " * it under the terms of the GNU General Public License as published by\n";
fprintf out " * the Free Software Foundation; either version 2, or (at your option)\n";
fprintf out " * any later version.\n";
fprintf out " *\n";
fprintf out " * paparazzi is distributed in the hope that it will be useful,\n";
fprintf out " * but WITHOUT ANY WARRANTY; without even the implied warranty of\n";
fprintf out " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n";
fprintf out " * GNU General Public License for more details.\n";
fprintf out " *\n";
fprintf out " * You should have received a copy of the GNU General Public License\n";
fprintf out " * along with paparazzi; see the file COPYING. If not, see\n";
fprintf out " * <http://www.gnu.org/licenses/>.\n";;
let write_copyright = fun out author gpl ->
fprintf out "/*\n";
fprintf out " * Copyright (C) %s\n" author;
fprintf out " *\n";
fprintf out " * This file is part of paparazzi\n";
fprintf out " *\n";
if gpl then write_license out;
fprintf out " */\n";;
let write_doxygen_header = fun out author filename description ->
fprintf out "/**\n";
fprintf out " * @file %s\n" filename;
fprintf out " * @author %s\n" author;
fprintf out " * %s\n" description;
fprintf out " */\n";;
let write_header = fun out author gpl ->
write_copyright out author gpl;
write_doxygen_header out author (sprintf "\"modules/%s/%s.h\"" dir_name name) desc;
fprintf out "\n#ifndef %s_H" (String.uppercase name);
fprintf out "\n#define %s_H\n\n" (String.uppercase name);
List.iter (fun f -> fprintf out "// extern void %s;\n" f) !init_list;
List.iter (fun (f,_,_,_,_) -> fprintf out "// extern void %s;\n" f) !periodic_list;
List.iter (fun f -> fprintf out "// extern void %s;\n" f) !event_list;
List.iter (fun (_,f) -> fprintf out "// extern void %s;\n" f) !datalink_list;
fprintf out "\n#endif\n\n";;
let write_code = fun out author gpl ->
write_copyright out author gpl;
write_doxygen_header out author (sprintf "\"modules/%s/%s.c\"" dir_name name) desc;
fprintf out "\n#include \"modules/%s/%s.h\"\n\n" dir_name name;
List.iter (fun f -> fprintf out "// void %s {}\n" f) !init_list;
List.iter (fun (f,_,_,_,_) -> fprintf out "// void %s {}\n" f) !periodic_list;
List.iter (fun f -> fprintf out "// void %s {}\n" f) !event_list;
List.iter (fun (_,f) -> fprintf out "// void %s {}\n" f) !datalink_list;
fprintf out "\n\n";;
print_newline ();;
test_filename ();;
print_newline ();;
let author = ask "Author name";;
let gpl = ask "Do you want to use GPLv2 license ? [Y,n]";;
let gpl = String.lowercase (gpl) = "y" || gpl = "";;
printf "Creating file %s ... " xml_name;;
try
let xml_out = open_out xml_name in
write_module_xml xml_out;
close_out xml_out;
printf "[done]\n";
with _ -> printf "[fail]\n";
flush stdout;;
Sys.command (sprintf "mkdir -p %s" ("sw/airborne/modules" // dir_name));;
printf "Creating file %s ... " header_name;;
try
let h_out = open_out header_name in
write_header h_out author gpl;
close_out h_out;
printf "[done]\n";
with _ -> printf "[fail]\n";
flush stdout;;
printf "Creating file %s ... " code_name;;
try
let c_out = open_out code_name in
write_code c_out author gpl;
close_out c_out;
printf "[done]\n";
with _ -> printf "[fail]\n";
flush stdout;;
printf "\nModule %s created\n" name;;
+10
View File
@@ -0,0 +1,10 @@
all:
pyuic5 create_module_ui.ui -o create_module_ui.py
pyuic5 datalink_ui.ui -o datalink_ui.py
pyuic5 event_ui.ui -o event_ui.py
pyuic5 init_ui.ui -o init_ui.py
pyuic5 periodic_ui.ui -o periodic_ui.py
clean:
rm create_module_ui.py datalink_ui.py event_ui.py init_ui.py periodic_ui.py
+5
View File
@@ -0,0 +1,5 @@
This tool helps you create a new module.
Need python3 with some modules, see requirements.txt.
Usage: launch the create_mod_qt.py module:
./create_mod_qt.py
+77
View File
@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="50"
height="50"
viewBox="0 0 13.229167 13.229167"
version="1.1"
id="svg8"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="add.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.313709"
inkscape:cx="35.338968"
inkscape:cy="26.604334"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1851"
inkscape:window-height="1012"
inkscape:window-x="1749"
inkscape:window-y="32"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-283.77082)">
<rect
style="fill:#00a300;fill-opacity:1;stroke:#00a300;stroke-width:0.34138367;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect819"
width="12.886954"
height="3.2371497"
x="0.17129618"
y="288.73166"
rx="0"
ry="0" />
<rect
style="fill:#00a300;fill-opacity:1;stroke:#00a300;stroke-width:0.34138367;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect819-3"
width="12.886954"
height="3.2371497"
x="283.90677"
y="-8.2333479"
rx="0"
ry="0"
transform="rotate(90)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

+21
View File
@@ -0,0 +1,21 @@
from PyQt5 import QtWidgets
from init_ui import Ui_Init
from periodic_ui import Ui_Periodic
from event_ui import Ui_Event
from datalink_ui import Ui_Datalink
class ComponentWidget(QtWidgets.QFrame):
def __init__(self, comp_type):
QtWidgets.QWidget.__init__(self)
self.comp_type = comp_type
self.ui = None
if self.comp_type == "Init":
self.ui = Ui_Init()
if self.comp_type == "Event":
self.ui = Ui_Event()
if self.comp_type == "Periodic":
self.ui = Ui_Periodic()
if self.comp_type == "Datalink":
self.ui = Ui_Datalink()
self.ui.setupUi(self)
+150
View File
@@ -0,0 +1,150 @@
#!/usr/bin/env python3
import sys
from PyQt5 import QtWidgets
from create_module_ui import Ui_CreateModule_Window
import components
import files_create
import unidecode
import os
from lxml import etree
PPRZ_SRC = os.getenv("PAPARAZZI_SRC")
PPRZ_HOME = os.getenv("PAPARAZZI_HOME")
if PPRZ_SRC is None:
PPRZ_SRC = os.path.realpath(os.path.dirname(os.path.realpath(__file__)) + "/../../..")
print("PAPARAZZI_SRC not set. Use {} as paparazzi home.".format(PPRZ_SRC))
if PPRZ_HOME is None:
PPRZ_HOME = PPRZ_SRC
class CreateModGUI(Ui_CreateModule_Window):
def __init__(self, parent=None):
Ui_CreateModule_Window.__init__(parent)
self.components = []
def build(self):
self.scrollAreaWidgetContents.setStyleSheet("QFrame#Init, QFrame#Datalink, QFrame#Periodic,QFrame#Event { border: 2px solid grey}")
self.create_button.clicked.connect(self.create_mod)
self.component_add_button.clicked.connect(self.add_component)
self.directory_combo.addItem("")
for directory in sorted([f.name for f in os.scandir(PPRZ_SRC + "/sw/airborne/modules") if f.is_dir()]):
self.directory_combo.addItem(directory)
self.get_messages()
@staticmethod
def get_messages():
messages_xml = PPRZ_HOME + "/var/messages.xml"
root = etree.parse(messages_xml).getroot()
classes = root.findall("msg_class")
for c in classes:
if c.attrib["name"] == "datalink":
messages = [m.attrib["name"] for m in c.findall("message")]
return messages
return []
def add_component(self):
comp_name = self.components_combo.currentText()
component = components.ComponentWidget(comp_name)
if component.comp_type == "Datalink":
messages = self.get_messages()
component.ui.message_combo.addItem("")
for m in messages:
component.ui.message_combo.addItem(m)
component.ui.remove_button.clicked.connect(lambda: self.remove_component(component))
self.scroll_area_layout.insertWidget(self.scroll_area_layout.count()-1, component)
self.components.append(component)
def remove_component(self, component):
component.deleteLater()
self.components.remove(component)
def create_mod(self):
fc = files_create.FilesCreate()
name = self.name_edit.text()
directory = self.directory_combo.currentText()
author = self.author_edit.text()
email = self.email_edit.text()
description = unidecode.unidecode(self.description_edit.toPlainText())
self.description_edit.setPlainText(description)
if name == "" or author == "" or description == "" or email == "":
self.statusbar.showMessage("Please fill the name, author, mail and description!")
self.statusbar.setStyleSheet("background-color:rgb(255,148,148);")
return
fc.name = name
fc.directory = directory
fc.description = description
fc.author = author
fc.email = email
for comp in self.components:
if comp.comp_type == "Init":
init = comp.ui.init_edit.text()
if init == "":
self.statusbar.showMessage("Please fill the Init field!")
self.statusbar.setStyleSheet("background-color:rgb(255,148,148);")
return
fc.add_init(init)
if comp.comp_type == "Periodic":
periodic = comp.ui.periodic_edit.text()
freq = comp.ui.freq_spinbox.value()
stop = comp.ui.stop_edit.text()
start = comp.ui.start_edit.text()
autorun = comp.ui.autorun_comboBox.currentText()
if periodic == "":
self.statusbar.showMessage("Please fill the Periodic field!")
self.statusbar.setStyleSheet("background-color:rgb(255,148,148);")
return
if freq == 0:
self.statusbar.showMessage("Freq should be > 0!")
self.statusbar.setStyleSheet("background-color:rgb(255,148,148);")
return
fc.add_periodic(periodic, freq, start, stop, autorun)
if comp.comp_type == "Event":
event = comp.ui.event_edit.text()
if event == "":
self.statusbar.showMessage("Please fill the Event field!")
self.statusbar.setStyleSheet("background-color:rgb(255,148,148);")
return
fc.add_event(event)
if comp.comp_type == "Datalink":
datalink = comp.ui.datalink_edit.text()
msg = comp.ui.message_combo.currentText()
if datalink == "" or msg == "":
self.statusbar.showMessage("Please fill the Datalink and Message fields!")
self.statusbar.setStyleSheet("background-color:rgb(255,148,148);")
return
fc.add_datalink(datalink, msg)
self.statusbar.setStyleSheet("background-color:rgb(155,232,155);")
licence = self.licence_comboBox.currentText()
files = fc.get_filenames()
existing = list(filter(lambda x: os.path.exists(x) and not os.path.isdir(x), files))
if len(existing) > 0:
message = "Do you want to overwrite these files ?\n" + "\n".join(existing)
buttonReply = QtWidgets.QMessageBox.question(None, 'Overwrite files ?', message,
QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No)
if buttonReply == QtWidgets.QMessageBox.No:
self.statusbar.showMessage("Action canceled! (no files overwritten)")
self.statusbar.setStyleSheet("background-color:rgb(255,204,0);")
return
fc.build_files(licence)
fc.write_files()
self.statusbar.showMessage("Ok!")
def closing(self):
pass
def main():
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
create_mod = CreateModGUI()
app.aboutToQuit.connect(create_mod.closing)
create_mod.setupUi(MainWindow)
create_mod.build()
MainWindow.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
+165
View File
@@ -0,0 +1,165 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'create_module_ui.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_CreateModule_Window(object):
def setupUi(self, CreateModule_Window):
CreateModule_Window.setObjectName("CreateModule_Window")
CreateModule_Window.resize(875, 553)
self.centralwidget = QtWidgets.QWidget(CreateModule_Window)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout_6 = QtWidgets.QHBoxLayout()
self.horizontalLayout_6.setObjectName("horizontalLayout_6")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setObjectName("label")
self.horizontalLayout.addWidget(self.label)
self.name_edit = QtWidgets.QLineEdit(self.centralwidget)
self.name_edit.setObjectName("name_edit")
self.horizontalLayout.addWidget(self.name_edit)
self.horizontalLayout_6.addLayout(self.horizontalLayout)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.label_2 = QtWidgets.QLabel(self.centralwidget)
self.label_2.setObjectName("label_2")
self.horizontalLayout_2.addWidget(self.label_2)
self.directory_combo = QtWidgets.QComboBox(self.centralwidget)
self.directory_combo.setEditable(True)
self.directory_combo.setObjectName("directory_combo")
self.horizontalLayout_2.addWidget(self.directory_combo)
self.horizontalLayout_6.addLayout(self.horizontalLayout_2)
self.horizontalLayout_15 = QtWidgets.QHBoxLayout()
self.horizontalLayout_15.setObjectName("horizontalLayout_15")
self.label_12 = QtWidgets.QLabel(self.centralwidget)
self.label_12.setObjectName("label_12")
self.horizontalLayout_15.addWidget(self.label_12)
self.licence_comboBox = QtWidgets.QComboBox(self.centralwidget)
self.licence_comboBox.setEditable(False)
self.licence_comboBox.setObjectName("licence_comboBox")
self.licence_comboBox.addItem("")
self.licence_comboBox.addItem("")
self.horizontalLayout_15.addWidget(self.licence_comboBox)
self.horizontalLayout_6.addLayout(self.horizontalLayout_15)
self.horizontalLayout_6.setStretch(0, 1)
self.horizontalLayout_6.setStretch(1, 1)
self.verticalLayout.addLayout(self.horizontalLayout_6)
self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
self.horizontalLayout_4.setObjectName("horizontalLayout_4")
self.label_4 = QtWidgets.QLabel(self.centralwidget)
self.label_4.setObjectName("label_4")
self.horizontalLayout_4.addWidget(self.label_4)
self.author_edit = QtWidgets.QLineEdit(self.centralwidget)
self.author_edit.setObjectName("author_edit")
self.horizontalLayout_4.addWidget(self.author_edit)
self.horizontalLayout_5.addLayout(self.horizontalLayout_4)
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.label_5 = QtWidgets.QLabel(self.centralwidget)
self.label_5.setObjectName("label_5")
self.horizontalLayout_3.addWidget(self.label_5)
self.email_edit = QtWidgets.QLineEdit(self.centralwidget)
self.email_edit.setObjectName("email_edit")
self.horizontalLayout_3.addWidget(self.email_edit)
self.horizontalLayout_5.addLayout(self.horizontalLayout_3)
self.verticalLayout.addLayout(self.horizontalLayout_5)
self.label_3 = QtWidgets.QLabel(self.centralwidget)
self.label_3.setObjectName("label_3")
self.verticalLayout.addWidget(self.label_3)
self.splitter = QtWidgets.QSplitter(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.splitter.sizePolicy().hasHeightForWidth())
self.splitter.setSizePolicy(sizePolicy)
self.splitter.setOrientation(QtCore.Qt.Vertical)
self.splitter.setChildrenCollapsible(False)
self.splitter.setObjectName("splitter")
self.description_edit = QtWidgets.QPlainTextEdit(self.splitter)
self.description_edit.setMinimumSize(QtCore.QSize(0, 0))
self.description_edit.setBaseSize(QtCore.QSize(0, 30))
self.description_edit.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContentsOnFirstShow)
self.description_edit.setObjectName("description_edit")
self.components_area = QtWidgets.QScrollArea(self.splitter)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(1)
sizePolicy.setHeightForWidth(self.components_area.sizePolicy().hasHeightForWidth())
self.components_area.setSizePolicy(sizePolicy)
self.components_area.setWidgetResizable(True)
self.components_area.setObjectName("components_area")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 855, 258))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.scroll_area_layout = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents)
self.scroll_area_layout.setObjectName("scroll_area_layout")
spacerItem = QtWidgets.QSpacerItem(20, 76, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.scroll_area_layout.addItem(spacerItem)
self.components_area.setWidget(self.scrollAreaWidgetContents)
self.verticalLayout.addWidget(self.splitter)
self.horizontalLayout_7 = QtWidgets.QHBoxLayout()
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
self.label_6 = QtWidgets.QLabel(self.centralwidget)
self.label_6.setObjectName("label_6")
self.horizontalLayout_7.addWidget(self.label_6)
self.components_combo = QtWidgets.QComboBox(self.centralwidget)
self.components_combo.setObjectName("components_combo")
self.components_combo.addItem("")
self.components_combo.addItem("")
self.components_combo.addItem("")
self.components_combo.addItem("")
self.horizontalLayout_7.addWidget(self.components_combo)
self.component_add_button = QtWidgets.QToolButton(self.centralwidget)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("add.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.component_add_button.setIcon(icon)
self.component_add_button.setObjectName("component_add_button")
self.horizontalLayout_7.addWidget(self.component_add_button)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout_7.addItem(spacerItem1)
self.verticalLayout.addLayout(self.horizontalLayout_7)
self.create_button = QtWidgets.QPushButton(self.centralwidget)
self.create_button.setObjectName("create_button")
self.verticalLayout.addWidget(self.create_button)
CreateModule_Window.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(CreateModule_Window)
self.menubar.setGeometry(QtCore.QRect(0, 0, 875, 22))
self.menubar.setObjectName("menubar")
CreateModule_Window.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(CreateModule_Window)
self.statusbar.setObjectName("statusbar")
CreateModule_Window.setStatusBar(self.statusbar)
self.retranslateUi(CreateModule_Window)
QtCore.QMetaObject.connectSlotsByName(CreateModule_Window)
def retranslateUi(self, CreateModule_Window):
_translate = QtCore.QCoreApplication.translate
CreateModule_Window.setWindowTitle(_translate("CreateModule_Window", "Create Module"))
self.label.setText(_translate("CreateModule_Window", "Module name"))
self.label_2.setText(_translate("CreateModule_Window", "Directory"))
self.label_12.setText(_translate("CreateModule_Window", "Licence"))
self.licence_comboBox.setItemText(0, _translate("CreateModule_Window", "GPLv2"))
self.licence_comboBox.setItemText(1, _translate("CreateModule_Window", "None"))
self.label_4.setText(_translate("CreateModule_Window", "Author"))
self.label_5.setText(_translate("CreateModule_Window", "email"))
self.label_3.setText(_translate("CreateModule_Window", "Description"))
self.label_6.setText(_translate("CreateModule_Window", "Add element :"))
self.components_combo.setItemText(0, _translate("CreateModule_Window", "Init"))
self.components_combo.setItemText(1, _translate("CreateModule_Window", "Periodic"))
self.components_combo.setItemText(2, _translate("CreateModule_Window", "Event"))
self.components_combo.setItemText(3, _translate("CreateModule_Window", "Datalink"))
self.component_add_button.setToolTip(_translate("CreateModule_Window", "Add component"))
self.component_add_button.setText(_translate("CreateModule_Window", "Add"))
self.create_button.setText(_translate("CreateModule_Window", "Create Module"))
+275
View File
@@ -0,0 +1,275 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CreateModule_Window</class>
<widget class="QMainWindow" name="CreateModule_Window">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>875</width>
<height>553</height>
</rect>
</property>
<property name="windowTitle">
<string>Create Module</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6" stretch="1,1,0">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Module name</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="name_edit"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Directory</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="directory_combo">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_15">
<item>
<widget class="QLabel" name="label_12">
<property name="text">
<string>Licence</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="licence_comboBox">
<property name="editable">
<bool>false</bool>
</property>
<item>
<property name="text">
<string>GPLv2</string>
</property>
</item>
<item>
<property name="text">
<string>None</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Author</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="author_edit"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>email</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="email_edit"/>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Description</string>
</property>
</widget>
</item>
<item>
<widget class="QSplitter" name="splitter">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="childrenCollapsible">
<bool>false</bool>
</property>
<widget class="QPlainTextEdit" name="description_edit">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContentsOnFirstShow</enum>
</property>
</widget>
<widget class="QScrollArea" name="components_area">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>855</width>
<height>258</height>
</rect>
</property>
<layout class="QVBoxLayout" name="scroll_area_layout">
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>76</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7" stretch="0,0,0,0">
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Add element :</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="components_combo">
<item>
<property name="text">
<string>Init</string>
</property>
</item>
<item>
<property name="text">
<string>Periodic</string>
</property>
</item>
<item>
<property name="text">
<string>Event</string>
</property>
</item>
<item>
<property name="text">
<string>Datalink</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QToolButton" name="component_add_button">
<property name="toolTip">
<string>Add component</string>
</property>
<property name="text">
<string>Add</string>
</property>
<property name="icon">
<iconset>
<normaloff>add.svg</normaloff>add.svg</iconset>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="create_button">
<property name="text">
<string>Create Module</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>875</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
+64
View File
@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'datalink_ui.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Datalink(object):
def setupUi(self, Datalink):
Datalink.setObjectName("Datalink")
Datalink.resize(753, 79)
self.verticalLayout = QtWidgets.QVBoxLayout(Datalink)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_11 = QtWidgets.QLabel(Datalink)
self.label_11.setStyleSheet("font: bold")
self.label_11.setAlignment(QtCore.Qt.AlignCenter)
self.label_11.setObjectName("label_11")
self.horizontalLayout.addWidget(self.label_11)
self.remove_button = QtWidgets.QToolButton(Datalink)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("remove.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.remove_button.setIcon(icon)
self.remove_button.setObjectName("remove_button")
self.horizontalLayout.addWidget(self.remove_button)
self.verticalLayout.addLayout(self.horizontalLayout)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.horizontalLayout_20 = QtWidgets.QHBoxLayout()
self.horizontalLayout_20.setObjectName("horizontalLayout_20")
self.label_16 = QtWidgets.QLabel(Datalink)
self.label_16.setObjectName("label_16")
self.horizontalLayout_20.addWidget(self.label_16)
self.datalink_edit = QtWidgets.QLineEdit(Datalink)
self.datalink_edit.setObjectName("datalink_edit")
self.horizontalLayout_20.addWidget(self.datalink_edit)
self.horizontalLayout_2.addLayout(self.horizontalLayout_20)
self.horizontalLayout_19 = QtWidgets.QHBoxLayout()
self.horizontalLayout_19.setObjectName("horizontalLayout_19")
self.label_15 = QtWidgets.QLabel(Datalink)
self.label_15.setObjectName("label_15")
self.horizontalLayout_19.addWidget(self.label_15)
self.message_combo = QtWidgets.QComboBox(Datalink)
self.message_combo.setEditable(True)
self.message_combo.setObjectName("message_combo")
self.horizontalLayout_19.addWidget(self.message_combo)
self.horizontalLayout_2.addLayout(self.horizontalLayout_19)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.retranslateUi(Datalink)
QtCore.QMetaObject.connectSlotsByName(Datalink)
def retranslateUi(self, Datalink):
_translate = QtCore.QCoreApplication.translate
Datalink.setWindowTitle(_translate("Datalink", "Datalink"))
self.label_11.setText(_translate("Datalink", "Datalink"))
self.remove_button.setText(_translate("Datalink", "remove"))
self.label_16.setText(_translate("Datalink", "fun"))
self.label_15.setText(_translate("Datalink", "Message"))
+85
View File
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Datalink</class>
<widget class="QWidget" name="Datalink">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>753</width>
<height>79</height>
</rect>
</property>
<property name="windowTitle">
<string>Datalink</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_11">
<property name="styleSheet">
<string notr="true">font: bold</string>
</property>
<property name="text">
<string>Datalink</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="remove_button">
<property name="text">
<string>remove</string>
</property>
<property name="icon">
<iconset>
<normaloff>remove.svg</normaloff>remove.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_20">
<item>
<widget class="QLabel" name="label_16">
<property name="text">
<string>fun</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="datalink_edit"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_19">
<item>
<widget class="QLabel" name="label_15">
<property name="text">
<string>Message</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="message_combo">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+50
View File
@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'event_ui.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Event(object):
def setupUi(self, Event):
Event.setObjectName("Event")
Event.resize(619, 77)
self.verticalLayout = QtWidgets.QVBoxLayout(Event)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_11 = QtWidgets.QLabel(Event)
self.label_11.setStyleSheet("font: bold")
self.label_11.setAlignment(QtCore.Qt.AlignCenter)
self.label_11.setObjectName("label_11")
self.horizontalLayout.addWidget(self.label_11)
self.remove_button = QtWidgets.QToolButton(Event)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("remove.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.remove_button.setIcon(icon)
self.remove_button.setObjectName("remove_button")
self.horizontalLayout.addWidget(self.remove_button)
self.verticalLayout.addLayout(self.horizontalLayout)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.label_10 = QtWidgets.QLabel(Event)
self.label_10.setObjectName("label_10")
self.horizontalLayout_2.addWidget(self.label_10)
self.event_edit = QtWidgets.QLineEdit(Event)
self.event_edit.setObjectName("event_edit")
self.horizontalLayout_2.addWidget(self.event_edit)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.retranslateUi(Event)
QtCore.QMetaObject.connectSlotsByName(Event)
def retranslateUi(self, Event):
_translate = QtCore.QCoreApplication.translate
Event.setWindowTitle(_translate("Event", "Event"))
self.label_11.setText(_translate("Event", "Event"))
self.remove_button.setText(_translate("Event", "remove"))
self.label_10.setText(_translate("Event", "fun"))
+63
View File
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Event</class>
<widget class="QWidget" name="Event">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>619</width>
<height>77</height>
</rect>
</property>
<property name="windowTitle">
<string>Event</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_11">
<property name="styleSheet">
<string notr="true">font: bold</string>
</property>
<property name="text">
<string>Event</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="remove_button">
<property name="text">
<string>remove</string>
</property>
<property name="icon">
<iconset>
<normaloff>remove.svg</normaloff>remove.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>fun</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="event_edit"/>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+258
View File
@@ -0,0 +1,258 @@
#!/usr/bin/env python3
import os
from lxml import etree
from collections import namedtuple
PPRZ_SRC = os.getenv("PAPARAZZI_SRC")
PPRZ_HOME = os.getenv("PAPARAZZI_HOME")
if PPRZ_SRC is None:
PPRZ_SRC = os.path.realpath(os.path.dirname(os.path.realpath(__file__)) + "/../../..")
print("PAPARAZZI_SRC not set. Use {} as paparazzi home.".format(PPRZ_SRC))
if PPRZ_HOME is None:
PPRZ_HOME = PPRZ_SRC
GPLv2 = """
*
* 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, see
* <http://www.gnu.org/licenses/>.
"""
LICENCES = {"GPLv2": GPLv2, None: "", "None": ""}
Periodic = namedtuple('Periodic', ['fun', 'freq', 'start', 'stop', 'autorun'])
Event = namedtuple('Event', ['fun'])
Init = namedtuple('Init', ['fun'])
Datalink = namedtuple('Datalink', ['fun', 'message', 'fun_c'])
class FilesCreate:
def __init__(self):
self.xml = etree.Element("module")
self.header = ""
self.src = ""
self._name = ""
self._directory = ""
self._description = ""
self._author = ""
self._email = ""
self.inits = []
self.periodics = []
self.events = []
self.datalinks = []
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name.lower()
@property
def directory(self):
if self._directory == "":
return self.name
return self._directory
@directory.setter
def directory(self, d):
self._directory = d.lower()
@property
def description(self):
return self._description
@description.setter
def description(self, description):
self._description = description
@property
def author(self):
return self._author
@author.setter
def author(self, author):
self._author = author
@property
def email(self):
return self._email
@email.setter
def email(self, email):
self._email = "<{}>".format(email)
def add_init(self, fun):
fun = fun.strip("()")
self.inits.append(Init(fun=fun))
def add_periodic(self, fun, freq, start="", stop="", autorun='LOCK'):
# add parenthesis to function name
fun = fun.strip("()")
start = start.strip("()")
stop = stop.strip("()")
self.periodics.append(Periodic(fun=fun, freq=str(freq), start=start, stop=stop, autorun=autorun))
def add_event(self, fun):
fun = fun.strip("()")
self.events.append(Event(fun=fun))
def add_datalink(self, fun, message):
splits = fun.split("(", maxsplit=1)
if len(splits) > 1:
name, args = splits
args = filter(lambda x: not x=='', [arg.strip() for arg in args.strip(")").split(",")])
args = [arg.rsplit(" ", 1) for arg in args]
fun_c = name + "(" + ", ".join(["{} {}".format(t, n) for t, n in args]) + ")"
fun_xml = name + "(/*" + ", ".join(["{}".format(n.strip("*")) for t, n in args]) + "*/)"
else:
fun_xml = fun + "(buf)"
fun_c = fun + "(uint8_t* buf)"
self.datalinks.append(Datalink(fun=fun_xml, message=message, fun_c=fun_c))
def build_xml(self):
# set name
self.xml.attrib["name"] = self.name
# set directory
self.xml.attrib["dir"] = self.directory
#set description
description = etree.Element("description")
description.text = self.description
doc = etree.Element("doc")
doc.append(description)
self.xml.append(doc)
# set header
h_file = etree.Element("file")
h_file.attrib["name"] = "{}.h".format(self.name)
header = etree.Element("header")
header.append(h_file)
self.xml.append(header)
# set init
for init in self.inits:
init_el = etree.Element("init")
init_el.attrib["fun"] = init.fun + "()"
self.xml.append(init_el)
# set periodic
for periodic in self.periodics:
periodic_el = etree.Element("periodic")
periodic_el.attrib["fun"] = periodic.fun + "()"
periodic_el.attrib["freq"] = periodic.freq
if not periodic.start == "":
periodic_el.attrib["start"] = periodic.start + "()"
if not periodic.stop == "":
periodic_el.attrib["stop"] = periodic.stop + "()"
if not periodic.autorun == "":
periodic_el.attrib["autorun"] = periodic.autorun
self.xml.append(periodic_el)
# set event
for event in self.events:
event_el = etree.Element("event")
event_el.attrib["fun"] = event.fun + "()"
self.xml.append(event_el)
# set datalink
for datalink in self.datalinks:
datalink_el = etree.Element("datalink")
datalink_el.attrib["fun"] = datalink.fun
datalink_el.attrib["message"] = datalink.message
self.xml.append(datalink_el)
# set makefile
c_file = etree.Element("file")
c_file.attrib["name"] = "{}.c".format(self.name)
makefile = etree.Element("makefile")
makefile.append(c_file)
self.xml.append(makefile)
def build_src(self, licence="GPLv2"):
cop = "/*\n * Copyright (C) {author} {email}\n{licence}\n */".format(
author=self.author, email=self.email, licence=LICENCES[licence])
description = "/** @file \"modules/{dir}/{name}.h\"\n * @author {author} {email}\n * {description}\n */".format(
dir=self.directory, name=self.name, author=self.author, email=self.email, description=self.description)
include = "#include \"modules/{dir}/{name}.h\"".format(dir=self.directory, name=self.name)
declarations = ""
for init in self.inits:
declarations += "void {}(){{\n // your init code here\n}}\n\n".format(init.fun)
for periodic in self.periodics:
declarations += "void {}(){{\n // your periodic code here.\n // freq = {} Hz\n}}\n\n".format(
periodic.fun, periodic.freq)
if not periodic.start == "":
declarations += "void {}(){{\n // your periodic start code here.\n}}\n\n".format(
periodic.start)
if not periodic.stop == "":
declarations += "void {}(){{\n // your periodic stop code here.\n}}\n\n".format(
periodic.stop)
for event in self.events:
declarations += "void {}(){{\n // your event code here\n}}\n\n".format(event.fun)
for datalink in self.datalinks:
declarations += "void {}{{\n // {}\n // your datalink code here\n}}\n\n".format(datalink.fun_c, datalink.message)
self.src = "{}\n{}\n{}\n{}\n".format(cop, description, include, declarations)
def build_header(self, licence="GPLv2"):
cop = "/*\n * Copyright (C) {author} {email}\n{licence}\n */".format(author=self.author, email=self.email, licence=LICENCES[licence])
description = "/** @file \"modules/{dir}/{name}.h\"\n * @author {author} {email}\n * {description}\n */".format(
dir=self.directory, name=self.name, author=self.author, email=self.email, description=self.description)
includes = ""
if len(self.datalinks) > 0:
includes += "#include \"stdint.h\"\n\n"
declarations = ""
for init in self.inits:
declarations += "extern void {}(void);\n".format(init.fun)
for periodic in self.periodics:
declarations += "extern void {}(void);\n".format(periodic.fun)
if not periodic.start == "":
declarations += "extern void {}(void);\n".format(periodic.start)
if not periodic.stop == "":
declarations += "extern void {}(void);\n".format(periodic.stop)
for event in self.events:
declarations += "extern void {}(void);\n".format(event.fun)
for datalink in self.datalinks:
declarations += "extern void {};\t// {}\n".format(datalink.fun_c, datalink.message)
self.header = "{cop}\n{des}\n#ifndef {guard}_H\n#define {guard}_H\n{includes}{decl}\n#endif // {guard}_H\n".format(
cop=cop, des=description, guard=self.name.upper(), includes=includes, decl=declarations)
def build_files(self, licence="GPLv2"):
self.build_xml()
self.build_src(licence)
self.build_header(licence)
def get_filenames(self):
dir_path = "{}/sw/airborne/modules/{}".format(PPRZ_SRC, self.directory)
xml_filename = "{}/conf/modules/{}.xml".format(PPRZ_HOME, self.name)
h_filename = "{}/{}.h".format(dir_path, self.name)
c_filename = "{}/{}.c".format(dir_path, self.name)
return xml_filename, h_filename, c_filename, dir_path
def write_files(self):
xml_filename, h_filename, c_filename, dir_path = self.get_filenames()
# XML file
with open(xml_filename, 'wb') as xml_file:
xml = etree.tostring(self.xml, pretty_print=True, doctype="<!DOCTYPE module SYSTEM \"module.dtd\">")
xml_file.write(xml)
# create directory is needed
if not os.path.isdir(dir_path):
os.mkdir(dir_path)
# create C file
with open(c_filename, 'w') as c_file:
c_file.write(self.src)
# create H file
with open(h_filename, 'w') as h_file:
h_file.write(self.header)
return [xml_filename, h_filename, c_filename]
+50
View File
@@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'init_ui.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Init(object):
def setupUi(self, Init):
Init.setObjectName("Init")
Init.resize(650, 76)
self.verticalLayout = QtWidgets.QVBoxLayout(Init)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_11 = QtWidgets.QLabel(Init)
self.label_11.setStyleSheet("font: bold")
self.label_11.setAlignment(QtCore.Qt.AlignCenter)
self.label_11.setObjectName("label_11")
self.horizontalLayout.addWidget(self.label_11)
self.remove_button = QtWidgets.QToolButton(Init)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("remove.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.remove_button.setIcon(icon)
self.remove_button.setObjectName("remove_button")
self.horizontalLayout.addWidget(self.remove_button)
self.verticalLayout.addLayout(self.horizontalLayout)
self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.label_10 = QtWidgets.QLabel(Init)
self.label_10.setObjectName("label_10")
self.horizontalLayout_2.addWidget(self.label_10)
self.init_edit = QtWidgets.QLineEdit(Init)
self.init_edit.setObjectName("init_edit")
self.horizontalLayout_2.addWidget(self.init_edit)
self.verticalLayout.addLayout(self.horizontalLayout_2)
self.retranslateUi(Init)
QtCore.QMetaObject.connectSlotsByName(Init)
def retranslateUi(self, Init):
_translate = QtCore.QCoreApplication.translate
Init.setWindowTitle(_translate("Init", "Init"))
self.label_11.setText(_translate("Init", "Init"))
self.remove_button.setText(_translate("Init", "remove"))
self.label_10.setText(_translate("Init", "fun"))
+63
View File
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Init</class>
<widget class="QWidget" name="Init">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>650</width>
<height>76</height>
</rect>
</property>
<property name="windowTitle">
<string>Init</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_11">
<property name="styleSheet">
<string notr="true">font: bold</string>
</property>
<property name="text">
<string>Init</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="remove_button">
<property name="text">
<string>remove</string>
</property>
<property name="icon">
<iconset>
<normaloff>remove.svg</normaloff>remove.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label_10">
<property name="text">
<string>fun</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="init_edit"/>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+103
View File
@@ -0,0 +1,103 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'periodic_ui.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Periodic(object):
def setupUi(self, Periodic):
Periodic.setObjectName("Periodic")
Periodic.resize(699, 115)
self.verticalLayout = QtWidgets.QVBoxLayout(Periodic)
self.verticalLayout.setObjectName("verticalLayout")
self.horizontalLayout = QtWidgets.QHBoxLayout()
self.horizontalLayout.setObjectName("horizontalLayout")
self.label_11 = QtWidgets.QLabel(Periodic)
self.label_11.setStyleSheet("font: bold")
self.label_11.setAlignment(QtCore.Qt.AlignCenter)
self.label_11.setObjectName("label_11")
self.horizontalLayout.addWidget(self.label_11)
self.remove_button = QtWidgets.QToolButton(Periodic)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("remove.svg"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.remove_button.setIcon(icon)
self.remove_button.setObjectName("remove_button")
self.horizontalLayout.addWidget(self.remove_button)
self.verticalLayout.addLayout(self.horizontalLayout)
self.horizontalLayout_11 = QtWidgets.QHBoxLayout()
self.horizontalLayout_11.setObjectName("horizontalLayout_11")
self.horizontalLayout_5 = QtWidgets.QHBoxLayout()
self.horizontalLayout_5.setObjectName("horizontalLayout_5")
self.label_6 = QtWidgets.QLabel(Periodic)
self.label_6.setObjectName("label_6")
self.horizontalLayout_5.addWidget(self.label_6)
self.freq_spinbox = QtWidgets.QDoubleSpinBox(Periodic)
self.freq_spinbox.setProperty("value", 1.0)
self.freq_spinbox.setObjectName("freq_spinbox")
self.horizontalLayout_5.addWidget(self.freq_spinbox)
self.horizontalLayout_11.addLayout(self.horizontalLayout_5)
self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
self.horizontalLayout_3.setObjectName("horizontalLayout_3")
self.label_5 = QtWidgets.QLabel(Periodic)
self.label_5.setObjectName("label_5")
self.horizontalLayout_3.addWidget(self.label_5)
self.periodic_edit = QtWidgets.QLineEdit(Periodic)
self.periodic_edit.setObjectName("periodic_edit")
self.horizontalLayout_3.addWidget(self.periodic_edit)
self.horizontalLayout_11.addLayout(self.horizontalLayout_3)
self.horizontalLayout_9 = QtWidgets.QHBoxLayout()
self.horizontalLayout_9.setObjectName("horizontalLayout_9")
self.label_9 = QtWidgets.QLabel(Periodic)
self.label_9.setObjectName("label_9")
self.horizontalLayout_9.addWidget(self.label_9)
self.autorun_comboBox = QtWidgets.QComboBox(Periodic)
self.autorun_comboBox.setObjectName("autorun_comboBox")
self.autorun_comboBox.addItem("")
self.autorun_comboBox.setItemText(0, "")
self.autorun_comboBox.addItem("")
self.autorun_comboBox.addItem("")
self.horizontalLayout_9.addWidget(self.autorun_comboBox)
self.horizontalLayout_11.addLayout(self.horizontalLayout_9)
self.verticalLayout.addLayout(self.horizontalLayout_11)
self.horizontalLayout_10 = QtWidgets.QHBoxLayout()
self.horizontalLayout_10.setObjectName("horizontalLayout_10")
self.horizontalLayout_8 = QtWidgets.QHBoxLayout()
self.horizontalLayout_8.setObjectName("horizontalLayout_8")
self.label_8 = QtWidgets.QLabel(Periodic)
self.label_8.setObjectName("label_8")
self.horizontalLayout_8.addWidget(self.label_8)
self.stop_edit = QtWidgets.QLineEdit(Periodic)
self.stop_edit.setObjectName("stop_edit")
self.horizontalLayout_8.addWidget(self.stop_edit)
self.horizontalLayout_10.addLayout(self.horizontalLayout_8)
self.horizontalLayout_7 = QtWidgets.QHBoxLayout()
self.horizontalLayout_7.setObjectName("horizontalLayout_7")
self.label_7 = QtWidgets.QLabel(Periodic)
self.label_7.setObjectName("label_7")
self.horizontalLayout_7.addWidget(self.label_7)
self.start_edit = QtWidgets.QLineEdit(Periodic)
self.start_edit.setObjectName("start_edit")
self.horizontalLayout_7.addWidget(self.start_edit)
self.horizontalLayout_10.addLayout(self.horizontalLayout_7)
self.verticalLayout.addLayout(self.horizontalLayout_10)
self.retranslateUi(Periodic)
QtCore.QMetaObject.connectSlotsByName(Periodic)
def retranslateUi(self, Periodic):
_translate = QtCore.QCoreApplication.translate
Periodic.setWindowTitle(_translate("Periodic", "Periodic"))
self.label_11.setText(_translate("Periodic", "Periodic"))
self.remove_button.setText(_translate("Periodic", "remove"))
self.label_6.setText(_translate("Periodic", "Freq"))
self.label_5.setText(_translate("Periodic", "fun"))
self.label_9.setText(_translate("Periodic", "Autorun"))
self.autorun_comboBox.setItemText(1, _translate("Periodic", "TRUE"))
self.autorun_comboBox.setItemText(2, _translate("Periodic", "FALSE"))
self.label_8.setText(_translate("Periodic", "Stop"))
self.label_7.setText(_translate("Periodic", "Start"))
+147
View File
@@ -0,0 +1,147 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Periodic</class>
<widget class="QWidget" name="Periodic">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>699</width>
<height>115</height>
</rect>
</property>
<property name="windowTitle">
<string>Periodic</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label_11">
<property name="styleSheet">
<string notr="true">font: bold</string>
</property>
<property name="text">
<string>Periodic</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="remove_button">
<property name="text">
<string>remove</string>
</property>
<property name="icon">
<iconset>
<normaloff>remove.svg</normaloff>remove.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_11">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Freq</string>
</property>
</widget>
</item>
<item>
<widget class="QDoubleSpinBox" name="freq_spinbox">
<property name="value">
<double>1.000000000000000</double>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_5">
<property name="text">
<string>fun</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="periodic_edit"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>Autorun</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="autorun_comboBox">
<item>
<property name="text">
<string/>
</property>
</item>
<item>
<property name="text">
<string>TRUE</string>
</property>
</item>
<item>
<property name="text">
<string>FALSE</string>
</property>
</item>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_10">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<item>
<widget class="QLabel" name="label_8">
<property name="text">
<string>Stop</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="stop_edit"/>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="label_7">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="start_edit"/>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
+67
View File
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="50"
height="50"
viewBox="0 0 13.229167 13.229167"
version="1.1"
id="svg8"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="remove.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="5.6568543"
inkscape:cx="-22.404405"
inkscape:cy="25.675666"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1851"
inkscape:window-height="1012"
inkscape:window-x="1749"
inkscape:window-y="32"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-283.77082)">
<rect
style="fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-width:0.34138367;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect819"
width="12.886954"
height="3.2371497"
x="0.17129618"
y="288.73166"
rx="0"
ry="0" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

+4
View File
@@ -0,0 +1,4 @@
PyQt5
unidecode
lxml