From 34928c1b9e531ba558b74617d3cacfe46c1ecb04 Mon Sep 17 00:00:00 2001 From: Florent Gallaire Date: Wed, 1 Jun 2016 01:15:07 +0200 Subject: [PATCH 1/3] Add 'addfield' feature (for QLineEdit) --- examples/advanced.py | 1 + formlayout.py | 91 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 87 insertions(+), 5 deletions(-) diff --git a/examples/advanced.py b/examples/advanced.py index 5adae4e..603d500 100644 --- a/examples/advanced.py +++ b/examples/advanced.py @@ -16,6 +16,7 @@ def create_datalist_example(): test = [('str *', 'this is a string'), + ('str +', 'how many strings ?'), ('str_m *', """this is a MULTILINE string"""), diff --git a/formlayout.py b/formlayout.py index 7135620..ab15e06 100644 --- a/formlayout.py +++ b/formlayout.py @@ -294,6 +294,68 @@ def setStyleSheet(self, style): btn.setStyleSheet(style) +class PlusLayout(QVBoxLayout): + """Field with a '+' PushButton in a QVBoxLayout""" + def __init__(self, field, value, parent=None): + QVBoxLayout.__init__(self) + self.field = field + self.value = value + self.style = '' + hbox = QHBoxLayout() + plusbtn = QPushButton('+') + plusbtn.setFixedSize(20, 20) + plusbtn.clicked.connect(self.addfield) + hbox.addWidget(self.field) + hbox.addWidget(plusbtn) + self.addLayout(hbox) + + def addfield(self): + if isinstance(self.field, QLineEdit): + if self.value == 'password': + field = QLineEdit() + field.setEchoMode(QLineEdit.Password) + else: + field = QLineEdit(self.value) + hbox = MoinsLayout(field, self) + self.addLayout(hbox) + + def items(self): + items = [to_text_string(self.field.text())] + for i in range(1, self.count()): + items.append(to_text_string(self.itemAt(i).field.text())) + if len(items) == 1: + return items[0] + return items + + def setStyleSheet(self, style): + self.style = style + self.field.setStyleSheet(self.style) + for i in range(1, self.count()): + self.itemAt(i).setStyleSheet(self.style) + + +class MoinsLayout(QHBoxLayout): + """Field with a '-' PushButton""" + def __init__(self, field, parent=None): + QHBoxLayout.__init__(self) + self.field = field + self.parent = parent + self.moinsbtn = QPushButton('-') + self.moinsbtn.setFixedSize(20, 20) + self.moinsbtn.clicked.connect(self.removefield) + self.addWidget(self.field) + self.addWidget(self.moinsbtn) + self.setStyleSheet(parent.style) + + def removefield(self): + self.field.close() + self.moinsbtn.close() + self.parent.removeItem(self) + + def setStyleSheet(self, style): + self.field.setStyleSheet(style) + + def font_is_installed(font): """Check if font is installed""" return [fam for fam in QFontDatabase().families() @@ -524,6 +586,15 @@ def setup(self): field.setTime(value) else: field = QLineEdit(repr(value), self) + + # Eventually catching the 'addfield' feature and processing it + if label.endswith(' +'): + label = label[:-2] + if isinstance(field, QLineEdit) and is_text_string(value): + field = PlusLayout(field, value) + else: + print("Warning: '%s' doesn't support 'addfield' feature"\ + % label, file=STDERR) # Eventually extracting tooltip from label and processing it index = label.find('::') @@ -587,6 +658,10 @@ def get(self): if label is None: # Separator / Comment continue + if label.endswith(' +'): + label = label[:-2] + if isinstance(field, PlusLayout): + value = field.items() elif tuple_to_qfont(value) is not None: value = field.get_font() elif is_text_string(value): @@ -659,12 +734,18 @@ def get(self): if label.endswith(' *'): label = label[:-2] required = 'true' - child = ET.SubElement(form, label) - if isinstance(value, datetime.datetime): - child.text = value.isoformat() + if isinstance(value, list): + for v in value: + child = ET.SubElement(form, label) + child.text = str(v) + child.attrib['required'] = required else: - child.text = str(value) - child.attrib['required'] = required + child = ET.SubElement(form, label) + if isinstance(value, datetime.datetime): + child.text = value.isoformat() + else: + child.text = str(value) + child.attrib['required'] = required return ET.tostring(form) From 21a98673bfc21dda023181fb619285c4b746e377 Mon Sep 17 00:00:00 2001 From: Florent Gallaire Date: Wed, 1 Jun 2016 18:32:27 +0200 Subject: [PATCH 2/3] Add 'addfield' feature (for QComboBox) --- examples/advanced.py | 3 ++- formlayout.py | 50 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/examples/advanced.py b/examples/advanced.py index 603d500..b538975 100644 --- a/examples/advanced.py +++ b/examples/advanced.py @@ -16,12 +16,13 @@ def create_datalist_example(): test = [('str *', 'this is a string'), - ('str +', 'how many strings ?'), + ('str +', 'this is a string'), ('str_m *', """this is a MULTILINE string"""), ('file *', 'file'), ('list *', [0, '1', '3', '4']), + ('list +', [0, '1', '3', '4']), ('tuple *', (0, '1', '3', '4')), ('list2', ['--', ('none', 'None'), ('--', 'Dashed'), ('-.', 'DashDot'), ('-', 'Solid'), diff --git a/formlayout.py b/formlayout.py index ab15e06..fd7ae70 100644 --- a/formlayout.py +++ b/formlayout.py @@ -296,11 +296,14 @@ def setStyleSheet(self, style): class PlusLayout(QVBoxLayout): """Field with a '+' PushButton in a QVBoxLayout""" - def __init__(self, field, value, parent=None): + def __init__(self, field, value, save_value, parent=None): QVBoxLayout.__init__(self) self.field = field self.value = value + self.save_value = save_value self.style = '' + if isinstance(self.field, QComboBox): + self.index = field.currentIndex() hbox = QHBoxLayout() plusbtn = QPushButton('+') plusbtn.setFixedSize(20, 20) @@ -316,16 +319,42 @@ def addfield(self): field.setEchoMode(QLineEdit.Password) else: field = QLineEdit(self.value) + elif isinstance(self.field, QComboBox): + field = QComboBox() + field.addItems(self.value) + field.setCurrentIndex(self.index) hbox = MoinsLayout(field, self) self.addLayout(hbox) def items(self): - items = [to_text_string(self.field.text())] - for i in range(1, self.count()): - items.append(to_text_string(self.itemAt(i).field.text())) - if len(items) == 1: - return items[0] - return items + if is_text_string(self.save_value): + items = [to_text_string(self.field.text())] + for i in range(1, self.count()): + items.append(to_text_string(self.itemAt(i).field.text())) + if len(items) == 1: + return items[0] + return items + elif isinstance(self.save_value, list): + index = self.field.currentIndex() + if isinstance(self.save_value[0], int): + value = index + 1 + else: + value = self.save_value[index+1] + if isinstance(value, (list, tuple)): + value = value[0] + items = [value] + for i in range(1, self.count()): + index = self.itemAt(i).field.currentIndex() + if isinstance(self.save_value[0], int): + v = index + 1 + else: + v = self.save_value[index+1] + if isinstance(v, (list, tuple)): + v = v[0] + items.append(v) + if len(items) == 1: + return items[0] + return items def setStyleSheet(self, style): self.style = style @@ -489,6 +518,7 @@ def get_dialog(self): def setup(self): for label, value in self.data: + save_value = value if DEBUG_FORMLAYOUT: print("value:", value) if label is None and value is None: @@ -533,7 +563,6 @@ def setup(self): else: field = QLineEdit(value, self) elif isinstance(value, (list, tuple)): - save_value = value value = list(value) # always needed to protect self.data selindex = value.pop(0) if isinstance(selindex, int): @@ -590,8 +619,9 @@ def setup(self): # Eventually catching the 'addfield' feature and processing it if label.endswith(' +'): label = label[:-2] - if isinstance(field, QLineEdit) and is_text_string(value): - field = PlusLayout(field, value) + if isinstance(field, QLineEdit) and is_text_string(value) or\ + isinstance(field, QComboBox): + field = PlusLayout(field, value, save_value) else: print("Warning: '%s' doesn't support 'addfield' feature"\ % label, file=STDERR) From c3188ec2da81e4953b2ee22ebc4d5fc492994722 Mon Sep 17 00:00:00 2001 From: Florent Gallaire Date: Wed, 1 Jun 2016 22:15:04 +0200 Subject: [PATCH 3/3] Simplify items() code --- formlayout.py | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/formlayout.py b/formlayout.py index fd7ae70..97d4e17 100644 --- a/formlayout.py +++ b/formlayout.py @@ -328,33 +328,25 @@ def addfield(self): def items(self): if is_text_string(self.save_value): - items = [to_text_string(self.field.text())] - for i in range(1, self.count()): - items.append(to_text_string(self.itemAt(i).field.text())) - if len(items) == 1: - return items[0] - return items + items = [to_text_string(self.field.text())] +\ + [to_text_string(self.itemAt(i).field.text())\ + for i in range(1, self.count())] elif isinstance(self.save_value, list): - index = self.field.currentIndex() - if isinstance(self.save_value[0], int): - value = index + 1 - else: - value = self.save_value[index+1] - if isinstance(value, (list, tuple)): - value = value[0] - items = [value] - for i in range(1, self.count()): - index = self.itemAt(i).field.currentIndex() + indexes = [self.field.currentIndex()] +\ + [self.itemAt(i).field.currentIndex()\ + for i in range(1, self.count())] + items = [] + for index in indexes: if isinstance(self.save_value[0], int): - v = index + 1 + value = index + 1 else: - v = self.save_value[index+1] - if isinstance(v, (list, tuple)): - v = v[0] - items.append(v) - if len(items) == 1: - return items[0] - return items + value = self.save_value[index+1] + if isinstance(value, (list, tuple)): + value = value[0] + items.append(value) + if len(items) == 1: + return items[0] + return items def setStyleSheet(self, style): self.style = style