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