frappy/secop/gui/cfg_editor/tree_widget_item.py
Markus Zolliker 41ce909172 update to changes from mlz repo
- bug fixes in error.py
- add from * to raise statements
- fix py35 compatibility
- finalize omit_unchanged_within feature
- fix follwup bug (missing Param.override) in proxy.py

Change-Id: I621c01a0d5e1ec6696fb06f39666f3316fb53649
2021-11-10 13:44:14 +01:00

224 lines
8.5 KiB
Python

# -*- coding: utf-8 -*-
# *****************************************************************************
#
# This program 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 of the License, or (at your option) any later
# version.
#
# This program 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
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Module authors:
# Sandra Seger <sandra.seger@frm2.tum.de>
#
# *****************************************************************************
from secop.gui.cfg_editor.utils import loadUi, \
set_name_edit_style, setIcon, setTreeIcon
from secop.gui.qt import QDialog, QFont, QHBoxLayout, \
QLabel, QPushButton, QSize, QSizePolicy, QTextEdit, \
QTreeWidgetItem, QVBoxLayout, QWidget, pyqtSignal
from secop.gui.valuewidgets import get_widget
from secop.properties import Property
NODE = 'node'
INTERFACE = 'interface'
MODULE = 'module'
PARAMETER = 'parameter'
PROPERTY = 'property'
COMMENT = 'comment'
class TreeWidgetItem(QTreeWidgetItem):
def __init__(self, kind=None, name='', value=None, class_object=None,
parameters=None, properties=None, parent=None):
"""object_class: for interfaces and modules = class
for parameter and properties = their objects
the datatype passed onto ValueWidget should be on of secop.datatypes"""
# TODO: like stated in docstring the datatype for parameters and
# properties must be found out through their object
super().__init__(parent)
self.kind = kind
self.name = name
self.class_object = class_object
self.parameters = parameters or {}
self.properties = properties or {}
if self.kind and self.kind != 'node':
setTreeIcon(self, '%s.png' % self.kind)
else:
setTreeIcon(self, 'empty.png')
font = QFont()
font.setWeight(QFont.Bold)
self.setFont(0, font)
self.setText(0, self.name)
self.duplicates = 0
datatype = None if type(class_object) != Property else \
class_object.datatype
self.widget = ValueWidget(name, value, datatype, kind)
if kind in [NODE, MODULE, INTERFACE]:
self.widget.edit_btn.clicked.connect(self.change_name)
def addChild(self, item):
QTreeWidgetItem.addChild(self, item)
item.setExpanded(True)
def duplicate(self):
self.duplicates += 1
duplicate = TreeWidgetItem(self.kind, '%s_%i' % (self.name,
self.duplicates), self.get_value(),
self.class_object)
self.parent().addChild(duplicate)
for i in range(self.childCount()):
child = self.child(i)
duplicate.addChild(TreeWidgetItem(child.kind,
child.name, child.widget.get_value()))
for k in range(child.childCount()):
sub_child = child.child(k)
duplicate.child(i).addChild(TreeWidgetItem(sub_child.kind,
sub_child.name,
sub_child.widget.get_value(),
sub_child.datatype))
def set_name(self, name):
self.name = name
self.setText(0, self.name)
self.widget.set_name(name)
def get_value(self):
return self.widget.get_value()
def set_value(self, value):
self.widget.set_value(value)
def set_class_object(self, class_obj, value=''):
# TODO: should do stuff here if module or interface class is changed or
# datatype
self.class_object = class_obj
datatype = None if type(self.class_object) != Property else \
self.class_object.datatype
self.widget.set_datatype(datatype, value)
def get_children_names(self):
children = []
for i in range(0, self.childCount()):
children.append(self.child(i).name)
return children
def change_name(self):
if self.parent():
invalid_names = self.parent().get_children_names()
invalid_names.remove(self.name)
else:
invalid_names = ['']
dialog = ChangeNameDialog(self.name, invalid_names)
new_name = dialog.get_values()
if new_name:
self.set_name(new_name)
class ValueWidget(QWidget):
save_status_changed = pyqtSignal(bool)
def __init__(self, name='', value='', datatype=None, kind='', parent=None):
# TODO: implement: change module/interface class
super().__init__(parent)
self.datatype = datatype
self.layout = QVBoxLayout()
self.name_label = QLabel(name)
self.name_label.setStyleSheet('font-weight: bold')
self.kind = kind
if self.kind in [NODE, MODULE, INTERFACE]:
self.edit_btn = QPushButton()
setIcon(self.edit_btn, 'edit.png')
self.edit_btn.setIconSize(QSize(18, 18))
self.edit_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
self.edit_btn.setFlat(True)
layout = QHBoxLayout()
layout.addWidget(self.name_label)
layout.addWidget(self.edit_btn)
self.layout.addLayout(layout)
else:
self.layout.addWidget(self.name_label)
# TODO value_display.valueChanged.connect(emit_save_status_changed) ->
# implement or map a valueChanged signal for all possible
# value_displays:
# String = QLineEdit = textChanged
# Enum = QComboBox = editTextChanged
# Bool = QCheckBox = stateChanged
# Int, Float = Q(Double)SpinBox = ValueChanged
# Struct, Array = QGroupBox = clicked
# Tuple = QFrame = ???
if self.kind == PROPERTY and datatype and name != 'datatype':
# TODO what to do if property is datatype
self.value_display = get_widget(datatype)
self.value_display.set_value(value)
elif self.kind in [NODE, COMMENT]:
self.value_display = QTextEdit()
self.value_display.text = self.value_display.toPlainText
self.value_display.setText = self.value_display.setPlainText
self.value_display.textChanged.connect(self.emit_save_status_changed)
self.set_value(value)
else:
self.value_display = QLabel(value)
self.layout.addWidget(self.value_display)
self.setLayout(self.layout)
def get_value(self):
if self.datatype:
return self.value_display.get_value()
return self.value_display.text()
def set_value(self, value):
# TODO try block
if self.datatype:
self.value_display.set_value(value)
else:
self.value_display.setText(value)
def set_name(self, name):
if name != self.name_label.text():
self.emit_save_status_changed(False)
self.name_label.setText(name)
def set_datatype(self, datatype, value=''):
if datatype == self.datatype:
return
# TODO: remove old value_display
self.datatype = datatype
if self.kind == PROPERTY and datatype:
self.value_display = get_widget(datatype)
self.value_display.set_value(value)
else:
self.value_display = QLabel(value)
def emit_save_status_changed(self, status=False):
self.save_status_changed.emit(status)
class ChangeNameDialog(QDialog):
def __init__(self, current_name='', invalid_names=None, parent=None):
super().__init__(parent)
loadUi(self, 'change_name_dialog.ui')
self.invalid_names = invalid_names
self.name.setText(current_name)
self.name.selectAll()
# TODO: input mask
self.name.textChanged.connect(self.check_input)
def get_values(self):
if self.exec_() == QDialog.Accepted:
return self.name.text()
return None
def check_input(self, name):
set_name_edit_style(name in self.invalid_names or name == '', self.name,
self.button_box)