schainGUI
324 lines
| 11.2 KiB
| text/plain
|
TextLexer
|
r577 | #!/usr/bin/env python | |
|
r1102 | import os | |
import sys | |||
|
r1288 | import ast | |
from schainpy.controller import Project | |||
from schainpy.cli import cli | |||
|
r1102 | from schainpy.utils import log | |
try: | |||
|
r1288 | import kivy | |
from kivy.app import App | |||
from kivy.uix.label import Label | |||
from kivy.uix.boxlayout import BoxLayout | |||
from kivy.uix.gridlayout import GridLayout | |||
from kivy.uix.textinput import TextInput | |||
from kivy.uix.button import Button | |||
from kivy.uix.dropdown import DropDown | |||
from kivy.uix.togglebutton import ToggleButton | |||
from kivy.uix.popup import Popup | |||
from kivy.uix.filechooser import FileChooserListView | |||
|
r1102 | except: | |
log.error( | |||
|
r1288 | 'You should install kivy module in order to run the GUI.') | |
|
r1102 | sys.exit() | |
|
r577 | ||
|
r1288 | DEFAULTS = { | |
'path': os.path.expanduser('~'), | |||
'startDate': '2018/01/01', | |||
'endDate': '2020/01/01', | |||
'startTime': '00:00:00', | |||
'endTime': '23:59:59', | |||
'online': '1', | |||
'delay': '30', | |||
'walk': '1', | |||
'show': '1', | |||
'zmin': '10', | |||
'zmax': '40', | |||
} | |||
class MainLayout(BoxLayout): | |||
def __init__(self, **kwargs): | |||
super(MainLayout, self).__init__(**kwargs) | |||
self.workspace = os.path.join(os.path.expanduser('~'), 'workspace/scripts') | |||
self.current_unit_id = None | |||
self._units = [] | |||
self.project = Project() | |||
self.project.setup(id='1', name='test', description='') | |||
self.sidebar_left = BoxLayout(orientation='vertical', size_hint_x=0.4, spacing=5) | |||
self.body = BoxLayout(orientation='vertical', spacing=5) | |||
self.sidebar_right = BoxLayout(orientation='vertical', size_hint_x=0.6, spacing=5) | |||
bt_prj = Button(text='Project') | |||
bt_prj.bind(on_press=self.show_project) | |||
self.sidebar_left.add_widget(bt_prj) | |||
bt_add_unit = Button(text='Add Unit') | |||
bt_add_unit.bind(on_press=self.select_unit) | |||
self.sidebar_left.add_widget(bt_add_unit) | |||
bt_add_operation = Button(text='Add Operation') | |||
bt_add_operation.bind(on_press=self.select_operation) | |||
self.sidebar_left.add_widget(bt_add_operation) | |||
bt_import = Button(text='Import') | |||
bt_import.bind(on_press=self.load) | |||
self.sidebar_left.add_widget(bt_import) | |||
bt_export = Button(text='Export') | |||
bt_export.bind(on_press=self.export) | |||
self.sidebar_left.add_widget(bt_export) | |||
bt_run = Button(text='Run') | |||
bt_run.bind(on_press=self.run) | |||
self.sidebar_left.add_widget(bt_run) | |||
bt_stop = Button(text='Stop') | |||
bt_stop.bind(on_press = self.stop) | |||
self.sidebar_left.add_widget(bt_stop) | |||
bt_exit = Button(text = 'Exit', height = 40, size_hint_y = None, background_color=(1, 0, 0, 1)) | |||
bt_exit.bind(on_press=App.get_running_app().stop) | |||
self.sidebar_left.add_widget(bt_exit) | |||
self.add_widget(self.sidebar_left) | |||
self.add_widget(self.body) | |||
self.add_widget(self.sidebar_right) | |||
def update_body(self): | |||
self._units = [] | |||
self.body.clear_widgets() | |||
self.sidebar_right.clear_widgets() | |||
for unit in self.project.getUnits(): | |||
box = GridLayout(cols=3) | |||
bt = ToggleButton(text=unit.name, group='units') | |||
bt._obj = unit | |||
bt.bind(on_press=self.show_parameters) | |||
box.add_widget(bt) | |||
self._units.append(bt) | |||
for operation in unit.operations: | |||
bt_op = Button(text = operation.name, background_color=(1, 0.5, 0, 1)) | |||
bt_op._id = unit.id | |||
bt_op._obj = operation | |||
bt_op.bind(on_press=self.show_parameters) | |||
box.add_widget(bt_op) | |||
self.body.add_widget(box) | |||
print(self.project) | |||
def show_parameters(self, instance): | |||
obj = instance._obj | |||
self.current_unit_id = obj.id | |||
self.sidebar_right.clear_widgets() | |||
if obj and obj.parameters: | |||
self._params = {} | |||
for key, value in obj.getParameters().items(): | |||
self.sidebar_right.add_widget(Label(text=key)) | |||
text = TextInput(text=value, multiline=False) | |||
self._params[key] = text | |||
self.sidebar_right.add_widget(text) | |||
bt_save = Button(text = 'Save', height = 40, size_hint_y = None, background_color=(0, 1, 0, 1)) | |||
bt_save._obj = obj | |||
if hasattr(instance, '_id'): | |||
bt_save._id = instance._id | |||
self.current_unit_id = None | |||
bt_save.bind(on_press=self.save_parameters) | |||
self.sidebar_right.add_widget(bt_save) | |||
bt_delete = Button(text = 'Delete', height = 40, size_hint_y = None, background_color=(1, 0, 0, 1)) | |||
bt_delete._obj = obj | |||
if hasattr(instance, '_id'): | |||
bt_delete._id = instance._id | |||
self.current_unit_id = obj.id | |||
bt_delete.bind(on_press=self.delete_object) | |||
self.sidebar_right.add_widget(bt_delete) | |||
def save_parameters(self, instance): | |||
obj = instance._obj | |||
params = {} | |||
for key in self._params: | |||
if self._params[key]: | |||
params[key] = self._params[key].text | |||
if hasattr(instance, '_id'): | |||
unit = self.project.getProcUnit(instance._id) | |||
op = unit.getOperation(obj.id) | |||
op.update(**params) | |||
else: | |||
unit = self.project.getProcUnit(obj.id) | |||
unit.update(**params) | |||
def delete_object(self, instance): | |||
obj = instance._obj | |||
if hasattr(instance, '_id'): | |||
unit = self.project.getProcUnit(instance._id) | |||
unit.removeOperation(obj.id) | |||
else: | |||
self.project.removeProcUnit(obj.id) | |||
self.project.updateId(self.project.id) | |||
self.update_body() | |||
def show_project(self, instance): | |||
self.sidebar_right.clear_widgets() | |||
self._params = {} | |||
for label in ['Id', 'Name', 'Description']: | |||
self.sidebar_right.add_widget(Label(text=label)) | |||
text = TextInput(text=getattr(self.project, label.lower()), multiline=False) | |||
self._params[label] = text | |||
self.sidebar_right.add_widget(text) | |||
self.sidebar_right.add_widget(Label(text='Workspace')) | |||
text = TextInput(text=getattr(self, 'workspace'), multiline=False) | |||
self._params['Workspace'] = text | |||
self.sidebar_right.add_widget(text) | |||
bt_save = Button(text = 'Save', height = 40, size_hint_y = None, background_color=(0, 1, 0, 1)) | |||
bt_save.bind(on_press = self.save_project_parameters) | |||
self.sidebar_right.add_widget(bt_save) | |||
def save_project_parameters(self, instance): | |||
for label in ['Id', 'Name', 'Description']: | |||
setattr(self.project, label.lower(), self._params[label].text) | |||
setattr(self, 'workspace', self._params['Workspace'].text) | |||
def select_unit(self, instance): | |||
self.sidebar_right.clear_widgets() | |||
bt_main = Button(text = 'Select Unit', height = 40, size_hint_y = None) | |||
dropdown = DropDown() | |||
for unit in cli.getProcs(): | |||
btn = Button(text = unit, size_hint_y = None, height = 40) | |||
btn.bind(on_release = lambda btn: dropdown.select(btn.text)) | |||
dropdown.add_widget(btn) | |||
bt_main.bind(on_release = dropdown.open) | |||
dropdown.bind(on_select = lambda instance, x: setattr(bt_main, 'text', x)) | |||
bt_add = Button(text = 'Add', height = 40, size_hint_y = None, background_color=(0, 1, 0, 1)) | |||
bt_add.bind(on_press = lambda instance: self.add_unit(bt_main.text)) | |||
self.sidebar_right.add_widget(bt_main) | |||
self.sidebar_right.add_widget(bt_add) | |||
def add_unit(self, s): | |||
if s: | |||
if 'Reader' in s: | |||
unit = self.project.addReadUnit(name=s) | |||
else: | |||
*_, last = self.project.getUnits() | |||
unit = self.project.addProcUnit(name=s, inputId=last.id) | |||
keys = cli.getArgs(unit.name) | |||
values = [DEFAULTS[key] if key in DEFAULTS else '' for key in keys] | |||
unit.update(**dict(zip(keys, values))) | |||
self.update_body() | |||
def select_operation(self, instance): | |||
self.sidebar_right.clear_widgets() | |||
btns = [bt.state == 'down' for bt in self._units] | |||
if True in btns: | |||
bt_main = Button(text = 'Select Operation', height = 40, size_hint_y = None) | |||
dropdown = DropDown() | |||
for unit in cli.getOperations(): | |||
btn = Button(text = unit, size_hint_y = None, height = 40) | |||
btn.bind(on_release = lambda btn: dropdown.select(btn.text)) | |||
dropdown.add_widget(btn) | |||
bt_main.bind(on_release = dropdown.open) | |||
dropdown.bind(on_select = lambda instance, x: setattr(bt_main, 'text', x)) | |||
bt_add = Button(text = 'Add', height = 40, size_hint_y = None, background_color=(0, 1, 0, 1)) | |||
bt_add.bind(on_press = lambda instance: self.add_operation(bt_main.text)) | |||
self.sidebar_right.add_widget(bt_main) | |||
self.sidebar_right.add_widget(bt_add) | |||
else: | |||
self.sidebar_right.add_widget(Label(text='Select Unit')) | |||
def add_operation(self, s): | |||
if s: | |||
unit = self.project.getProcUnit(self.current_unit_id) | |||
op = unit.addOperation(name=s) | |||
keys = cli.getArgs(op.name) | |||
values = [DEFAULTS[key] if key in DEFAULTS else '' for key in keys] | |||
op.update(**dict(zip(keys, values))) | |||
self.update_body() | |||
def run(self, instance): | |||
if self.project and self.project.is_alive(): | |||
self.sidebar_right.clear_widgets() | |||
self.sidebar_right.add_widget(Label(text='Project running')) | |||
else: | |||
if self.project.exitcode is None: | |||
self.project.start() | |||
else: | |||
self.project = self.project.clone() | |||
self.project.start() | |||
def stop(self, instance): | |||
if self.project and self.project.is_alive(): | |||
self.project.kill() | |||
log.error('Project Stopped by user', 'GUI') | |||
else: | |||
self.sidebar_right.clear_widgets() | |||
self.sidebar_right.add_widget(Label(text='Project not running')) | |||
def load(self, instance): | |||
self.sidebar_right.clear_widgets() | |||
textinput = FileChooserListView( | |||
path=self.workspace, size_hint=(1, 1), dirselect=False, filters=['*.xml']) | |||
|
r1102 | ||
|
r1288 | self.sidebar_right.add_widget(textinput) | |
bt_open = Button(text = 'Open', height = 40, size_hint_y = None, background_color=(0, 1, 0, 1)) | |||
bt_open.textinput = textinput | |||
bt_open.bind(on_press = self.load_file) | |||
self.sidebar_right.add_widget(bt_open) | |||
def load_file(self, instance): | |||
|
r1102 | ||
|
r1288 | self.project.readXml(instance.textinput.selection[0]) | |
self.update_body() | |||
|
r1102 | ||
|
r1288 | def export(self, instance): | |
|
r1102 | ||
|
r1288 | filename = os.path.join(self.workspace, '{}.xml'.format(self.project.name)) | |
self.project.writeXml(filename) | |||
log.success('File created: {}'.format(filename), 'GUI') | |||
|
r1102 | ||
|
r1288 | class SignalChainApp(App): | |
def build(self): | |||
return MainLayout(spacing=10) | |||
|
r1102 | ||
|
r577 | if __name__ == "__main__": | |
|
r1288 | SignalChainApp().run() |