scrolling in xmlrpctracker
[sface.git] / sface / xmlrpcwindow.py
index 72b0f68..91f0c01 100644 (file)
@@ -1,4 +1,5 @@
 import re
+import xmlrpclib
 from lxml import etree
 from PyQt4.QtXml import QDomDocument
 from sface.xmlwidget import XmlWindow, DomModel, XmlView, XmlDelegate, ElemNodeDelegate, TextNodeDelegate, CommentNodeDelegate
@@ -15,39 +16,6 @@ class XmlrpcReader():
     def store(self, rawOutput):
         self.rawOutput = rawOutput
 
-    def paramString(self, item):
-        """
-           Convert an xmlrpc <PARAM> into a human-readable string
-           Is there an easier way?
-        """
-        if item.tag == "string":
-            return item.text
-        elif item.tag == "array":
-            arrayValues = item.xpath("data/value")
-            if arrayValues:
-                children = list(arrayValues[0])
-                if children:
-                    return self.paramString(children[0]) + ", ..."
-                else:
-                    return "[]"
-            else:
-                return "[]"
-        elif item.tag == "struct":
-            dict = {}
-            members = item.xpath("member")
-            for member in members:
-                names = member.xpath("name")
-                values = member.xpath("value")
-                if (names) and (values):
-                    name = names[0]
-                    value = values[0]
-                    if len(list(value))>0:
-                        data = list(value)[0]
-                        dict[name.text] = self.paramString(list(value)[0])
-            return str(dict)
-        else:
-            return "unknown"
-
     def parseMethodCall(self, mc):
         mc = str(mc)
 
@@ -61,20 +29,14 @@ class XmlrpcReader():
         if tree.tag != "methodCall" or (len(list(tree))==0):
             return request
 
-        methodNames = tree.xpath("//methodCall/methodName")
-
-        if len(methodNames) == 0:
-            return request
-
-        request["args"] = []
-
-        params = tree.xpath("//methodCall/params/param/value")
-        for param in params:
-            children = list(param)
-            if children:
-                request["args"].append(self.paramString(children[0]))
+        try:
+            (pythonParams, methodName) = xmlrpclib.loads(etree.tostring(tree))
+        except:  # in case something went wrong when unmarashaling...
+            pythonParams = []
+            methodName = "<exception in parseMethodCall>"
 
-        request["methodName"] = methodNames[0].text
+        request["args"] = [str(x) for x in pythonParams]
+        request["methodName"] = methodName
 
         return request
 
@@ -196,6 +158,11 @@ class XmlrpcTracker(QWidget):
         self.delegate.insertNodeDelegate('comment', CommentNodeDelegate())
         self.xmlView.setItemDelegate(self.delegate)
 
+        exportButton = QPushButton("&Export Call")
+        layoutButtons = QHBoxLayout()
+        layoutButtons.addWidget(exportButton)
+        layoutButtons.addStretch()
+
         self.layout = QVBoxLayout()
         self.layout.addWidget(labelCalls)
         self.layout.addWidget(self.callTable)
@@ -203,10 +170,12 @@ class XmlrpcTracker(QWidget):
         self.layout.addWidget(self.argsTable)
         self.layout.addWidget(labelXml)
         self.layout.addWidget(self.xmlView)
+        self.layout.addLayout(layoutButtons)
 
         self.setLayout(self.layout)
 
         self.connect(self.callTable, SIGNAL("itemSelectionChanged ()"), self.onCallSelect)
+        self.connect(exportButton, SIGNAL("clicked()"), self.onExportClicked)
 
     def getAndPrint(self, rawOutput):
         self.reader.store(rawOutput)
@@ -215,8 +184,9 @@ class XmlrpcTracker(QWidget):
 
     def updateCallTable(self):
         self.callTable.clear()
-        self.callTable.setColumnCount(2)
-        self.callTable.setHorizontalHeaderLabels(["name", "status"])
+        self.callTable.setColumnCount(3)
+        self.callTable.setHorizontalHeaderLabels(["name", "status", "faultString"])
+        self.callTable.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)
 
         calls = self.reader.calls
         self.callTable.setRowCount(len(calls))
@@ -235,6 +205,11 @@ class XmlrpcTracker(QWidget):
             item.setData(Qt.UserRole, index)
             self.callTable.setItem(row, 1, item)
 
+            item = QTableWidgetItem(call.get("faultString", ""))
+            item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled)
+            item.setData(Qt.UserRole, index)
+            self.callTable.setItem(row, 2, item)
+
             row = row + 1
 
         self.callTable.resizeColumnsToContents()
@@ -261,19 +236,27 @@ class XmlrpcTracker(QWidget):
 
         self.argsTable.resizeColumnsToContents()
 
-    def onCallSelect(self):
+    def getSelectedCall(self):
         selItems = self.callTable.selectedItems()
         if (len(selItems) <= 0):
-            return
+            return None
 
         row = selItems[0].data(Qt.UserRole).toInt()[0]
 
         calls = self.reader.calls
         if len(calls)<=row:
-            return
+            return None
 
         call = calls[row]
 
+        return call
+
+    def onCallSelect(self):
+        call = self.getSelectedCall()
+
+        if not call:
+            return
+
         xml = "<debug>" + call.get("request","") + call.get("reply", "") + "</debug>"
         #xml = call.get("request","") + call.get("reply", "")
 
@@ -281,6 +264,20 @@ class XmlrpcTracker(QWidget):
 
         self.updateArgsTable(call.get("args",[]))
 
+    def onExportClicked(self):
+        call = self.getSelectedCall()
+
+        if not call:
+            return
+
+        filename = QFileDialog.getSaveFileName(self, 'Save File', '.')
+
+        f = open(filename, "w")
+        f.write(call.get("request","") + "\n")
+        f.write(call.get("reply","") + "\n")
+        f.close()
+
+
     def displayXml(self, xml):
         self.document = QDomDocument("XMLRPC Tracker")
         self.document.setContent(xml)