refactoring on the way. Need some more debug
authorGiovanni Gherdovich <ggherdov@brentaal.inria.fr>
Thu, 7 Oct 2010 16:44:44 +0000 (18:44 +0200)
committerGiovanni Gherdovich <ggherdov@brentaal.inria.fr>
Thu, 7 Oct 2010 16:44:44 +0000 (18:44 +0200)
sface/rspecwindow.py
sface/sfiprocess.py
sface/xmlrpcwindow.py [new file with mode: 0644]
sface/xmlwidget.py [new file with mode: 0644]

index a0741c4..f9bca14 100644 (file)
@@ -5,20 +5,14 @@ from PyQt4.QtCore import *
 from PyQt4.QtGui import *
 from PyQt4.QtXml import *
 
+from sface.xmlwidget import *
 from sface.config import config
 from sface.screens.sfascreen import SfaScreen
 
 
-class RSpecView(QTreeView):
+class RSpecView(XmlView):
     def __init__(self, parent):
-        QTreeView.__init__(self, parent)
-
-        self.setAnimated(True)
-        self.setItemsExpandable(True)
-        self.setRootIsDecorated(True)
-        self.setHeaderHidden(True)
-        self.setAttribute(Qt.WA_MacShowFocusRect, 0)
-        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+        XmlView.__init__(self, parent)
 
     def expandMatchingText(self, txt):
         self.collapseAll()
@@ -48,227 +42,19 @@ class RSpecView(QTreeView):
             index = model.index(r, 0)
             search(index)
 
-
-class DomModel(QAbstractItemModel):
-    def __init__(self, document, parent = 0):
-        QAbstractItemModel.__init__(self, parent)
-        self.domDocument = document
-        # one of the children of the rootItem is the 'xml' thing.
-        # here I delete it.
-        childList = document.childNodes()
-        for i in range(childList.count()):
-            currElem = childList.item(i)
-            if (currElem.nodeType() == QDomNode.ProcessingInstructionNode):
-                document.removeChild(currElem)
-                break
-        self.rootItem = DomItem(document, 0);
-
-    def data(self, index, role = Qt.DisplayRole):
-        # sometimes it return a QString, sometimes a QVariant. not good.
-        if not index.isValid():
-            return QVariant()
-        if role != Qt.DisplayRole:
-            return QVariant()
-        node = index.internalPointer().node()
-        attributeMap = node.attributes()
-
-        col = index.column()
-        if col == 0:
-            if node.nodeType() == QDomNode.ElementNode:
-                qslist = QStringList()
-                for i in range(attributeMap.count()):
-                    attr = attributeMap.item(i)
-                    elem = ' <b>%s</b>="<font color="#1e90ff">%s</font>"' % (attr.nodeName(), attr.nodeValue())
-                    qslist.append(elem)
-                return QString('&lt;<b><font color="#b42be2">%s</font></b>%s&gt;'% (node.nodeName(), qslist.join(' ')))
-            elif node.nodeType() == QDomNode.AttributeNode:
-                return QString('Whozat?!')
-            elif node.nodeType() == QDomNode.TextNode:
-                return node.nodeValue()
-            elif node.nodeType() == QDomNode.CDATASectionNode:
-                return QString('unsupported node type')
-            elif node.nodeType() == QDomNode.EntityReferenceNode:
-                return QString('unsupported node type')
-            elif node.nodeType() == QDomNode.EntityNode:
-                return QString('unsupported node type')
-            elif node.nodeType() == QDomNode.ProcessingInstructionNode:
-                return QVariant()
-                #return node.nodeName()
-            elif node.nodeType() == QDomNode.CommentNode:
-                return QString('#').append(node.nodeValue())
-            elif node.nodeType() == QDomNode.DocumentNode:
-                return QString('unsupported node type')
-            elif node.nodeType() == QDomNode.DocumentTypeNode:
-                return QString('unsupported node type')
-            elif node.nodeType() == QDomNode.DocumentFragmentNode:
-                return QString('unsupported node type')
-            elif node.nodeType() == QDomNode.NotationNode:
-                return QString('unsupported node type')
-            elif node.nodeType() == QDomNode.BaseNode:
-                return QString('unsupported node type')
-            elif node.nodeType() == QDomNode.CharacterDataNode:
-                return QString('unsupported node type')
-            else:
-                return QVariant()
-        else:
-            return QVariant()
-
-    def flags(self, index):
-        if not index.isValid():
-            return Qt.ItemIsEnabled
-        return Qt.ItemIsEnabled | Qt.ItemIsSelectable
-        
-    def headerData(self, section, orientation, role):
-        return QVariant()
-
-    def index(self, row, column, parent=None):
-        if not parent or not parent.isValid():
-            parentItem = self.rootItem
-        else:
-            parentItem = parent.internalPointer()
-
-        childItem = parentItem.child(row)
-        # childItem would be None to say "false"?
-        if childItem:
-            return self.createIndex(row, column, childItem)
-        else:
-            return QModelIndex()
-
-    def parent(self, child):
-        if not child.isValid():
-            return QModelIndex()
-        childItem = child.internalPointer()
-        parentItem = childItem.parent()
-        
-        if not parentItem or parentItem == self.rootItem:
-            return QModelIndex()
-        return self.createIndex(parentItem.row(), 0, parentItem)
-
-    def rowCount(self, parent=None):
-        if not parent or not parent.isValid():
-            parentItem = self.rootItem
-        else:
-            parentItem = parent.internalPointer()
-
-        return parentItem.node().childNodes().count()
-
-    def columnCount(self, parent):
-        # just one column we'll print tag name (and attributes) or the
-        # tag content
-        return 1
-
-
-class DomItem:
-    # wrapper around PyQt4.QtXml.QDomNode it keeps an hash of
-    # childrens for performance reasons
-
-    def __init__(self, node, row, parent = 0):
-        # node is of type PyQt4.QtXml.QDomNode
-        self.domNode = node
-        self.parentItem = parent
-        self.rowNumber = row
-        self.childItems = {}
-
-    def child(self, i):
-        if i in self.childItems:
-            return self.childItems[i]
-        if i >= 0 and i < self.domNode.childNodes().count():
-            childNode = self.domNode.childNodes().item(i)
-            childItem = DomItem(childNode, i, self)
-            self.childItems[i] = childItem
-            return childItem
-        return None
-            
-    def parent(self):
-        return self.parentItem
-
-    def node(self):
-        return self.domNode
-
-    def row(self):
-        return self.rowNumber
-    
-
-class RSpecWindow(QDialog):
+class RSpecWindow(XmlWindow):
     def __init__(self, parent=None):
-        QDialog.__init__(self, parent)
-        self.setWindowTitle("RSpec View")
-
-        self.document = None
-        self.model = None
-
+        XmlWindow.__init__(self, parent, 'RSpec Window')
         self.view = RSpecView(self)
-        self.delegate = RSpecDelegate(self)
-        self.view.setItemDelegate(self.delegate)
-        layout = QVBoxLayout()
-        layout.addWidget(self.view)
-        self.setLayout(layout)
 
-        self.updateView()
-
-    def show(self):
-        self.updateView()
-        QDialog.show(self)
-        
     def showNode(self, hostname):
         self.view.expandMatchingText(hostname)
 
     def updateView(self):
-        del self.document
-        del self.model
-        self.document = None
-        self.model = None
+        XmlWindow.updateView(self)
 
         rspec_file = config.getSliceRSpecFile()
         if not os.path.exists(rspec_file):
             return
 
-        self.document = QDomDocument("RSpec")
         self.document.setContent(open(rspec_file,'r').read())
-        self.model = DomModel(self.document, self)
-
-        self.view.setModel(self.model)
-        self.view.expand(self.model.index(0, 0)) #expand first level only
-
-
-class RSpecDelegate(QAbstractItemDelegate):
-    
-    def __init__(self, parent=None):
-        QAbstractItemDelegate.__init__(self, parent)
-
-    def paint(self, painter, option, index):
-        text = index.model().data(index)
-        palette = QApplication.palette()
-        document = QTextDocument()
-        document.setDefaultFont(option.font)
-        if option.state & QStyle.State_Selected:
-            rx = QRegExp(QString('<font .*>'))
-            rx.setMinimal(True)
-            # If selected, I remove the <font color="..."> by hand,
-            # and give the highlight color
-            document.setHtml(QString("<font color=%1>%2</font>") \
-                                 .arg(palette.highlightedText().color().name())\
-                                 .arg(text.replace(rx, QString('')).
-                                      replace(QString('</font>'),QString(''))))
-        else:
-            document.setHtml(text)
-        color = palette.highlight().color() \
-            if option.state & QStyle.State_Selected \
-            else palette.base().color()
-        painter.save()
-        # voodoo: if not highlighted, filling the rect
-        # with the base color makes no difference
-        painter.fillRect(option.rect, color)
-        painter.translate(option.rect.x(), option.rect.y())
-        document.drawContents(painter)
-        painter.restore()
-
-    def sizeHint(self, option, index):
-        fm = option.fontMetrics
-        text = index.model().data(index)
-        document = QTextDocument()
-        document.setDefaultFont(option.font)
-        document.setHtml(text)
-        # the +5 is for margin. The +4 is voodoo;
-        # fm.height just give it too small.
-        return QSize(document.idealWidth() + 5, fm.height() + 4)
index bf37de5..1e93b29 100644 (file)
@@ -2,14 +2,10 @@
 import os
 import sys
 import time
-import re
 
 from PyQt4.QtCore import *
-from PyQt4.QtXml import QDomDocument
 from sface.config import config
-from sface.logwindow import LogIO
-from sface.rspecwindow import RSpecWindow, DomModel
-
+from sface.xmlrpcwindow import XmlrpcTracker
 
 def find_executable(exec_name):
     """find the given executable in $PATH"""
@@ -29,8 +25,8 @@ class SfiProcess(QObject):
         self.connect(self.process, SIGNAL("finished(int, QProcess::ExitStatus)"),
                      self.processFinished)
         
-        self.xmltracker = XmlTracker()
-        # in case self.output is read by the XmlTracker before any
+        self.xmlrpctracker = XmlrpcTracker()
+        # in case self.output is read by the XmlrpcTracker before any
         # readyReadStandardOutput signal
         self.output = ''
 
@@ -59,8 +55,7 @@ class SfiProcess(QObject):
         # the process has made new data available through its standard output channel.
         # But the process is not necessarily finished.
         # It's cool to have this method wo we print the stdOut live,
-        # but we must be carefull with self.output, used by xmlTracker too.
-        print "SETTING SELF.OUTPUT"
+        # but we must be carefull with self.output, used by XmlrpcTracker too.
         tmpOut = self.process.readAllStandardOutput()
         if config.debug:
             print tmpOut        
@@ -145,69 +140,5 @@ class SfiProcess(QObject):
         if config.verbose:
             command = "%s %s" % (self.exe, self.args.join(" "))
             print time.strftime('%M:%S'),"[%.3f s]"%(time.time()-self._trace),command,'Done'
-            self.xmltracker.getAndPrint(self.output)
-
-class XmlTracker():
-    def __init__(self):
-        self.xmlrpcWindow = XmlrpcWindow()
-
-    def getAndPrint(self, rawOutput):
-        self.store(rawOutput)
-        self.extractXml()
-        self.xmlrpcWindow.setData(self.xml)
-        self.showXmlrpc()
-
-    def showXmlrpc(self):
-        self.xmlrpcWindow.show()
-        self.xmlrpcWindow.resize(500, 640)
-        self.xmlrpcWindow.raise_()
-        self.xmlrpcWindow.activateWindow()
-
-    def store(self, rawOutput):
-        self.rawOutput = rawOutput
-
-    def extractXml(self):
-        pttrnAsk = '<methodCall>.*?</methodCall>'
-        pttrnAns = '<methodResponse>.*?</methodResponse>'
-        answers = re.compile(pttrnAsk, re.DOTALL).findall(self.rawOutput)
-        replies = re.compile(pttrnAns, re.DOTALL).findall(self.rawOutput)
-        # cleaning
-        answers = map(lambda x: x.replace('\\n','\n'), answers)
-        replies = map(lambda x: x.replace('\\n','\n').replace("'\nbody: '", ''), replies)
-        replies.reverse() # so that I use pop() as popleft
-        # A well-formed XML document must have one, and only one, top-level element
-        self.xml = '<debug>'
-        for ans in answers:
-            self.xml += ans + replies.pop()
-        self.xml += '</debug>'
-
-    def stats(self):
-        # statistics: round-trip time, size of the com
-        pass
-
-    def prettyPrint(self, XmlComs):
-        # just for testing
-        print XmlComs
-
-class XmlrpcWindow(RSpecWindow):
-    def __init__(self, parent=None):
-        # super __init__() calls updateView,
-        # which assumes you have some data
-        self.data = '<debug/>'
-        RSpecWindow.__init__(self, parent)
-
-    def setData(self, XmlrpcCom):
-        self.data = XmlrpcCom
-
-    def updateView(self):
-        del self.document
-        del self.model
-        self.document = None
-        self.model = None
-
-        self.document = QDomDocument("RSpec")
-        self.document.setContent(self.data)
-        self.model = DomModel(self.document, self)
-
-        self.view.setModel(self.model)
-        self.view.expand(self.model.index(0, 0)) #expand first level only
+            self.xmlrpctracker.getAndPrint(self.output)
+
diff --git a/sface/xmlrpcwindow.py b/sface/xmlrpcwindow.py
new file mode 100644 (file)
index 0000000..483d443
--- /dev/null
@@ -0,0 +1,56 @@
+import re
+from PyQt4.QtXml import QDomDocument
+from sface.xmlwidget import XmlWindow, DomModel
+
+class XmlrpcTracker():
+    def __init__(self):
+        self.xmlrpcWindow = XmlrpcWindow()
+
+    def getAndPrint(self, rawOutput):
+        self.store(rawOutput)
+        self.extractXml()
+        self.xmlrpcWindow.setData(self.xml)
+        self.showXmlrpc()
+
+    def showXmlrpc(self):
+        self.xmlrpcWindow.show()
+        self.xmlrpcWindow.resize(500, 640)
+        self.xmlrpcWindow.raise_()
+        self.xmlrpcWindow.activateWindow()
+
+    def store(self, rawOutput):
+        self.rawOutput = rawOutput
+
+    def extractXml(self):
+        pttrnAsk = '<methodCall>.*?</methodCall>'
+        pttrnAns = '<methodResponse>.*?</methodResponse>'
+        answers = re.compile(pttrnAsk, re.DOTALL).findall(self.rawOutput)
+        replies = re.compile(pttrnAns, re.DOTALL).findall(self.rawOutput)
+        # cleaning
+        answers = map(lambda x: x.replace('\\n','\n'), answers)
+        replies = map(lambda x: x.replace('\\n','\n').replace("'\nbody: '", ''), replies)
+        replies.reverse() # so that I use pop() as popleft
+        # A well-formed XML document must have one, and only one, top-level element
+        self.xml = '<debug>'
+        for ans in answers:
+            self.xml += ans + replies.pop()
+        self.xml += '</debug>'
+
+    def stats(self):
+        # statistics: round-trip time, size of the com
+        pass
+
+class XmlrpcWindow(XmlWindow):
+    def __init__(self, parent=None):
+        # super __init__() calls updateView,
+        # which assumes you have some data
+        self.data = '<debug/>'
+        XmlWindow.__init__(self, parent, 'XMLRPC window')
+
+    def setData(self, XmlrpcCom):
+        self.data = XmlrpcCom
+
+    def updateView(self):
+        XmlWindow.updateView(self)
+
+        self.document.setContent(self.data)
diff --git a/sface/xmlwidget.py b/sface/xmlwidget.py
new file mode 100644 (file)
index 0000000..a52522a
--- /dev/null
@@ -0,0 +1,244 @@
+import os
+import sys
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+from PyQt4.QtXml import *
+
+from sface.config import config
+from sface.screens.sfascreen import SfaScreen
+
+class DomModel(QAbstractItemModel):
+    def __init__(self, document, parent = 0):
+        QAbstractItemModel.__init__(self, parent)
+        self.domDocument = document
+        # one of the children of the rootItem is the 'xml' thing.
+        # here I delete it.
+        childList = document.childNodes()
+        for i in range(childList.count()):
+            currElem = childList.item(i)
+            if (currElem.nodeType() == QDomNode.ProcessingInstructionNode):
+                document.removeChild(currElem)
+                break
+        self.rootItem = DomItem(document, 0);
+
+    def data(self, index, role = Qt.DisplayRole):
+        # sometimes it return a QString, sometimes a QVariant. not good.
+        if not index.isValid():
+            return QVariant()
+        if role != Qt.DisplayRole:
+            return QVariant()
+        node = index.internalPointer().node()
+        attributeMap = node.attributes()
+
+        col = index.column()
+        if col == 0:
+            if node.nodeType() == QDomNode.ElementNode:
+                qslist = QStringList()
+                for i in range(attributeMap.count()):
+                    attr = attributeMap.item(i)
+                    elem = ' <b>%s</b>="<font color="#1e90ff">%s</font>"' % (attr.nodeName(), attr.nodeValue())
+                    qslist.append(elem)
+                return QString('&lt;<b><font color="#b42be2">%s</font></b>%s&gt;'% (node.nodeName(), qslist.join(' ')))
+            elif node.nodeType() == QDomNode.AttributeNode:
+                return QString('Whozat?!')
+            elif node.nodeType() == QDomNode.TextNode:
+                return node.nodeValue()
+            elif node.nodeType() == QDomNode.CDATASectionNode:
+                return QString('unsupported node type')
+            elif node.nodeType() == QDomNode.EntityReferenceNode:
+                return QString('unsupported node type')
+            elif node.nodeType() == QDomNode.EntityNode:
+                return QString('unsupported node type')
+            elif node.nodeType() == QDomNode.ProcessingInstructionNode:
+                return QVariant()
+                #return node.nodeName()
+            elif node.nodeType() == QDomNode.CommentNode:
+                return QString('#').append(node.nodeValue())
+            elif node.nodeType() == QDomNode.DocumentNode:
+                return QString('unsupported node type')
+            elif node.nodeType() == QDomNode.DocumentTypeNode:
+                return QString('unsupported node type')
+            elif node.nodeType() == QDomNode.DocumentFragmentNode:
+                return QString('unsupported node type')
+            elif node.nodeType() == QDomNode.NotationNode:
+                return QString('unsupported node type')
+            elif node.nodeType() == QDomNode.BaseNode:
+                return QString('unsupported node type')
+            elif node.nodeType() == QDomNode.CharacterDataNode:
+                return QString('unsupported node type')
+            else:
+                return QVariant()
+        else:
+            return QVariant()
+
+    def flags(self, index):
+        if not index.isValid():
+            return Qt.ItemIsEnabled
+        return Qt.ItemIsEnabled | Qt.ItemIsSelectable
+        
+    def headerData(self, section, orientation, role):
+        return QVariant()
+
+    def index(self, row, column, parent=None):
+        if not parent or not parent.isValid():
+            parentItem = self.rootItem
+        else:
+            parentItem = parent.internalPointer()
+
+        childItem = parentItem.child(row)
+        # childItem would be None to say "false"?
+        if childItem:
+            return self.createIndex(row, column, childItem)
+        else:
+            return QModelIndex()
+
+    def parent(self, child):
+        if not child.isValid():
+            return QModelIndex()
+        childItem = child.internalPointer()
+        parentItem = childItem.parent()
+        
+        if not parentItem or parentItem == self.rootItem:
+            return QModelIndex()
+        return self.createIndex(parentItem.row(), 0, parentItem)
+
+    def rowCount(self, parent=None):
+        if not parent or not parent.isValid():
+            parentItem = self.rootItem
+        else:
+            parentItem = parent.internalPointer()
+
+        return parentItem.node().childNodes().count()
+
+    def columnCount(self, parent):
+        # just one column we'll print tag name (and attributes) or the
+        # tag content
+        return 1
+
+
+class DomItem:
+    # wrapper around PyQt4.QtXml.QDomNode it keeps an hash of
+    # childrens for performance reasons
+
+    def __init__(self, node, row, parent = 0):
+        # node is of type PyQt4.QtXml.QDomNode
+        self.domNode = node
+        self.parentItem = parent
+        self.rowNumber = row
+        self.childItems = {}
+
+    def child(self, i):
+        if i in self.childItems:
+            return self.childItems[i]
+        if i >= 0 and i < self.domNode.childNodes().count():
+            childNode = self.domNode.childNodes().item(i)
+            childItem = DomItem(childNode, i, self)
+            self.childItems[i] = childItem
+            return childItem
+        return None
+            
+    def parent(self):
+        return self.parentItem
+
+    def node(self):
+        return self.domNode
+
+    def row(self):
+        return self.rowNumber
+
+class XmlView(QTreeView):
+    def __init__(self, parent):
+        QTreeView.__init__(self, parent)
+
+        self.setAnimated(True)
+        self.setItemsExpandable(True)
+        self.setRootIsDecorated(True)
+        self.setHeaderHidden(True)
+        self.setAttribute(Qt.WA_MacShowFocusRect, 0)
+        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
+
+class XmlWindow(QDialog):
+    def __init__(self, parent=None, title='XML Window'):
+        QDialog.__init__(self, parent)
+        self.setWindowTitle(title)
+
+        self.document = None
+        self.model = None
+        self.title = title
+
+        self.view = XmlView(self)
+        self.delegate = XmlDelegate(self)
+        self.view.setItemDelegate(self.delegate)
+        layout = QVBoxLayout()
+        layout.addWidget(self.view)
+        self.setLayout(layout)
+
+        self.updateView()
+
+    def show(self):
+        self.updateView()
+        QDialog.show(self)
+        
+    def updateView(self):
+        del self.document
+        del self.model
+        self.document = None
+        self.model = None
+
+        self.document = QDomDocument(self.title)
+        self.model = DomModel(self.document, self)
+
+        self.view.setModel(self.model)
+        self.view.expand(self.model.index(0, 0)) #expand first level only
+
+        #move the code below to rspec window
+        rspec_file = config.getSliceRSpecFile()
+        if not os.path.exists(rspec_file):
+            return
+
+        self.document.setContent(open(rspec_file,'r').read())
+
+
+
+class XmlDelegate(QAbstractItemDelegate):
+    
+    def __init__(self, parent=None):
+        QAbstractItemDelegate.__init__(self, parent)
+
+    def paint(self, painter, option, index):
+        text = index.model().data(index)
+        palette = QApplication.palette()
+        document = QTextDocument()
+        document.setDefaultFont(option.font)
+        if option.state & QStyle.State_Selected:
+            rx = QRegExp(QString('<font .*>'))
+            rx.setMinimal(True)
+            # If selected, I remove the <font color="..."> by hand,
+            # and give the highlight color
+            document.setHtml(QString("<font color=%1>%2</font>") \
+                                 .arg(palette.highlightedText().color().name())\
+                                 .arg(text.replace(rx, QString('')).
+                                      replace(QString('</font>'),QString(''))))
+        else:
+            document.setHtml(text)
+        color = palette.highlight().color() \
+            if option.state & QStyle.State_Selected \
+            else palette.base().color()
+        painter.save()
+        # voodoo: if not highlighted, filling the rect
+        # with the base color makes no difference
+        painter.fillRect(option.rect, color)
+        painter.translate(option.rect.x(), option.rect.y())
+        document.drawContents(painter)
+        painter.restore()
+
+    def sizeHint(self, option, index):
+        fm = option.fontMetrics
+        text = index.model().data(index)
+        document = QTextDocument()
+        document.setDefaultFont(option.font)
+        document.setHtml(text)
+        # the +5 is for margin. The +4 is voodoo;
+        # fm.height just give it too small.
+        return QSize(document.idealWidth() + 5, fm.height() + 4)