fix failed parsing of attributes with spaces in them in xml viewer
[sface.git] / sface / xmlwidget.py
index b11f1ed..be53182 100644 (file)
@@ -1,4 +1,5 @@
 import os
+import shlex
 import sys
 
 from PyQt4.QtCore import *
@@ -85,7 +86,7 @@ class DomModel(QAbstractItemModel):
         if not index.isValid():
             return Qt.ItemIsEnabled
         return Qt.ItemIsEnabled | Qt.ItemIsSelectable
-        
+
     def headerData(self, section, orientation, role):
         return QVariant()
 
@@ -176,7 +177,7 @@ class XmlWindow(QDialog):
         self.model = None
         self.title = title
 
-        self.view = XmlView(self)
+        self.view = self.initView()
         self.delegate = XmlDelegate(self)
         self.view.setItemDelegate(self.delegate)
         self.delegate.insertNodeDelegate('element', ElemNodeDelegate())
@@ -188,6 +189,9 @@ class XmlWindow(QDialog):
 
         self.updateView()
 
+    def initView(self):
+        return XmlView(self)
+
     def show(self):
         self.updateView()
         QDialog.show(self)
@@ -228,6 +232,8 @@ class XmlDelegate(QItemDelegate):
             del self.delegates[nodeType]
     
     def paint(self, painter, option, index):
+        if isinstance(index.model().data(index),QVariant):
+            return
         nodeType = index.model().data(index).property('nodeType')
         delegate = self.delegates.get(str(nodeType.toString()))
         #print "TYPE:", str(type(str(nodeType.toString())))
@@ -244,6 +250,8 @@ class XmlDelegate(QItemDelegate):
 
     def sizeHint(self, option, index):
         fm = option.fontMetrics
+        if isinstance(index.model().data(index),QVariant):
+            return QSize(0, 0)
         text = index.model().data(index).property('content').toString()
         document = QTextDocument()
         document.setDefaultFont(option.font)
@@ -270,11 +278,21 @@ class ElemNodeDelegate(QAbstractItemDelegate):
             AttListHtml = ''
             if len(tmp) > 1:
                 # many elems don't have atts...
-                attList = tmp[1].split()
+                # use shlex.split so we can handle quoted strings with spaces
+                # in them, like <link enpoints="foo bar">. Note that there are
+                # documented problems with shlex.split and unicode, so we
+                # convert any potential unicode to a string first.
+                attList = shlex.split(str(tmp[1]))
                 for att in attList:
-                    tmp = att.split('=')
-                    attName = tmp[0]
-                    attValue = tmp[1][1:-1]
+                    tmp = att.split('=',1)
+                    if len(tmp)>=2:
+                        attName = tmp[0]
+                        attValue = tmp[1]
+                    else:
+                        # this shouldn't happen, but if it does, pretend the
+                        # attribute value is blank.
+                        attName = tmp[0]
+                        attValue = ""
                     AttListHtml += (nonHighAttPattern % (attName, attValue))
             html = (globPattern % (elemName, AttListHtml))
             return html