From c7c9403d1f67c29bd78e9482ab63c8a5a4112208 Mon Sep 17 00:00:00 2001 From: Enrico Faulhaber Date: Wed, 24 Jul 2019 14:02:00 +0200 Subject: [PATCH] Add TextType to ease gui generation TextType is intended for formatted text (multiple lines), whereas StringType is intended for a single line of text (without '\n') Change-Id: Ibce29ae6b4e426bd8685f2cf7ff6966d81b0c6aa Reviewed-on: https://forge.frm2.tum.de/review/20951 Tested-by: JenkinsCodeReview Reviewed-by: Enrico Faulhaber --- secop/datatypes.py | 16 +++++++++++++++- secop/gui/valuewidgets.py | 22 ++++++++++++++++++++-- test/test_datatypes.py | 23 ++++++++++++++++++++++- 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/secop/datatypes.py b/secop/datatypes.py index d55fbb1..c1c73ac 100644 --- a/secop/datatypes.py +++ b/secop/datatypes.py @@ -408,7 +408,7 @@ class StringType(DataType): def __init__(self, minsize=0, maxsize=None): if maxsize is None: - maxsize = minsize or 255*256 + maxsize = minsize or 100 self.minsize = int(minsize) self.maxsize = int(maxsize) if self.minsize < 0: @@ -456,6 +456,20 @@ class StringType(DataType): return repr(value) +# TextType is a special StringType intended for longer texts (i.e. embedding \n), +# whereas StringType is supposed to not contain '\n' +# unfortunately, SECoP makes no distinction here.... +# note: content is supposed to follow the format of a git commit message, i.e. a line of text, 2 '\n' + a longer explanation +class TextType(StringType): + def __init__(self, maxsize=None): + if maxsize is None: + maxsize = 8000 + super(TextType, self).__init__(0, maxsize) + + def __repr__(self): + return u'TextType(%d, %d)' % (self.minsize, self.maxsize) + + # Bool is a special enum class BoolType(DataType): default = False diff --git a/secop/gui/valuewidgets.py b/secop/gui/valuewidgets.py index 1d754f1..7939832 100644 --- a/secop/gui/valuewidgets.py +++ b/secop/gui/valuewidgets.py @@ -24,9 +24,10 @@ from __future__ import division, print_function from secop.datatypes import ArrayOf, BLOBType, BoolType, EnumType, \ - FloatRange, IntRange, StringType, StructOf, TupleOf + FloatRange, IntRange, StringType, StructOf, TupleOf, TextType from secop.gui.qt import QCheckBox, QComboBox, QDialog, QDoubleSpinBox, \ - QFrame, QGridLayout, QGroupBox, QLabel, QLineEdit, QSpinBox, QVBoxLayout + QFrame, QGridLayout, QGroupBox, QLabel, QLineEdit, QSpinBox, QVBoxLayout, \ + QTextEdit from secop.gui.util import loadUi # XXX: implement live validators !!!! @@ -46,10 +47,26 @@ class StringWidget(QLineEdit): self.setText(value) +class TextWidget(QTextEdit): + def __init__(self, datatype, readonly=False, parent=None): + super(TextWidget, self).__init__(parent) + self.datatype = datatype + if readonly: + self.setEnabled(False) + + def get_value(self): + res = self.text() + return self.datatype(res) + + def set_value(self, value): + self.setText(value) + + class BlobWidget(StringWidget): # XXX: make an editable hex-table ? pass + # or derive from widget and switch between combobox and radiobuttons? class EnumWidget(QComboBox): def __init__(self, datatype, readonly=False, parent=None): @@ -202,6 +219,7 @@ def get_widget(datatype, readonly=False, parent=None): return {FloatRange: FloatWidget, IntRange: IntWidget, StringType: StringWidget, + TextType: TextWidget, BLOBType: BlobWidget, EnumType: EnumWidget, BoolType: BoolWidget, diff --git a/test/test_datatypes.py b/test/test_datatypes.py index d7176d1..a34bc64 100644 --- a/test/test_datatypes.py +++ b/test/test_datatypes.py @@ -28,7 +28,7 @@ import pytest from secop.datatypes import ArrayOf, BLOBType, BoolType, \ DataType, EnumType, FloatRange, IntRange, ProgrammingError, \ - ScaledInteger, StringType, StructOf, TupleOf, get_datatype, CommandType + ScaledInteger, StringType, TextType, StructOf, TupleOf, get_datatype, CommandType def copytest(dt): @@ -261,6 +261,27 @@ def test_StringType(): assert dt.format_value(u'abcd') == u"u'abcd'" +def test_TextType(): + # test constructor catching illegal arguments + dt = TextType(12) + assert dt.export_datatype() == [u'string', {u'min':0, u'max':12}] + + with pytest.raises(ValueError): + dt(9) + with pytest.raises(ValueError): + dt(u'abcdefghijklmno') + with pytest.raises(ValueError): + dt('abcdefg\0') + assert dt('ab\n\ncd\n') == b'ab\n\ncd\n' + assert dt(b'ab\n\ncd\n') == b'ab\n\ncd\n' + assert dt(u'ab\n\ncd\n') == b'ab\n\ncd\n' + + assert dt.export_value('abcd') == b'abcd' + assert dt.export_value(b'abcd') == b'abcd' + assert dt.export_value(u'abcd') == b'abcd' + assert dt.import_value(u'abcd') == u'abcd' + + def test_BoolType(): # test constructor catching illegal arguments dt = BoolType()