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