Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions examples/Treè vîew.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"Name": "QuickForm",
"Authors":
{"french" : {"old": "Pièrre", "new": "Flôrent"},
"english" : [
{"Brit" : ["John", "Andrew"]},
{"US" : [
"Tim",
{"William" : ["Will","Bill"]}
]
}
]
},
"Python": {"old": "2", "new": "3"}
}
2 changes: 2 additions & 0 deletions examples/Treè vîew.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version='1.0' encoding='UTF-8'?>
<Root><Name><b>Q<i>uîck</i>For</b>m</Name><Empty/><Authors quality='high' sort='language'><french number='1'>Pièrre</french><french number='2'>Flôrent</french><english><Brit>John</Brit><Brit>Andrew</Brit><US>Tim</US><US><William>Will</William><William>Bill</William></US></english></Authors><Python>2</Python><Python>3</Python></Root>
1 change: 1 addition & 0 deletions examples/Treè vîew_Node content.json
1 change: 1 addition & 0 deletions examples/Treè vîew_Node content.xml
37 changes: 37 additions & 0 deletions examples/tree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
#
# Copyright © 2009 Pierre Raybaut
# Licensed under the terms of the MIT License
# (see formlayout.py for details)

"""
Tree examples
"""

from formlayout import fedit

datalist = [('dict:', {"Name": "QuickForm",
"Authors":
{"french" : [u"Pièrre", u"Flôrent"],
"english" : [
{"Brit" : ["John", "Andrew"]},
{"US" : [
"Tim",
{"William" : ["Will","Bill"]}
]
}
]
},
"Python": ["2", "3"]
}),
(None, 'JSON tree:'),
(None, u'Treè vîew.json'),
(None, 'JSON tree + content:'),
(None, u'Treè vîew_Node content.json'),
(None, 'XML tree:'),
(None, u'Treè vîew.xml'),
(None, 'XML tree + content:'),
(None, u'Treè vîew_Node content.xml')
]

print('result:', fedit(datalist, title='Tree examples', type='questions'))
151 changes: 151 additions & 0 deletions formlayout.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,119 @@ def apply(self, callback):
self.dialog.formwidget.get_widgets())


class DictTreeModel(QStandardItemModel):
def __init__(self, data, header=[], parent=None):
QStandardItemModel.__init__(self, parent)
self.ficon = qApp.style().standardIcon(QStyle.SP_FileIcon)
self.dicon = qApp.style().standardIcon(QStyle.SP_DirIcon)
self.columns = False
if len(header) > 0:
self.setHorizontalHeaderLabels(header)
if len(header) > 1:
self.columns = True
parent = self.invisibleRootItem()
self.add(data, parent)

def add(self, data, parent):
if isinstance(data, dict):
for key, value in data.items():
item = QStandardItem(key)
parent.appendRow(item)
if self.columns and not isinstance(value, (dict,list)):
item.setIcon(self.ficon)
leaf = QStandardItem(value)
parent.setChild(self.indexFromItem(item).row(), 1, leaf)
else:
item.setIcon(self.dicon)
self.add(value, item)
elif isinstance(data, list):
for el in data:
self.add(el, parent)
else:
item = QStandardItem(data)
item.setIcon(self.ficon)
parent.appendRow(item)

def value(self):
parent = self.invisibleRootItem()
return self.addvalue(parent)

def addvalue(self, parent):
children, ret = [], {}
for i in range(parent.rowCount()):
child = parent.child(i)
if child.hasChildren():
key = to_text_string(child.text())
ret[key] = self.addvalue(child)
else:
children.append(to_text_string(child.text()))
if ret and not children:
return ret
elif ret:
return children + [ret]
elif len(children) == 1:
return children[0]
else:
return children


class XMLTreeModel(QStandardItemModel):
def __init__(self, xmldata, header=[], parent=None):
QStandardItemModel.__init__(self, parent)
self.ficon = qApp.style().standardIcon(QStyle.SP_FileIcon)
self.dicon = qApp.style().standardIcon(QStyle.SP_DirIcon)
self.columns = False
if len(header) > 0:
self.setHorizontalHeaderLabels(header)
if len(header) > 1:
self.columns = True
parent = self.invisibleRootItem()
root = xmldata.getroot()
self.add(root, parent)

def add(self, element, parent):
item = QStandardItem(element.tag)
item.setIcon(self.dicon)
parent.appendRow(item)
for key, value in element.attrib.items():
itemattrib = QStandardItem(key)
item.appendRow(itemattrib)
itemleaf = QStandardItem(value)
if self.columns:
item.setChild(self.indexFromItem(itemattrib).row(), 1,
itemleaf)
else:
itemattrib.appendRow(itemleaf)
if (element.text and not element.text.isspace()) or (
element.getchildren() and element[0].tail
and not element[0].tail.isspace()):
text = ET.tostring(element, method='text', encoding='utf-8'
).decode('utf-8')
if not element.attrib:
itemtext = QStandardItem(text)
if self.columns:
item.setIcon(self.ficon)
parent.setChild(self.indexFromItem(item).row(), 1,
itemtext)
else:
itemtext.setIcon(self.ficon)
item.appendRow(itemtext)
else:
itemtext = QStandardItem('TEXT')
item.appendRow(itemtext)
itemleaf = QStandardItem(text)
if self.columns:
itemtext.setIcon(self.ficon)
item.setChild(self.indexFromItem(itemtext).row(), 1,
itemleaf)
else:
itemleaf.setIcon(self.ficon)
itemtext.appendRow(itemleaf)
else:
for el in element:
self.add(el, item)


def font_is_installed(font):
"""Check if font is installed"""
return [fam for fam in QFontDatabase().families()
Expand Down Expand Up @@ -518,6 +631,37 @@ def setup(self):
lab = QLabel()
lab.setPixmap(pixmap)
self.formlayout.addRow(lab)
elif value.endswith('.json'):
# JSON file
import json, io
from collections import OrderedDict
jsonfile = io.open(value, 'r', encoding='utf-8')
jsondata = json.load(jsonfile,
object_pairs_hook=OrderedDict)
if '_' in value:
header = value[:-5].split('_')
else:
header = [value[:-5]]
treemodel = DictTreeModel(jsondata, header)
tree = QTreeView()
tree.setModel(treemodel)
tree.setEditTriggers(QAbstractItemView.NoEditTriggers)
self.formlayout.addRow(tree)
elif value.endswith('.xml'):
# XML file
global ET
import xml.etree.ElementTree as ET
xmlfile = open(value, 'r')
xmldata = ET.parse(xmlfile)
if '_' in value:
header = value[:-4].split('_')
else:
header = [value[:-4]]
treemodel = XMLTreeModel(xmldata, header)
tree = QTreeView()
tree.setModel(treemodel)
tree.setEditTriggers(QAbstractItemView.NoEditTriggers)
self.formlayout.addRow(tree)
else:
# Comment
self.formlayout.addRow(QLabel(value))
Expand Down Expand Up @@ -571,6 +715,11 @@ def setup(self):
field.setCurrentIndex(selindex)
elif isinstance(save_value, tuple):
field = RadioLayout(value, selindex, self)
elif isinstance(value, dict):
treemodel = DictTreeModel(value)
field = QTreeView()
field.header().hide()
field.setModel(treemodel)
elif isinstance(value, bool):
field = QCheckBox(self)
field.setCheckState(Qt.Checked if value else Qt.Unchecked)
Expand Down Expand Up @@ -685,6 +834,8 @@ def get(self):
value = value[index+1]
if isinstance(value, (list, tuple)):
value = value[0]
elif isinstance(value, dict):
value = field.model().value()
elif isinstance(value, bool):
value = field.checkState() == Qt.Checked
elif isinstance(value, float):
Expand Down