import sys, os, logging
from FileFormat import *
import Banners
import pefile
from TextDecorators import *
import TextSelection

import PyQt5
from PyQt5 import QtGui, QtCore, QtWidgets
from cemu import *
import time

import DisasmViewMode

logger = logging.getLogger(__name__)

class PE(FileFormat):
    name = 'pe'
    priority = 5

    DisplayTypes = ['VA', 'RVA', 'FA']

    def recognize(self, dataModel):
        self.dataModel = dataModel

        try:
            self.PE = pefile.PE(data=dataModel.getData())
        except:
            return False
        
        return True


    def getVA(self, offset):
        ofs = self.PE.get_rva_from_offset(offset)

        if ofs is None:
            return None

        return ofs + self.PE.OPTIONAL_HEADER.ImageBase

    def changeAddressMode(self):
        self.DisplayTypes = self.DisplayTypes[1:] + [self.DisplayTypes[0]]

    def getAddressMode(self):
        return self.DisplayTypes[0]

    def init(self, viewMode, parent):
        self._viewMode = viewMode
        self.viewMode = viewMode        

        start = self.PE.get_overlay_data_start_offset()

        self.MZbrush = QtGui.QBrush(QtGui.QColor(128, 0, 0))
        self.greenPen = QtGui.QPen(QtGui.QColor(255, 255, 0))
        self.grayBrush = QtGui.QBrush(QtGui.QColor(128, 128, 128))
        self.whitePen = QtGui.QPen(QtGui.QColor(255, 255, 255))        


        self.textDecorator = TextDecorator(viewMode)
        self.textDecorator = HighlightASCII(self.textDecorator)
        self.textDecorator = HighlightPrefix(self.textDecorator, 'MZ', brush=self.MZbrush, pen=self.greenPen)
        self.textDecorator = HighlightPrefix(self.textDecorator, 'PE\x00\x00', brush=self.MZbrush, pen=self.greenPen)
        self.textDecorator = HighlightPrefix(self.textDecorator, '\xFF\x15', additionalLength=4, brush=self.grayBrush, pen=self.whitePen)
        self.textDecorator = HighlightWideChar(self.textDecorator)

        ep = self.PE.get_offset_from_rva(self.PE.OPTIONAL_HEADER.AddressOfEntryPoint)
        self.viewMode.selector.addSelection((ep, ep + 30, QtGui.QBrush(QtGui.QColor(51, 153, 255)), 0.5), type=TextSelection.SelectionType.PERMANENT)

        if start:
            # overlay
            self.textDecorator = RangePen(self.textDecorator, start, start + self.dataModel.getDataSize(), QtGui.QPen(QtGui.QColor(128, 128, 128), 0, QtCore.Qt.SolidLine), ignoreHighlights=False)

        for d in self.PE.OPTIONAL_HEADER.DATA_DIRECTORY:
            if d.Size != 0:
                if d.name == 'IMAGE_DIRECTORY_ENTRY_IAT':
                    start = self.PE.get_offset_from_rva(d.VirtualAddress)
                    size  = d.Size
                    self.textDecorator = RangePen(self.textDecorator, start, start + size, QtGui.QPen(QtGui.QColor(0, 200, 0), 0, QtCore.Qt.SolidLine), ignoreHighlights=False)                    

        self.viewMode.setTransformationEngine(self.textDecorator)
        
    def hintDisasm(self):

        if self.PE.FILE_HEADER.Machine & pefile.MACHINE_TYPE['IMAGE_FILE_MACHINE_AMD64'] == pefile.MACHINE_TYPE['IMAGE_FILE_MACHINE_AMD64']:
            return DisasmViewMode.Disasm_x86_64bit

        if self.PE.FILE_HEADER.Machine & pefile.MACHINE_TYPE['IMAGE_FILE_MACHINE_I386'] == pefile.MACHINE_TYPE['IMAGE_FILE_MACHINE_I386']:
            return DisasmViewMode.Disasm_x86_32bit

        return DisasmViewMode.Disasm_x86_32bit

    def hintDisasmVA(self, offset):
        return self.getVA(offset)

    def hintBanner(self, offset):
        if offset >= self.PE.DOS_HEADER.get_file_offset() and offset < self.PE.DOS_HEADER.sizeof():
            name = 'DOS header'
            return name

        base = self.PE.FILE_HEADER.get_file_offset()
        if offset >= base and offset < base + self.PE.FILE_HEADER.sizeof():
            name = 'File header'
            return name

        base = self.PE.OPTIONAL_HEADER.get_file_offset()
        end = base + self.PE.OPTIONAL_HEADER.sizeof() + len(self.PE.OPTIONAL_HEADER.DATA_DIRECTORY) * 8


        if offset >= base and offset < end:
            name = 'Opt. header'
            return name

        # section headers
        if offset >= end and offset < (end + len(self.PE.sections) * 0x28):
            name = 'Section header'
            return name

        DirectoryNames = ['Export', 'Import', 'Resource', 'Exception', 'Security', 'BaseReloc', 'Debug', 'Copyright', 'GlobalPtr', 'TLS', 'LoadConfig', 'BoundImport', 'IAT',
                          'DelayedImports', 'COM Descr.', 'Reserved']

        end += len(self.PE.sections) * 0x28
        for i, o in enumerate(self.PE.OPTIONAL_HEADER.DATA_DIRECTORY):
            if o.VirtualAddress != 0 and o.Size != 0:
                s = self.PE.get_offset_from_rva(o.VirtualAddress)
                e = s + o.Size
                if offset >= s and offset < e:
                    name = DirectoryNames[i]
                    return name


        if self.PE.get_overlay_data_start_offset() is not None:
            if offset >= self.PE.get_overlay_data_start_offset():
                name = 'Overlay'
                return name

        name = self.PE.get_section_by_offset(offset)
        if name is None:
            name = ''
        else:
            name = name.Name
            
        return name

    def stringFromVA(self, va):
        try:
           offset = self.PE.get_offset_from_rva(va - self.PE.OPTIONAL_HEADER.ImageBase)
        except:
            return ''

        doit = True
        s = bytearray()
        data = self.dataModel

        import string
        Special = (string.ascii_letters + string.digits + ' .;\':;=\"?-!()/\\_').encode('cp437')
        while doit:
            c = data.getChar(offset)

            if not c:
                break

            if c in Special:
                s.append(c)
                offset += 1

                c1 = data.getChar(offset)
                c2 = data.getChar(offset+1)
                if not c1 or not c2:
                    break

                if c1 == '\0' and c2 in Special:
                    offset += 1
            else:
                doit = False

        return s.decode('cp437')

    def disasmVAtoFA(self, va):
        try:
            offset = self.PE.get_offset_from_rva(va - self.PE.OPTIONAL_HEADER.ImageBase)
        except:
            return None

        return offset

    def disasmSymbol(self, va):
        if not hasattr(self.PE, 'DIRECTORY_ENTRY_IMPORT'):
            return None

        # TODO: should implement with a lookup table
        for i, entry in enumerate(self.PE.DIRECTORY_ENTRY_IMPORT):

            for imp in entry.imports:
                if imp.address == va:
                    name = ''
                    if imp.name:
                        name = imp.name

                    if imp.ordinal:
                        name = bytes(imp.ordinal)

                    return '{0}:{1}'.format(entry.dll.decode('cp437'), name.decode('cp437'))

        return None




    def getBanners(self):
        self.banners = [PEBanner(self.dataModel, self.viewMode, self), PEHeaderBanner(self.dataModel, self.viewMode, self), PEBottomBanner(self.dataModel, self.viewMode, self)]
        return self.banners
   
    def writeData(self, w):

        if hasattr(self.PE, 'FileInfo'):
            for f in self.PE.FileInfo:
                if f.Key == 'StringFileInfo':
                    for st in f.StringTable:
                        for entry in st.entries:
                            #print entry
                            w.ui.tableWidget_2.setColumnWidth(0, 300)                        
                            if entry == 'CompanyName':
                                w.ui.tableWidget_2.setItem(0, 0, QtWidgets.QTableWidgetItem(st.entries[entry]))

                            if entry == 'FileDescription':
                                w.ui.tableWidget_2.setItem(0, 1, QtWidgets.QTableWidgetItem(st.entries[entry]))

                            if entry == 'FileVersion':
                                w.ui.tableWidget_2.setItem(0, 2, QtWidgets.QTableWidgetItem(st.entries[entry]))

                            if entry == 'LegalCopyright':
                                w.ui.tableWidget_2.setItem(0, 3, QtWidgets.QTableWidgetItem(st.entries[entry]))

                            if entry == 'OriginalFilename':
                                w.ui.tableWidget_2.setItem(0, 4, QtWidgets.QTableWidgetItem(st.entries[entry]))

                            if entry == 'ProductName':
                                w.ui.tableWidget_2.setItem(0, 5, QtWidgets.QTableWidgetItem(st.entries[entry]))

                            if entry == 'ProductVersion':
                                w.ui.tableWidget_2.setItem(0, 6, QtWidgets.QTableWidgetItem(st.entries[entry]))



        
        if self.PE.is_exe():
            petype = 'EXE'
        elif self.PE.is_dll():
            petype = 'DLL'
        elif self.PE.is_driver():
            petype = 'Driver'
        else:
            petype = 'n/a'

        w.ui.tableWidget.setItem(0, 0, QtWidgets.QTableWidgetItem(petype))
        w.ui.tableWidget.setItem(1, 0, QtWidgets.QTableWidgetItem('{:,} bytes'.format(self.dataModel.getDataSize())))

        # add exports
        parent = w.ui.treeWidgetExports
        parent.setColumnWidth(0, 300) 

      
        if hasattr(self.PE, 'DIRECTORY_ENTRY_EXPORT'):
            try:
                rva = self.PE.get_offset_from_rva(self.PE.DIRECTORY_ENTRY_EXPORT.struct.Name)

                # very ygly, i know
                s = ''
                c = 'z'
                k = 0
                while c != '\0' and k < 50:
                    c = chr(self.dataModel.getBYTE(rva))
                    s += c
                    rva += 1
                    k += 1


                child = QtWidgets.QTreeWidgetItem(None)
                child.setText(0, s)

                parent.addTopLevelItem(child)
                parent.expandItem(child)
                
                for i, exp in enumerate(self.PE.DIRECTORY_ENTRY_EXPORT.symbols):

                    child = QtWidgets.QTreeWidgetItem(None)

                    if exp.name:
                        child.setText(0, exp.name)
                        child.setText(1, '0x{0:X}'.format(exp.address))

                        #parent.topLevelItem(i).addChild(child)

                        #parent.topLevelItem(i).addChild(child)
                    
                    parent.topLevelItem(0).addChild(child)

            except Exception as e:
                logger.error(e, exc_info=1)

        # add imports
        parent = w.ui.treeWidgetImports
        parent.setColumnWidth(0, 300) 
        try:
            for i, entry in enumerate(self.PE.DIRECTORY_ENTRY_IMPORT):
                
                child = QtWidgets.QTreeWidgetItem(None)
                child.setText(0, entry.dll.decode('cp437'))
                parent.addTopLevelItem(child)

                for imp in entry.imports:
                    child = QtWidgets.QTreeWidgetItem(None)
                    if imp.name:
                        child.setText(0, imp.name.decode('cp437'))
                        child.setText(1, '0x{0:X}'.format(imp.address-self.PE.OPTIONAL_HEADER.ImageBase))

                        parent.topLevelItem(i).addChild(child)

                    if imp.ordinal:
                        child.setText(0, 'ordinal:{0}'.format(imp.ordinal))
                        child.setText(1, '0x{0:X}'.format(imp.address-self.PE.OPTIONAL_HEADER.ImageBase))

                        parent.topLevelItem(i).addChild(child)
        except Exception as e:
            logger.error(e, exc_info=1)

        # populate with sections
        parent = w.ui.treeWidgetSections
        parent.setColumnWidth(0, 100) 
        parent.setColumnWidth(1, 80) 
        parent.setColumnWidth(2, 80) 
        parent.setColumnWidth(3, 80) 
        parent.setColumnWidth(4, 80)        

        for section in self.PE.sections:
            child  = QtWidgets.QTreeWidgetItem(None)
            child.setText(0, section.Name.decode('cp437'))
            child.setText(1, '{0:X}'.format(section.PointerToRawData))
            child.setText(2, '{0:X}'.format(section.SizeOfRawData))
            child.setText(3, '{0:X}'.format(section.VirtualAddress))
            child.setText(4, '{0:X}'.format(section.Misc_VirtualSize))

            child.setForeground(1, QtGui.QColor('green'))
            child.setForeground(2, QtGui.QColor('green'))


            child.setForeground(3, QtGui.QColor(183, 72, 197))
            child.setForeground(4, QtGui.QColor(183, 72, 197))
            
            # build characteristics string for every section
            fr = 'R' if section.IMAGE_SCN_MEM_READ else '-'
            fw = 'W' if section.IMAGE_SCN_MEM_WRITE else '-'
            fe = 'E' if section.IMAGE_SCN_MEM_EXECUTE else '-'

            fc = 'C' if section.IMAGE_SCN_CNT_CODE else '-'
            fi = 'I' if section.IMAGE_SCN_CNT_INITIALIZED_DATA else '-'
            fu = 'U' if section.IMAGE_SCN_CNT_UNINITIALIZED_DATA else '-'


            
            child.setText(5, '{0:X} {1}'.format(section.Characteristics, '[{0}{1}{2}  {3}{4}{5}]'.format(fr, fw, fe, fc, fi, fu)))

            for i in range(6)[1:]:
                child.setTextAlignment(i, QtCore.Qt.AlignRight)

            parent.addTopLevelItem(child)


        # populate with directories
        parent = w.ui.treeWidgetDirectories
        parent.setColumnWidth(0, 150) 

        for d in self.PE.OPTIONAL_HEADER.DATA_DIRECTORY:
            child  = QtWidgets.QTreeWidgetItem(None)
            child.setText(0, d.name.replace('IMAGE_DIRECTORY_ENTRY_', ''))

            if d.VirtualAddress != 0 and d.Size != 0:
                for i, section in enumerate(self.PE.sections):
                    if section.contains_rva(d.VirtualAddress):
                        child.setText(1, '{0} [{1}]'.format(section.Name.decode('cp437').strip('\0'), i))
                        child.setForeground(1, QtGui.QColor('red'))
                        break
                else:
                    child.setText(1, '{0}'.format('<outside>'))


                child.setText(2, '{0:X}'.format(d.VirtualAddress))
                child.setText(3, '{0:X}'.format(d.Size))
                child.setForeground(2, QtGui.QColor('green'))
                child.setForeground(3, QtGui.QColor('green'))
            else:
                child.setForeground(0, QtGui.QColor('lightgray'))

            parent.addTopLevelItem(child)

            for i in range(4)[1:]:
                child.setTextAlignment(i, QtCore.Qt.AlignRight)



        # populate Header
        parent = w.ui.treeWidgetHeader
        parent.setColumnWidth(0, 250) 

        bkbrush = QtGui.QBrush(QtGui.QColor(192, 165, 194))
        bkbrush2 = QtGui.QBrush(QtGui.QColor(232, 194, 229))

        child = QtWidgets.QTreeWidgetItem(None)

        child.setText(0, 'IMAGE_DOS_HEADER')
        child.setBackground(0, bkbrush)

        ch2 = QtWidgets.QTreeWidgetItem(['magic', 'word', '{0:X}'.format(int(self.PE.DOS_HEADER.e_magic))])
        ch2.setForeground(2, QtGui.QColor('green'))
        ch2.setForeground(1, QtGui.QColor(183, 72, 197))
        child.addChild(ch2)

        ch2 = QtWidgets.QTreeWidgetItem(['e_lfanew', 'word', '{0:X}'.format(int(self.PE.DOS_HEADER.e_lfanew))])
        ch2.setForeground(2, QtGui.QColor('green'))
        ch2.setForeground(1, QtGui.QColor(183, 72, 197))
        child.addChild(ch2)

        parent.addTopLevelItem(child)


        item = QtWidgets.QTreeWidgetItem(['IMAGE_NT_HEADERS'])
        item.setBackground(0, bkbrush)

        child = QtWidgets.QTreeWidgetItem(['Signature', 'word',  '{0:X}'.format(int(self.PE.NT_HEADERS.Signature))])
        child.setForeground(2, QtGui.QColor('green'))
        child.setForeground(1, QtGui.QColor(183, 72, 197))

        item.addChild(child)

        subitem = QtWidgets.QTreeWidgetItem(['IMAGE_FILE_HEADER'])
        subitem.setBackground(0, bkbrush2)

        child = QtWidgets.QTreeWidgetItem(['Machine', 'word',  '{0:X}'.format(int(self.PE.FILE_HEADER.Machine))])
        child.setForeground(2, QtGui.QColor('green'))
        child.setForeground(1, QtGui.QColor(183, 72, 197))

        subitem.addChild(child)

        child = QtWidgets.QTreeWidgetItem(['NumberOfSections', 'word',  '{0:X}'.format(int(self.PE.FILE_HEADER.NumberOfSections))])
        child.setForeground(2, QtGui.QColor('green'))
        child.setForeground(1, QtGui.QColor(183, 72, 197))

        subitem.addChild(child)

        child = QtWidgets.QTreeWidgetItem(['TimeDateStamp', 'dword',  '{0:X}'.format(int(self.PE.FILE_HEADER.TimeDateStamp))])
        child.setForeground(2, QtGui.QColor('green'))
        child.setForeground(1, QtGui.QColor(183, 72, 197))

        subitem.addChild(child)

        child = QtWidgets.QTreeWidgetItem(['Characteristics', 'dword',  '{0:X}'.format(int(self.PE.FILE_HEADER.Characteristics))])
        child.setForeground(2, QtGui.QColor('green'))
        child.setForeground(1, QtGui.QColor(183, 72, 197))

        subitem.addChild(child)
        item.addChild(subitem)


        subitem = QtWidgets.QTreeWidgetItem(['IMAGE_OPTIONAL_HEADER'])
        subitem.setBackground(0, bkbrush2)

        Data = [['Magic', 'word',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.Magic))],
                ['SizeOfCode', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.SizeOfCode))],
                ['SizeOfInitializedData', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.SizeOfInitializedData))],
                ['SizeOfUninitializedData', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.SizeOfUninitializedData))],
                ['AddressOfEntryPoint', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.AddressOfEntryPoint))],
                ['BaseOfCode', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.BaseOfCode))],
                ['ImageBase', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.ImageBase))],
                ['SectionAlignment', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.SectionAlignment))],
                ['FileAlignment', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.FileAlignment))],
                ['SizeOfImage', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.SizeOfImage))],
                ['SizeOfHeaders', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.SizeOfHeaders))],
                ['CheckSum', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.CheckSum))],
                ['Magic', 'word',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.Magic))],
                ['SizeOfCode', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.SizeOfCode))],
                ['SizeOfInitializedData', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.SizeOfInitializedData))],
                ['SizeOfUninitializedData', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.SizeOfUninitializedData))],
                ['AddressOfEntryPoint', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.AddressOfEntryPoint))],
                ['BaseOfCode', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.BaseOfCode))],
                ['ImageBase', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.ImageBase))],
                ['SectionAlignment', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.SectionAlignment))],
                ['FileAlignment', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.FileAlignment))],
                ['SizeOfImage', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.SizeOfImage))],
                ['SizeOfHeaders', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.SizeOfHeaders))],
                ['CheckSum', 'dword',  '{0:X}'.format(int(self.PE.OPTIONAL_HEADER.CheckSum))]]

        for it in Data:
            child = QtWidgets.QTreeWidgetItem(it)

            child.setForeground(2, QtGui.QColor('green'))
            child.setForeground(1, QtGui.QColor(183, 72, 197))

            subitem.addChild(child)


        child = QtWidgets.QTreeWidgetItem(['IMAGE_DATA_DIRECTORY [16]'])
        child.setBackground(0, bkbrush2)

        for i, d in enumerate(self.PE.OPTIONAL_HEADER.DATA_DIRECTORY):
            subchild = QtWidgets.QTreeWidgetItem(['[{0}] {1}'.format(i, d.name.replace('IMAGE_DIRECTORY_ENTRY_', ''))])
            if d.VirtualAddress == 0 and d.Size == 0:
                subchild.setForeground(0, QtGui.QColor('lightgray'))

            c = QtWidgets.QTreeWidgetItem(['VirtualAddress', 'dword', '{0:X}'.format(int(d.VirtualAddress))])
            c.setForeground(2, QtGui.QColor('green'))
            c.setForeground(1, QtGui.QColor(183, 72, 197))
            subchild.addChild(c)

            c = QtWidgets.QTreeWidgetItem(['Size', 'dword', '{0:X}'.format(int(d.Size))])
            c.setForeground(2, QtGui.QColor('green'))
            c.setForeground(1, QtGui.QColor(183, 72, 197))
            subchild.addChild(c)

            child.addChild(subchild)


        subitem.addChild(child)

        item.addChild(subitem)


        parent.addTopLevelItem(item) # NT_HEADERS


        _item =  QtWidgets.QTreeWidgetItem(['{0}'.format('IMAGE_SECTION_HEADERS []')])
        parent.addTopLevelItem(_item)

        for i, section in enumerate(self.PE.sections):
            item =  QtWidgets.QTreeWidgetItem(['{0} [{1}]'.format('SECTION_HEADER', i)])
            item.setBackground(0, bkbrush)

            Data = [['Name', 'char[8]',  section.Name.decode('cp437')],
                    ['VirtualSize', 'dword',  '{0:X}'.format(int(section.Misc_VirtualSize))],
                    ['VirtualAddress', 'dword',  '{0:X}'.format(int(section.VirtualAddress))],
                    ['SizeOfRawData', 'dword',  '{0:X}'.format(int(section.SizeOfRawData))],
                    ['PointerToRawData', 'dword',  '{0:X}'.format(int(section.PointerToRawData))],
                    ['Characteristics', 'dword',  '{0:X}'.format(int(section.Characteristics))]
            ]

            for data in Data:
                child = QtWidgets.QTreeWidgetItem(data)
                child.setForeground(2, QtGui.QColor('green'))
                child.setForeground(1, QtGui.QColor(183, 72, 197))

                item.addChild(child)

            _item.addChild(item)



        #print self.PE


        """
        

        parent = w.ui.treeWidget


        # add sections

        for section in self.PE.sections:
            child  = QtWidgets.QTreeWidgetItem(None)            
            child.setText(0, section.Name)            
            parent.topLevelItem(3).addChild(child)
        """

    def doit(self):
        if not self.w.isVisible():
            #self.w.setModal(True)
            self.w.show()
            #self._parent.releaseKeyboard()  #TODO: ugly
            #self.w.activateWindow()
            self.w.ui.treeWidgetHeader.setFocus()
            self.w.ui.treeWidgetHeader.activateWindow()

  #          self.writeData(self.w)


        else:

            #self._parent.grabKeyboard()
            #self._parent.activateWindow()
            #self._viewMode.grabKeyboard()
            #self._viewMode.activateWindow()
            #self.w.releaseKeyboard()
            self.w.hide()

    def shortVersionInfo(self):
        if not self.w.isVisible():
            self.w.show()
            self.w.ui.tableWidget_2.setFocus()
            self.w.ui.tableWidget_2.activateWindow()
            self.w.ui.tabWidget.setCurrentIndex(4)
 #           self.writeData(self.w)


        else:
            self.w.hide()


    def shortHeader(self):
        if not self.w.isVisible():
            self.w.show()
            self.w.ui.tableWidget_2.setFocus()
            self.w.ui.tableWidget_2.activateWindow()
            self.w.ui.tabWidget.setCurrentIndex(0)
 #           self.writeData(self.w)


        else:
            self.w.hide()

    def shortExports(self):
        if not self.w.isVisible():
            self.w.show()
            self.w.ui.tableWidget_2.setFocus()
            self.w.ui.tableWidget_2.activateWindow()
            self.w.ui.tabWidget.setCurrentIndex(4)
            self.w.ui.treeWidgetExports.setFocus()
 #           self.writeData(self.w)


        else:
            self.w.hide()

    def shortImports(self):
        if not self.w.isVisible():
            self.w.show()
            self.w.ui.tableWidget_2.setFocus()
            self.w.ui.tableWidget_2.activateWindow()
            self.w.ui.tabWidget.setCurrentIndex(3)
            self.w.ui.treeWidgetImports.setFocus()
 #           self.writeData(self.w)


        else:
            self.w.hide()

    def shortSections(self):
        if not self.w.isVisible():
            self.w.show()
            self.w.ui.tableWidget_2.setFocus()
            self.w.ui.tableWidget_2.activateWindow()
            self.w.ui.tabWidget.setCurrentIndex(1)
            self.w.ui.treeWidgetSections.setFocus()
#            self.writeData(self.w)


        else:
            self.w.hide()

    def shortDirectories(self):
        if not self.w.isVisible():
            self.w.show()
            self.w.ui.tableWidget_2.setFocus()
            self.w.ui.tableWidget_2.activateWindow()
            self.w.ui.tabWidget.setCurrentIndex(2)
            self.w.ui.treeWidgetDirectories.setFocus()
#            self.writeData(self.w)


        else:
            self.w.hide()

    def F7(self):
        offset = self.PE.get_offset_from_rva(self.PE.OPTIONAL_HEADER.AddressOfEntryPoint)
        self._viewMode.goTo(offset)


    def F3(self):
        self.changeAddressMode()

        self._parent.update()

    def skip_chars(self):

        off = self._viewMode.getCursorAbsolutePosition()

        x = off + 1

        sizeOfData = self.dataModel.getDataSize()
        if x >= sizeOfData:
            return

        # skip bytes of current value
#        import time

        BYTES = 512
#        k = time.time()
        b = self.dataModel.getStream(off, off + 1)
        z = b * BYTES

        # compare stream of bytes
        z = self.dataModel.getStream(off, off+BYTES)
        while x < sizeOfData - BYTES and self.dataModel.getStream(x, x + BYTES) == z:
            x += BYTES

        while x < sizeOfData - 1 and self.dataModel.getBYTE(x) == ord(b):
            x += 1

#        print time.time() - k

        self._viewMode.goTo(x)


    def skip_block(self):

        off = self._viewMode.getCursorAbsolutePosition()

        x = off

        sizeOfData = self.dataModel.getDataSize()
        if x >= sizeOfData:
            return

        x = self.dataModel.getData().find(b'\x00'*8, off)
        if x == -1:
            x = off


        if x == off:
            if x < sizeOfData - 1:
                x += 1

        self._viewMode.goTo(x)

        return
        # skip bytes of current value

        #k = time.time()

        """
        # slower
        while x < sizeOfData - 8 and self.dataModel.getQWORD(x) != 0:
            b = self.dataModel.getQWORD(x)
            lastb = b & -b

                              
            pos = 0
            if lastb & 0xFFFFFFFF == 0:
                lastb >>= 32
                pos += 4

            if lastb & 0xFFFF == 0:
                lastb >>=  16
                pos += 2

            if lastb & 0xFF == 0:
                lastb >>= 8
                pos += 1

            x += (8 - pos + 1)

        if x == off:
            if x < sizeOfData - 1:
                x += 1

        self._viewMode.goTo(x)
        """

    def jump_overlay(self):
        overlay = self.PE.get_overlay_data_start_offset()
        if overlay:
            self._viewMode.goTo(overlay)

    def skip_section_up(self):
        # cursor pozition in datamodel
        off = self._viewMode.getCursorAbsolutePosition()
        x = off
        
        # get section represented by offset
        section = self.PE.get_section_by_offset(off)

        if section is None:
            # if it's not in a section, find it
            while off < self.dataModel.getDataSize() and self.PE.get_section_by_offset(off) is None:
                off += 1

            section = self.PE.get_section_by_offset(off)

            if section:
                # if found, go to begining
                x = section.PointerToRawData
            else:
                if off == self.dataModel.getDataSize():
                    # if eof, go to the end
                    x = self.dataModel.getDataSize() - 1
                else:
                    # don't know what to do
                    return

        else:
            # we found a section, go to the end + 1 (actually it's the next section physically in file)
            x =  section.PointerToRawData + section.SizeOfRawData

        self._viewMode.goTo(x)

    def skip_section_dw(self):
        # cursor pozition in datamodel
        off = self._viewMode.getCursorAbsolutePosition()

        # get section represented by offset
        section = self.PE.get_section_by_offset(off)
        x = off

        if section is None:
            # if it's not in a section, find it
            while off > 0 and self.PE.get_section_by_offset(off) is None:
                off -= 1

            section = self.PE.get_section_by_offset(off)

            if section:
                # if found, go to begining
                x = section.PointerToRawData
            else:
                if off == 0:
                    # if start of file, go to 0
                    x = off

        else:
            # we found a section, go to the preceding one
            if section.PointerToRawData >= 0:
                x =  section.PointerToRawData - 1
                section = self.PE.get_section_by_offset(x)
                if section:
                    x = section.PointerToRawData
                else:
                    x = 0

        self._viewMode.goTo(x)


    def _showGoto(self):
        if not self.dgoto.isVisible():
            self.dgoto.show()
        else:
            self.dgoto.hide()

    def registerShortcuts(self, parent):
        self.w = WHeaders(parent, self)
        self._parent = parent

        self._Shortcuts += [QtWidgets.QShortcut(QtGui.QKeySequence("Alt+H"), parent, self.doit, self.doit)]
        self._Shortcuts += [QtWidgets.QShortcut(QtGui.QKeySequence("Alt+V"), parent, self.shortVersionInfo, self.shortVersionInfo)]
        self._Shortcuts += [QtWidgets.QShortcut(QtGui.QKeySequence("Alt+H"), parent, self.shortHeader, self.shortHeader)]
        self._Shortcuts += [QtWidgets.QShortcut(QtGui.QKeySequence("Alt+I"), parent, self.shortImports, self.shortImports)]
        self._Shortcuts += [QtWidgets.QShortcut(QtGui.QKeySequence("Alt+E"), parent, self.shortExports, self.shortExports)]
        self._Shortcuts += [QtWidgets.QShortcut(QtGui.QKeySequence("Alt+S"), parent, self.shortSections, self.shortSections)]
        self._Shortcuts += [QtWidgets.QShortcut(QtGui.QKeySequence("Alt+D"), parent, self.shortDirectories, self.shortDirectories)]
        self._Shortcuts += [QtWidgets.QShortcut(QtGui.QKeySequence("F7"), parent, self.F7, self.F7)]
        self._Shortcuts += [QtWidgets.QShortcut(QtGui.QKeySequence("F3"), parent, self.F3, self.F3)]
        self._Shortcuts += [QtWidgets.QShortcut(QtGui.QKeySequence("s"), parent, self.skip_chars, self.skip_chars)]
        self._Shortcuts += [QtWidgets.QShortcut(QtGui.QKeySequence("e"), parent, self.skip_block, self.skip_block)]
        self._Shortcuts += [QtWidgets.QShortcut(QtGui.QKeySequence("["), parent, self.skip_section_dw, self.skip_section_dw)]
        self._Shortcuts += [QtWidgets.QShortcut(QtGui.QKeySequence("]"), parent, self.skip_section_up, self.skip_section_up)]
        self._Shortcuts += [QtWidgets.QShortcut(QtGui.QKeySequence("0"), parent, self.jump_overlay, self.jump_overlay)]

        self.writeData(self.w)

        self.dgoto = PEDialogGoto(parent, self)
        self._Shortcuts += [QtWidgets.QShortcut(QtGui.QKeySequence("Alt+G"), parent, self._showGoto, self._showGoto)]


# GoTo dialog (inheritance from FileFormat DialogGoto)
class PEDialogGoto(DialogGoto):
    def initUI(self):
        super(PEDialogGoto, self).initUI()
        self.ui.comboBox.clear()

        # for PE we support RVA/FileAddress/VA
        self.ui.comboBox.addItems(['RVA', 'FileAddress', 'VirtualAddress'])

        # we support some konstants EP/END (end of file)

        self.konstants = {'EP' : self.kEP, 
                          'END': self.kEND}

        self.GoTos = {'FileAddress' : self.fa, 'VirtualAddress' : self.va, 'RVA' : self.rva}
        
    # constants, calculate them in every way (where possible)
    def kEP(self, k):
        gtype = str(self.ui.comboBox.currentText())

        if gtype == 'RVA':
            return int(self.plugin.PE.OPTIONAL_HEADER.AddressOfEntryPoint)

        elif gtype == 'VirtualAddress':
            return int(self.plugin.PE.OPTIONAL_HEADER.AddressOfEntryPoint + self.plugin.PE.OPTIONAL_HEADER.ImageBase)

        elif gtype == 'FileAddress':
            return self.plugin.PE.get_offset_from_rva(self.plugin.PE.OPTIONAL_HEADER.AddressOfEntryPoint)
        else:
            return None

    def kEND(self, k):
        gtype = str(self.ui.comboBox.currentText())

        if gtype == 'FileAddress':
            return self.plugin.dataModel.getDataSize()

        elif gtype == 'VirtualAddress':
            offset = self.plugin.dataModel.getDataSize()
            return self.plugin.PE.get_rva_from_offset(offset) + self.plugin.PE.OPTIONAL_HEADER.ImageBase
        elif gtype == 'RVA':
            offset = self.plugin.dataModel.getDataSize()
            return self.plugin.PE.get_rva_from_offset(offset)
        else:
            return None

    # goto address type fa/va/rva
    def fa(self, result):
        return result

    def rva(self, rva):
        self.PE = self.plugin.PE
        try:
            result = self.PE.get_offset_from_rva(rva)
        except Exception as e:
            return None

        return result

    def va(self, va):
        self.PE = self.plugin.PE
        try:
            result = self.PE.get_offset_from_rva(va - self.PE.OPTIONAL_HEADER.ImageBase)
        except Exception as e:
            return None

        return result


class ImportsEventFilter(QtCore.QObject):
    def __init__(self, plugin, widget):
        super(QtCore.QObject, self).__init__()
        self.widget = widget
        self.plugin = plugin

    def eventFilter(self, watched, event):
        if event.type() == QtCore.QEvent.KeyPress:
            if event.key() == QtCore.Qt.Key_Return:

                # get RVA column from treeView
                item = self.widget.currentItem()
                rva = self.widget.indexFromItem(item, 1).data()
                if rva:
                    # strip 0x
                    rva = int(str(rva[2:]), 16)

                    offset = self.plugin.PE.get_offset_from_rva(rva)

                    self.plugin._viewMode.goTo(offset)

        return False

class ExportsEventFilter(QtCore.QObject):
    def __init__(self, plugin, widget):
        super(QtCore.QObject, self).__init__()
        self.widget = widget
        self.plugin = plugin

    def eventFilter(self, watched, event):
        if event.type() == QtCore.QEvent.KeyPress:
            if event.key() == QtCore.Qt.Key_Return:

                # get RVA column from treeView
                item = self.widget.currentItem()
                rva = self.widget.indexFromItem(item, 1).data()
                if rva:
                    rva = str(rva)
                    # strip 0x
                    rva = int(rva, 0)

                    offset = self.plugin.PE.get_offset_from_rva(rva)

                    self.plugin._viewMode.goTo(offset)

        return False


class SectionsEventFilter(QtCore.QObject):
    def __init__(self, plugin, widget):
        super(QtCore.QObject, self).__init__()
        self.widget = widget
        self.plugin = plugin

    def eventFilter(self, watched, event):
        if event.type() == QtCore.QEvent.KeyPress:
            if event.key() == QtCore.Qt.Key_Return:

                # get file-address column from treeView
                item = self.widget.currentItem()
                offset = self.widget.indexFromItem(item, 1).data()
                offset = int(str(offset), 16)

                self.plugin._viewMode.goTo(offset)

            if event.key() == QtCore.Qt.Key_F9:
                item = self.widget.currentItem()
                offset = self.widget.indexFromItem(item, 1).data()
                offset = int(str(offset), 16)

                size = self.widget.indexFromItem(item, 2).data()
                size = int(str(size), 16)

                self.plugin._viewMode.selector.addSelection((offset, offset+size), type=TextSelection.SelectionType.NORMAL)
                self.plugin._viewMode.goTo(offset)

        return False


class HeaderEventFilter(QtCore.QObject):
    def __init__(self, plugin, widget):
        super(QtCore.QObject, self).__init__()
        self.widget = widget
        self.plugin = plugin

    def eventFilter(self, watched, event):
        if event.type() == QtCore.QEvent.KeyPress:
            item = self.widget.currentItem()
            txt = self.widget.indexFromItem(item, 0).data()

            if event.key() == QtCore.Qt.Key_Return:

                if txt == 'IMAGE_DOS_HEADER':
                    offset = self.plugin.PE.DOS_HEADER.get_file_offset()
                    self.plugin._viewMode.goTo(offset)




            if event.key() == QtCore.Qt.Key_F9:

                if txt == 'IMAGE_DOS_HEADER':
                    offset = self.plugin.PE.DOS_HEADER.get_file_offset()
                    size = self.plugin.PE.DOS_HEADER.sizeof()

                if txt == 'IMAGE_NT_HEADERS':
                    offset = self.plugin.PE.NT_HEADERS.get_file_offset()
                    size = self.plugin.PE.NT_HEADERS.sizeof()

                if txt == 'IMAGE_FILE_HEADER':
                    offset = self.plugin.PE.FILE_HEADER.get_file_offset()
                    size = self.plugin.PE.FILE_HEADER.sizeof()

                if txt == 'IMAGE_OPTIONAL_HEADER':
                    offset = self.plugin.PE.OPTIONAL_HEADER.get_file_offset()
                    size = self.plugin.PE.OPTIONAL_HEADER.sizeof()

                if offset:
                    self.plugin._viewMode.goTo(offset)
                    self.plugin._viewMode.selector.addSelection((offset, offset+size), type=TextSelection.SelectionType.NORMAL)

        return False

class DirectoriesEventFilter(QtCore.QObject):
    def __init__(self, plugin, widget):
        super(QtCore.QObject, self).__init__()
        self.widget = widget
        self.plugin = plugin

    def eventFilter(self, watched, event):
        if event.type() == QtCore.QEvent.KeyPress:
            if event.key() == QtCore.Qt.Key_Return:

                # get file-address column from treeView
                item = self.widget.currentItem()
                offset = self.widget.indexFromItem(item, 2).data()
                if offset:
                    offset = int(str(offset), 16)
                    offset = self.plugin.PE.get_offset_from_rva(offset)

                    self.plugin._viewMode.goTo(offset)
                #self.plugin._viewMode.transformationEngine.makeSelection(Selection(0x1000+20, 0x1000+20+200, QtGui.QBrush(QtGui.QColor(100, 80, 0))))

            if event.key() == QtCore.Qt.Key_F9:
                item = self.widget.currentItem()
                offset = self.widget.indexFromItem(item, 2).data()
                size = self.widget.indexFromItem(item, 3).data()

                if offset and size:

                    offset = int(str(offset), 16)
                    size = int(str(size), 16)

                    offset = self.plugin.PE.get_offset_from_rva(offset)
                    #self.plugin._viewMode.transformationEngine.makeSelection(Selection(offset, offset + size, QtGui.QBrush(QtGui.QColor(100, 80, 0))))
                    self.plugin._viewMode.selector.addSelection((offset, offset+size), type=TextSelection.SelectionType.NORMAL)
                    self.plugin._viewMode.goTo(offset)

        return False


class WHeaders(QtWidgets.QDialog):
    
    def __init__(self, parent, plugin):
        super(WHeaders, self).__init__(parent)
        
        self.parent = parent
        self.plugin = plugin
        self.oshow = super(WHeaders, self).show

        root = os.path.dirname(sys.argv[0])
        self.ui = PyQt5.uic.loadUi(os.path.join(root, 'plugins', 'format','pe.ui'), baseinstance=self)

        self.ei = ImportsEventFilter(plugin, self.ui.treeWidgetImports)
        self.ui.treeWidgetImports.installEventFilter(self.ei)

        self.ee = ExportsEventFilter(plugin, self.ui.treeWidgetExports)
        self.ui.treeWidgetExports.installEventFilter(self.ee)

        self.es = SectionsEventFilter(plugin, self.ui.treeWidgetSections)
        self.ui.treeWidgetSections.installEventFilter(self.es)

        self.ed = DirectoriesEventFilter(plugin, self.ui.treeWidgetDirectories)
        self.ui.treeWidgetDirectories.installEventFilter(self.ed)

        self.eh = HeaderEventFilter(plugin, self.ui.treeWidgetHeader)
        self.ui.treeWidgetHeader.installEventFilter(self.eh)

        self.initUI()

    def show(self):

        # TODO: remember position? resize plugin windows when parent resize?
        pwidth = self.parent.parent.size().width()
        pheight = self.parent.parent.size().height()

        width = self.ui.tabWidget.size().width()+15
        height = self.ui.tabWidget.size().height()+15

        self.setGeometry(pwidth - width - 15, pheight - height, width, height)
        self.setFixedSize(width, height)

        self.oshow()

    def initUI(self):      

        self.setWindowTitle('PE plugin')
        self.setSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)

        shortcut = QtWidgets.QShortcut(QtGui.QKeySequence("Alt+F"), self, self.close, self.close)

    """
    def eventFilter(self, watched, event):
        if event.type() == QtCore.QEvent.KeyPress:
            #print 'da'
            key = event.key()
            modifiers = event.modifiers()
            if key == QtCore.Qt.Key_Left:
                print 'left'

                # new style?
                self._parent.scrolled.emit(2)

                # old style
                self._parent.emit(QtCore.SIGNAL('scroll'), 10)

                #self.plugin.dataModel.slidePage(1)
                #self.plugin._viewMode.scrollPages(1)                
                #self._parent.update()
                self.keyleft = True


        return True
    """        
#        self.setWindowFlags()

class PEBottomBanner(Banners.BottomBanner):
    def __init__(self, dataModel, viewMode, plugin):
        self.plugin = plugin
        super(PEBottomBanner, self).__init__(dataModel, viewMode)
        self.gray = QtGui.QPen(QtGui.QColor(128, 128, 128), 0, QtCore.Qt.SolidLine)
        self.yellow = self.textPen
        self.purple = QtGui.QPen(QtGui.QColor(172, 129, 255), 0, QtCore.Qt.SolidLine)
        self.editmode = QtGui.QPen(QtGui.QColor(255, 102, 179), 0, QtCore.Qt.SolidLine)
        self.viewmode = QtGui.QPen(QtGui.QColor(0, 153, 51), 0, QtCore.Qt.SolidLine)

    def draw(self):
        qp = QtGui.QPainter()
        qp.begin(self.qpix)

        qp.fillRect(0, 0, self.width,  self.height, self.backgroundBrush)
        qp.setPen(self.textPen)
        qp.setFont(self.font)

        cemu = ConsoleEmulator(qp, self.height//self.fontHeight, self.width//self.fontWidth)

        dword = self.dataModel.getDWORD(self.viewMode.getCursorAbsolutePosition(), asString=True)
        if dword is None:
            dword = '----'

        sd = 'DWORD: {0}'.format(dword)

        pos = 'POS: {0:08x}'.format(self.viewMode.getCursorAbsolutePosition())



        qword = self.dataModel.getQWORD(self.viewMode.getCursorAbsolutePosition(), asString=True)
        if qword is None:
            qword = '----'
        sq = 'QWORD: {0}'.format(qword)

        byte = self.dataModel.getBYTE(self.viewMode.getCursorAbsolutePosition(), asString=True)
        if byte is None:
            byte = '-'

        sb = 'BYTE: {0}'.format(byte)

        cemu.writeAt(1,  0, pos)
        if self.viewMode.isInEditMode():
            qp.setPen(self.editmode)
            cemu.writeAt(1, 1, '[edit mode]')
        else:
            qp.setPen(self.viewmode)
            cemu.writeAt(1,  1, '[view mode]')

        qp.setPen(self.yellow)
        cemu.writeAt(17, 0, sd)
        cemu.writeAt(35, 0, sq)
        cemu.writeAt(62, 0, sb)

        qp.drawLine(15 * self.fontWidth + 5, 0, 15 * self.fontWidth + 5, 50)
        qp.drawLine(33 * self.fontWidth + 5, 0, 33 * self.fontWidth + 5, 50)
        qp.drawLine(59 * self.fontWidth + 5, 0, 59 * self.fontWidth + 5, 50)
        qp.drawLine(71 * self.fontWidth + 5, 0, 71 * self.fontWidth + 5, 50)

        sel = None
        hint = self.plugin.hintBanner(self.viewMode.getCursorAbsolutePosition())
        qp.setPen(self.purple)
        cemu.writeAt(73, 1, hint)

        sel = '<no selection>'
        if self.viewMode.selector.getCurrentSelection():
            u, v = self.viewMode.selector.getCurrentSelection()
            if u != v:
                pen = QtGui.QPen(QtGui.QColor(51, 153, 255), 0, QtCore.Qt.SolidLine)
                qp.setPen(pen)

                #cemu.writeAt(73, 0, 'Selection: ')
                sel = 'Selection: {0:x}:{1}'.format(u, v-u)
                cemu.writeAt(73, 0, sel)
        else:
            pen = QtGui.QPen(QtGui.QColor(128, 128, 128), 0, QtCore.Qt.SolidLine)
            qp.setPen(pen)

            sel = '<no selection>'
            cemu.writeAt(73, 0, sel)

        off = 1
        if sel:
            off += len(sel)

        ovr_line_off = (73 + off) * self.fontWidth + 5

        qp.setPen(self.yellow)
        qp.drawLine(ovr_line_off, 0, ovr_line_off, 50)

        start = self.plugin.PE.get_overlay_data_start_offset()

        if start:
            qp.setPen(self.gray)
            overlay = 'overlay: {0:,} bytes'.format(start)

            if sel:
                off = 73 + 3 + len(sel)

            cemu.writeAt(off, 0, 'overlay: {0:,} bytes'.format(self.dataModel.size() - start))
            cemu.writeAt(off, 1, '         {0}%'.format((self.dataModel.size() - start)*100//self.dataModel.size()))
        
        qp.end()


class PEHeaderBanner(Banners.TopBanner):
    def __init__(self, dataModel, viewMode, peplugin):
        self.peplugin = peplugin
        super(PEHeaderBanner, self).__init__(dataModel, viewMode)

    def draw(self):
        qp = QtGui.QPainter()
        qp.begin(self.qpix)

        qp.fillRect(0, 0, self.width,  self.height, self.backgroundBrush)
        qp.setPen(self.textPen)
        qp.setFont(self.font)

        cemu = ConsoleEmulator(qp, self.height//self.fontHeight, self.width//self.fontWidth)

        cemu.writeAt(1, 0, 'Name')

        displayType = self.peplugin.getAddressMode()

        offset = 10
        if displayType == 'FA':
            offset = 13
        if displayType == 'RVA':
            offset = 13
        if displayType == 'VA':
            offset = 13

        cemu.writeAt(offset, 0, displayType)

        offset = 21 # for PE plugin !

        text = ''
        text = self.viewMode.getHeaderInfo()

        cemu.writeAt(offset, 0, text)
        
        qp.end()

class PEBanner(Banners.Banner):
    def __init__(self, dataModel, viewMode, peplugin):
        self.width = 0
        self.height = 0
        self.dataModel = dataModel
        self.viewMode = viewMode
        self.qpix = self._getNewPixmap(self.width, self.height)
        self.backgroundBrush = QtGui.QBrush(QtGui.QColor(0, 0, 128))

        self.peplugin = peplugin

        initPE = True
        try:
            self.PE = pefile.PE(data=dataModel.getData())
        except:
            initPE = False
        

        # text font
        self.font = QtGui.QFont('Terminus', 11, QtGui.QFont.Bold)

        # font metrics. assume font is monospaced
        self.font.setKerning(False)
        self.font.setFixedPitch(True)
        fm = QtGui.QFontMetrics(self.font)
        self.fontWidth  = fm.width('a')
        self.fontHeight = fm.height()

        self.textPen = QtGui.QPen(QtGui.QColor(192, 192, 192), 0, QtCore.Qt.SolidLine)


        if initPE == False:
            return

    def getOrientation(self):
        return Banners.Orientation.Left

    def getDesiredGeometry(self):
        return self.fontWidth*20# 160

    def setViewMode(self, viewMode):
        self.viewMode = viewMode

    def getPixmap(self):
        return self.qpix

    def _getNewPixmap(self, width, height):
        return QtGui.QPixmap(width, height)

    def draw(self):
        #for section in self.PE.sections:
        #    print section.PointerToRawData

        qp = QtGui.QPainter()

        offset = self.viewMode.getPageOffset()
        columns, rows = self.viewMode.getGeometry()

        qp.begin(self.qpix)
        qp.fillRect(0, 0, self.width,  self.height, self.backgroundBrush)
        qp.setPen(self.textPen)
        qp.setFont(self.font)
        
        for i in range(rows):
            s = '--------'
            
            columns = self.viewMode.getColumnsbyRow(i)

            section = self.PE.get_section_by_offset(offset)
            if section:
                s = section.Name.replace(b'\0', b' ').decode('cp437')

            displayType = self.peplugin.getAddressMode()
            if displayType == 'FA':
                sOff = ' {0:08x}'.format(offset)
            elif displayType == 'RVA':
                sOff = ' {0:08x}'.format(self.PE.get_rva_from_offset(offset))
            else:
                rva = self.PE.get_rva_from_offset(offset)
                if rva is not None:
                    sOff = '{0:08x}'.format(self.PE.get_rva_from_offset(offset) + self.PE.OPTIONAL_HEADER.ImageBase)
                    if len(sOff) == 8:
                        sOff = ' ' + sOff
                else:
                    # overlay for eg.
                    sOff = '  overlay'

            sDisplay = '{0} {1}'.format(s, sOff)
            qp.drawText(0+5, (i+1) * self.fontHeight, sDisplay)
            offset += columns
        

        qp.end()

    def resize(self, width, height):
        self.width = width
        self.height = height

        self.qpix = self._getNewPixmap(self.width, self.height)