320e065e6fd598eb0bd18e32d79bf01237167a36
[sface.git] / sface / screens / rspecscreen.py
1 import os
2 import sys
3
4 from PyQt4.QtCore import *
5 from PyQt4.QtGui import *
6 from PyQt4.QtXml import *
7
8 from sface.config import config
9 from sface.screens.sfascreen import SfaScreen
10
11
12 class DomModel(QAbstractItemModel):
13     def __init__(self, document, parent = 0):
14         QAbstractItemModel.__init__(self, parent)
15         self.domDocument = document
16         self.rootItem = DomItem(document, 0);
17
18     def data(self, index, role):
19         if not index.isValid():
20             return QVariant()
21         if role != Qt.DisplayRole:
22             return QVariant()
23         node = index.internalPointer().node()
24         attributeMap = node.attributes()
25
26         col = index.column()
27         if col == 0:
28             if node.nodeType() == QDomNode.ElementNode:
29                 qslist = QStringList()
30                 for i in range(attributeMap.count()):
31                     attr = attributeMap.item(i)
32                     elem = (attr.nodeName()
33                             .append(QString('="'))
34                             .append(attr.nodeValue())
35                             .append(QString('"')))
36                     qslist.append(elem)
37                 return (QString('<').
38                         append(node.nodeName()).
39                         append(' ').
40                         append(qslist.join(' ')).
41                         append('>'))
42             elif node.nodeType() == QDomNode.AttributeNode:
43                 return QString('Whozat?!')
44             elif node.nodeType() == QDomNode.TextNode:
45                 return node.nodeValue()
46             elif node.nodeType() == QDomNode.CDATASectionNode:
47                 return QString('unsupported node type')
48             elif node.nodeType() == QDomNode.EntityReferenceNode:
49                 return QString('unsupported node type')
50             elif node.nodeType() == QDomNode.EntityNode:
51                 return QString('unsupported node type')
52             elif node.nodeType() == QDomNode.ProcessingInstructionNode:
53                 return node.nodeName()
54             elif node.nodeType() == QDomNode.CommentNode:
55                 return QString('#').append(node.nodeValue())
56             elif node.nodeType() == QDomNode.DocumentNode:
57                 return QString('unsupported node type')
58             elif node.nodeType() == QDomNode.DocumentTypeNode:
59                 return QString('unsupported node type')
60             elif node.nodeType() == QDomNode.DocumentFragmentNode:
61                 return QString('unsupported node type')
62             elif node.nodeType() == QDomNode.NotationNode:
63                 return QString('unsupported node type')
64             elif node.nodeType() == QDomNode.BaseNode:
65                 return QString('unsupported node type')
66             elif node.nodeType() == QDomNode.CharacterDataNode:
67                 return QString('unsupported node type')
68             else:
69                 return QVariant()
70         else:
71             return QVariant()
72
73     def flags(self, index):
74         if not index.isValid():
75             return Qt.ItemIsEnabled
76         # does this `|` thing hold?
77         return Qt.ItemIsEnabled | Qt.ItemIsSelectable
78         
79     def headerData(self, section, orientation, role):
80         return QVariant()
81
82     def index(self, row, column, parent):
83         if not parent.isValid():
84             parentItem = self.rootItem
85         else:
86             parentItem = parent.internalPointer()
87
88         childItem = parentItem.child(row)
89         # childItem would be None to say "false"?
90         if childItem:
91             return self.createIndex(row, column, childItem)
92         else:
93             return QModelIndex()
94
95     def parent(self, child):
96         if not child.isValid():
97             return QModelIndex()
98         childItem = child.internalPointer()
99         parentItem = childItem.parent()
100         
101         if not parentItem or parentItem == self.rootItem:
102             return QModelIndex()
103         return self.createIndex(parentItem.row(), 0, parentItem)
104
105     def rowCount(self, parent):
106         if not parent.isValid():
107             parentItem = self.rootItem
108         else:
109             parentItem = parent.internalPointer()
110
111         return parentItem.node().childNodes().count()
112
113     def columnCount(self, parent):
114         # just one column
115         # we'll print tag name (and attributes)
116         # or the tag content
117         return 1
118
119
120 class DomItem:
121     # wrapper around PyQt4.QtXml.QDomNode
122     # it keeps an hash of childrens for
123     # performance reasons
124
125     def __init__(self, node, row, parent = 0):
126         # node is of type PyQt4.QtXml.QDomNode
127         self.domNode = node
128         self.parentItem = parent
129         self.rowNumber = row
130         self.childItems = {}
131
132     def child(self, i):
133         if i in self.childItems:
134             return self.childItems[i]
135         if i >= 0 and i < self.domNode.childNodes().count():
136             childNode = self.domNode.childNodes().item(i)
137             childItem = DomItem(childNode, i, self)
138             self.childItems[i] = childItem
139             return childItem
140         return None
141             
142     def parent(self):
143         return self.parentItem
144
145     def node(self):
146         return self.domNode
147
148     def row(self):
149         return self.rowNumber
150     
151
152 class RSpecWidget(QWidget):
153     def __init__(self, parent=None):
154         QWidget.__init__(self, parent)
155         self.updateView()
156
157     def updateView(self):
158         document = QDomDocument("RSpec")
159         rspec_file = config.getSliceRSpecFile()
160         if not os.path.exists(rspec_file):
161             return
162
163         document.setContent(open(rspec_file,'r').read())
164         model = DomModel(document, self)
165
166         view = QTreeView(self)
167         view.setHeaderHidden(True)
168         view.setModel(model)
169
170         layout = QVBoxLayout()
171         layout.addWidget(view)
172         self.setLayout(layout)
173
174
175 class RSpecScreen(SfaScreen):
176     def __init__(self, parent):
177         SfaScreen.__init__(self, parent)
178         
179         widget = RSpecWidget(self)
180         self.init(widget, "RSpec Window", "RSPec View")
181
182     def rspecUpdated(self):
183         self.widget.updateView()