<s> from __future__ import print_function <EOL> import sys <EOL> import os <EOL> from collections import deque <EOL> from binascii import hexlify , unhexlify <EOL> from xml . sax . saxutils import escape as xmlEscape <EOL> from PyQt5 . QtCore import * <EOL> from PyQt5 . QtGui import * <EOL> from PyQt5 . QtWidgets import * <EOL> from PyQt5 . QtWebKit import * <EOL> class TextLineItem ( QGraphicsItemGroup ) : <EOL> STYLE_SHEET = '''<STR_LIT>''' <EOL> NUM_COLUMNS = <NUM_LIT:3> <EOL> COLIDX_ADDR , COLIDX_HEX , COLIDX_ASM = range ( NUM_COLUMNS ) <EOL> COLUMN_SPACING = <NUM_LIT:15> <EOL> def __init__ ( self , mainWin , addr , size , asmOp , font ) : <EOL> QGraphicsItemGroup . __init__ ( self ) <EOL> self . mainWin = mainWin <EOL> self . addr = addr <EOL> self . size = size <EOL> self . asmOp = asmOp <EOL> self . font = font <EOL> self . hexBytes = bytearray ( <EOL> self . mainWin . core . getBytes ( self . addr , self . size ) ) <EOL> self . items = [ <EOL> self . _makeTextItem ( self . htmlAddr ) , <EOL> self . _makeTextItem ( self . htmlHex ) , <EOL> self . _makeTextItem ( self . htmlAsm ) , <EOL> ] <EOL> assert len ( self . items ) == self . NUM_COLUMNS <EOL> self . myTextWidths = [ item . document ( ) . idealWidth ( ) <EOL> for item in self . items ] <EOL> for i , item in enumerate ( self . items ) : <EOL> item . setPos ( i * <NUM_LIT:100> , <NUM_LIT:0> ) <EOL> def _makeTextItem ( self , html ) : <EOL> item = QGraphicsTextItem ( self ) <EOL> item . setFont ( self . font ) <EOL> doc = item . document ( ) <EOL> doc . setDefaultStyleSheet ( self . STYLE_SHEET ) <EOL> doc . setHtml ( html ) <EOL> return item <EOL> @ property <EOL> def htmlAddr ( self ) : <EOL> '''<STR_LIT>''' <EOL> return '<STR_LIT>' . format ( <EOL> xmlEscape ( self . mainWin . fmtNum ( self . addr ) ) ) <EOL> @ property <EOL> def htmlHex ( self ) : <EOL> '''<STR_LIT>''' <EOL> hexWithSpaces = '<STR_LIT:U+0020>' . join ( format ( b , '<STR_LIT>' ) for b in self . hexBytes ) <EOL> return '<STR_LIT>' . format ( <EOL> xmlEscape ( hexWithSpaces ) ) <EOL> @ property <EOL> def htmlAsm ( self ) : <EOL> '''<STR_LIT>''' <EOL> if self . asmOp is None : <EOL> return '<STR_LIT>' <EOL> return self . mainWin . asmFormatter . format ( str ( self . hexBytes ) , self . addr ) <EOL> @ staticmethod <EOL> def _getColWidth ( colIdx , textLines ) : <EOL> w = max ( textln . myTextWidths [ colIdx ] for textln in textLines ) <EOL> isLast = ( colIdx == TextLineItem . NUM_COLUMNS - <NUM_LIT:1> ) <EOL> if not isLast : <EOL> w += TextLineItem . COLUMN_SPACING <EOL> return w <EOL> @ staticmethod <EOL> def updateColWidths ( textLines ) : <EOL> colWidths = [ TextLineItem . _getColWidth ( i , textLines ) <EOL> for i in xrange ( TextLineItem . NUM_COLUMNS ) ] <EOL> x = <NUM_LIT:0> <EOL> for i , w in enumerate ( colWidths ) : <EOL> for textln in textLines : <EOL> textln . items [ i ] . setPos ( x , <NUM_LIT:0> ) <EOL> x += w <EOL> class SonareTextScene ( QGraphicsScene ) : <EOL> HORIZ_MARGIN = VERT_MARGIN = <NUM_LIT> <EOL> EXTRA_LINES = <NUM_LIT:10> <EOL> def __init__ ( self , mainWin ) : <EOL> QGraphicsScene . __init__ ( self ) <EOL> self . mainWin = mainWin <EOL> self . setBackgroundBrush ( mainWin . WINDOW_COLOR ) <EOL> self . font = QFont ( "<STR_LIT>" , <NUM_LIT:8> ) <EOL> self . lineSpacing = QFontMetricsF ( self . font ) . lineSpacing ( ) <EOL> self . textLines = deque ( ) <EOL> self . gotoAddr ( <NUM_LIT:0> ) <EOL> def gotoAddr ( self , addr ) : <EOL> self . clear ( ) <EOL> self . textLines . clear ( ) <EOL> size = self . mainWin . core . nextAddr ( addr ) - addr <EOL> item = self . _makeLine ( <NUM_LIT:0> , addr , size ) <EOL> self . addItem ( item ) <EOL> self . textLines . append ( item ) <EOL> for v in self . views ( ) : <EOL> v . centerOn ( item . x ( ) , item . y ( ) ) <EOL> @ property <EOL> def curTop ( self ) : <EOL> return self . textLines [ <NUM_LIT:0> ] . y ( ) <EOL> @ property <EOL> def curBottom ( self ) : <EOL> return self . textLines [ - <NUM_LIT:1> ] . y ( ) + self . lineSpacing <EOL> def _makeLine ( self , y , addr , size ) : <EOL> asmOp = self . mainWin . core . getAsmOp ( addr ) <EOL> item = TextLineItem ( self . mainWin , addr , size , asmOp , self . font ) <EOL> item . setPos ( <NUM_LIT:0> , y ) <EOL> return item <EOL> def setLines ( self , top , bottom ) : <EOL> linesChanged = False <EOL> extraY = self . EXTRA_LINES * self . lineSpacing <EOL> while self . curTop >= top - extraY : <EOL> oldTopAddr = self . textLines [ <NUM_LIT:0> ] . addr <EOL> addr = self . mainWin . core . prevAddr ( oldTopAddr ) <EOL> size = oldTopAddr - addr <EOL> item = self . _makeLine ( self . curTop - self . lineSpacing , addr , size ) <EOL> self . addItem ( item ) <EOL> self . textLines . appendleft ( item ) <EOL> linesChanged = True <EOL> while self . curBottom <= bottom + extraY : <EOL> addr = self . textLines [ - <NUM_LIT:1> ] . addr + self . textLines [ - <NUM_LIT:1> ] . size <EOL> size = self . mainWin . core . nextAddr ( addr ) - addr <EOL> item = self . _makeLine ( self . curBottom , addr , size ) <EOL> self . addItem ( item ) <EOL> self . textLines . append ( item ) <EOL> linesChanged = True <EOL> while self . curTop < top - extraY : <EOL> self . removeItem ( self . textLines . popleft ( ) ) <EOL> linesChanged = True <EOL> while self . curBottom > bottom + extraY : <EOL> self . removeItem ( self . textLines . pop ( ) ) <EOL> linesChanged = True <EOL> if linesChanged : <EOL> TextLineItem . updateColWidths ( self . textLines ) <EOL> class SonareTextView ( QGraphicsView ) : <EOL> linesUpdated = pyqtSignal ( [ int , int ] ) <EOL> def __init__ ( self , mainWin ) : <EOL> self . scene = SonareTextScene ( mainWin ) <EOL> QGraphicsView . __init__ ( self , self . scene ) <EOL> self . setRenderHints ( <EOL> QPainter . Antialiasing <EOL> | QPainter . TextAntialiasing <EOL> | QPainter . SmoothPixmapTransform <EOL> | QPainter . HighQualityAntialiasing ) <EOL> self . linesUpdated . connect ( self . scene . setLines ) <EOL> def getYRange ( self ) : <EOL> sceneViewPoly = self . mapToScene ( self . viewport ( ) . rect ( ) ) <EOL> r = sceneViewPoly . boundingRect ( ) <EOL> return ( r . top ( ) , r . bottom ( ) ) <EOL> def resizeEvent ( self , evt ) : <EOL> QGraphicsView . resizeEvent ( self , evt ) <EOL> self . _emitLinesSignal ( ) <EOL> def scrollContentsBy ( self , dx , dy ) : <EOL> QGraphicsView . scrollContentsBy ( self , dx , dy ) <EOL> self . _emitLinesSignal ( ) <EOL> def _emitLinesSignal ( self ) : <EOL> y0 , y1 = self . getYRange ( ) <EOL> self . linesUpdated . emit ( y0 , y1 ) <EOL> def gotoAddr ( self , addr ) : <EOL> self . scene . gotoAddr ( addr ) </s>
