from PyQt5.QtCore import Qt, QEvent, QT_VERSION_STR
from PyQt5.QtWidgets import QStyledItemDelegate, QStyleOptionButton, QStyle, QApplication


class PushButtonDelegateQt(QStyledItemDelegate):
    ''' 
    Delegate for a clickable button in a model view.
    Calls the model's setData() method when clicked, wherein the button clicked action should be handled.
    '''
    def __init__(self, text = "", parent = None):
        QStyledItemDelegate.__init__(self, parent)
        self.text = text
        self._isMousePressed = False


    def createEditor(self, parent, option, index):
        ''' 
        Important, otherwise an editor is created if the user clicks in this cell.
        '''
        return None


    def paint(self, painter, option, index):
        ''' 
        Draw button in cell.
        '''
        opts = QStyleOptionButton()
        opts.state |= QStyle.State_Active
        opts.state |= QStyle.State_Enabled
        if QT_VERSION_STR[0] == '4':
            opts.state |= (QStyle.State_Sunken if self._isMousePressed else QStyle.State_Raised)
        elif QT_VERSION_STR[0] == '5':
            # When raised in PyQt5, white text cannot be seen on white background.
            # Should probably fix this by initializing form styled button, but for now I'll just sink it all the time.
            opts.state |= QStyle.State_Sunken
        opts.rect = option.rect
        opts.text = self.text
        QApplication.style().drawControl(QStyle.CE_PushButton, opts, painter)


    def editorEvent(self, event, model, option, index):
        ''' 
        Handle mouse events in cell.
        On left button release in this cell, call model's setData() method,
            wherein the button clicked action should be handled.
        Currently, the value supplied to setData() is the button text, but this is arbitrary.
        '''
        if event.button() == Qt.LeftButton:
            if event.type() == QEvent.MouseButtonPress:
                if option.rect.contains(event.pos()):
                    self._isMousePressed = True
                    return True
            elif event.type() == QEvent.MouseButtonRelease:
                self._isMousePressed = False
                if option.rect.contains(event.pos()):
                    model.setData(index, self.text, Qt.EditRole)  # Model should handle button click action in its setData() method.
                    return True
        return False