Exemplo n.º 1
0
class MListWidget(QListWidget):
    '''Allows setting HTML items instead of just text.
    This is a nasty hack, unfortunately - thanks to some unfortunate Qt API decicions (QLabel inconsistently hides certain internals :( )
    '''
    gainedFocus = pyqtSignal()
    lostFocus = pyqtSignal()

    def __init__(self, parent = None):
        QListWidget.__init__(self, parent)

        self._htmlItemLabel = None
        self._htmlItemWidget = None
        self._htmlItemWidgetFinishedLoading = False

        self._prepHtmlItemWidget()

    #def focusInEvent(self, event):
        #self.gainedFocus.emit()
        #event.accept()
        #QListWidget.focusInEvent(self, event)
    
    #def focusOutEvent(self, event):
        #self.lostFocus.emit()
        #event.accept()
        #QListWidget.focusOutEvent(self, event)

    #def event(self, event):
        #if event.type() == QEvent.InputMethod:
            #print 'ionout pmethod'
            #self.inputMethodEvent(event)
        #elif event.type() == QEvent.KeyPress:
            #print 'key pressed'
        #return QListWidget.event(self, event)

    #@pyqtSignature('QInputMethodEvent')
    #def inputMethodEvent(self, event):
        #print 'custom input event!'
        #print event

    def event(self, event):
        '''Intercept enter/return presses.
        '''
        if event.type() == QEvent.KeyPress:
            key_press = QKeyEvent(event)
            if key_press.key() in [Qt.Key_Enter, Qt.Key_Return]:
                self.returnPressed.emit()
                return True
        return QListWidget.event(self, event)

    def _htmlItemWidgetLoadedSignal(self, ok):
        self._htmlItemWidgetFinishedLoading = True

    def _prepHtmlItemWidget(self):
        self._htmlItemWidget = QWebView()
        hw = self._htmlItemWidget

        hw.loadFinished.connect(self._htmlItemWidgetLoadedSignal)

        #TODO hw.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        #hw.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        # font
        ws = hw.settings()
        font_size = self.font().pointSize()
        ws.setFontSize(QWebSettings.DefaultFontSize, font_size)
        ws.setFontFamily(QWebSettings.StandardFont, self.font().family())

        # transparency
        palette = hw.palette()
        palette.setBrush(QPalette.Base, Qt.transparent)
        hw.page().setPalette(palette)
        hw.setAttribute(Qt.WA_OpaquePaintEvent, False)

        # better rendering
        hw.setRenderHint(QPainter.Antialiasing, True)
        hw.setRenderHint(QPainter.TextAntialiasing, True)
        hw.setRenderHint(QPainter.SmoothPixmapTransform, True)
        hw.setRenderHint(QPainter.HighQualityAntialiasing, True)

        hw.setHtml(u'')
        h = font_size + 6
        hw.setFixedHeight(h)
        


    def addHtmlItem(self, html, data):
        '''Adds a new QTextEdit widget containing the given HTMl as an item in the list.
        '''
        item = QListWidgetItem()
        item.setData(Qt.UserRole, data)
        self.addItem(item)
        item.setSizeHint(self._htmlItemWidget.frameSize())

        label = QLabel()
        label.setTextInteractionFlags(Qt.NoTextInteraction)

        html = u'<html><body style="margin:0px 0px 0px 4px">{0}</body></html>'.format(html)

        if '<img' in html:
            self._htmlItemWidgetFinishedLoading = False
            self._htmlItemWidget.setHtml(html)

            pm = QImage(self._htmlItemWidget.size(), QImage.Format_ARGB32)
            pm.fill(Qt.transparent)

            # wait for it to finish loading, then render
            q_app = QApplication.instance()
            while not self._htmlItemWidgetFinishedLoading:
                q_app.processEvents(QEventLoop.WaitForMoreEvents | QEventLoop.ExcludeUserInputEvents)
            
            self._htmlItemWidget.render(pm, flags=QWidget.DrawChildren)

            label.setPixmap(QPixmap.fromImage(pm))
        else:
            label.setText(html)
        
        self.setItemWidget(item, label)