@@ -991,9 +991,11 @@ def __resetPreview(self):
991991 base = CachedBytesIOWrapper (self .__sample , self .__buffer )
992992
993993 wrapper = io .TextIOWrapper (
994- base , encoding = self .encoding (), errors = "replace"
994+ base , encoding = self .encoding (),
995+ # use surrogate escape to validate/detect encoding errors in
996+ # delegates
997+ errors = "surrogateescape"
995998 )
996-
997999 rows = csv .reader (
9981000 wrapper , dialect = self .dialect ()
9991001 )
@@ -1372,6 +1374,11 @@ def sizeHint(self):
13721374 return sh .expandedTo (QSize (8 * hsection , 20 * vsection ))
13731375
13741376
1377+ def is_surrogate_escaped (text : str ) -> bool :
1378+ """Does `text` contain any surrogate escape characters."""
1379+ return any ("\udc80 " <= c <= "\udcff " for c in text )
1380+
1381+
13751382class PreviewItemDelegate (QStyledItemDelegate ):
13761383 def initStyleOption (self , option , index ):
13771384 # type: (QStyleOptionViewItem, QModelIndex) -> None
@@ -1389,6 +1396,18 @@ def initStyleOption(self, option, index):
13891396 if coltype == ColumnType .Numeric or coltype == ColumnType .Time :
13901397 option .displayAlignment = Qt .AlignRight | Qt .AlignVCenter
13911398
1399+ if not self .validate (option .text ):
1400+ option .palette .setBrush (
1401+ QPalette .All , QPalette .Text , QBrush (Qt .red , Qt .SolidPattern )
1402+ )
1403+ option .palette .setBrush (
1404+ QPalette .All , QPalette .HighlightedText ,
1405+ QBrush (Qt .red , Qt .SolidPattern )
1406+ )
1407+
1408+ def validate (self , value : str ) -> bool : # pylint: disable=no-self-use
1409+ return not is_surrogate_escaped (value )
1410+
13921411 def helpEvent (self , event , view , option , index ):
13931412 # type: (QHelpEvent, QAbstractItemView, QStyleOptionViewItem, QModelIndex) -> bool
13941413 if event .type () == QEvent .ToolTip :
@@ -1467,17 +1486,6 @@ def __init__(self, *args, converter=None, **kwargs):
14671486 super ().__init__ (* args , ** kwargs )
14681487 self .converter = converter or float
14691488
1470- def initStyleOption (self , option , index ):
1471- super ().initStyleOption (option , index )
1472- if not self .validate (option .text ):
1473- option .palette .setBrush (
1474- QPalette .All , QPalette .Text , QBrush (Qt .red , Qt .SolidPattern )
1475- )
1476- option .palette .setBrush (
1477- QPalette .All , QPalette .HighlightedText ,
1478- QBrush (Qt .red , Qt .SolidPattern )
1479- )
1480-
14811489 def validate (self , value ):
14821490 if value in {"NA" , "Na" , "na" , "n/a" , "N/A" , "?" , "" , "." }:
14831491 return True
@@ -1486,7 +1494,7 @@ def validate(self, value):
14861494 except ValueError :
14871495 return False
14881496 else :
1489- return True
1497+ return super (). validate ( value )
14901498
14911499
14921500def number_parser (groupsep , decimalsep ):
0 commit comments