# -*- coding: utf8 -*-

from qt import *
from qttable import QTable, QTableItem

class TableCheckBox(QWidget):
    def __init__(self, table, item, checked, parent, *args):
        #print "TableCheckBox,__init__:", checked
        self.table = table
        self.checked = checked
        self.selected = False
        QWidget.__init__(self, parent, *args)
        self.setEraseColor(parent.eraseColor())
        self.setFocusPolicy(QWidget.TabFocus)
        self.setChecked(self.checked)

    def setChecked(self, checked):
        #print "TableCheckBox.setChecked:", checked
        self.checked = checked != False
        self.update()
        self.emit(PYSIGNAL("toggled"), (self.checked,))
    
    def isChecked(self):
        #print "TableCheckBox.isChecked:", self.checked
        return self.checked
    
    def mousePressEvent(self, e):
        #print "TableCheckBox.mousePressEvent"
        self.setChecked(not self.checked)
        QWidget.mousePressEvent(self, e)

    def keyPressEvent(self, e):
        key = e.key()
        #print "TableCheckBox.keyPressEvent", key
        if key == Qt.Key_Space:
            #print "TableCheckBox: bingo"
            self.setChecked(not self.checked)
        QWidget.keyPressEvent(self, e)

    def paintEvent(self, e):
        table = self.table
        row = table.currentRow()
        col = table.currentColumn()
        selected = table.isSelected(row, col)
        p = QPainter(self)
        r = e.rect()
        p.setClipRect(r)
        #print "TableCheckBox.paintEvent[%s,%s]:" % (row, col), \
        #        r.x(), r.y(), r.width(), r.height()
        w = r.width()
        h = r.height()
        cg = self.colorGroup()
        p.fillRect(0, 0, w, h,
                   self.selected and cg.brush(QColorGroup.Highlight)
                                 or cg.brush(QColorGroup.Base))
        sz = QSize(table.style().pixelMetric(QStyle.PM_IndicatorWidth),
                   table.style().pixelMetric(QStyle.PM_IndicatorHeight))
        cbw = sz.width()
        cbh = sz.height()
        c = QColorGroup(cg)
        c.setBrush(QColorGroup.Background, c.brush(QColorGroup.Base))
        flags = QStyle.Style_Default
        if self.isEnabled() and self.table.isEnabled():
            flags |= QStyle.Style_Enabled
        if self.checked:
            flags |= QStyle.Style_On
        else:
            flags |= QStyle.Style_Off
        #print "TableCheckBox.paintEvent[%s,%s]:" % (row, col), \
        #        w, h, cbw, cbh, (w - cbw) / 2, (h - cbh) / 2
        table.style().drawPrimitive(QStyle.PE_Indicator, p,
            QRect((w - cbw) / 2, (h - cbh) / 2, cbw, cbh), c, flags)

        if table.focusStyle() == QTable.SpreadSheet:
            p.setPen(QPen(Qt.black, 1))
            p.setBrush(Qt.NoBrush)
            #p.drawRect(r.x(), r.y(), r.width() - 1, r.height() - 1)
            #p.drawRect(r.x() - 1, r.y() - 1, r.width() + 1, r.height() + 1)
            # with SpreadSheet focus style, something strange happens:
            # some paint events have the full size, and some have a w/h - 1.
            # Since it's unpossible to get this en par with Qt's native 
            # focus style implementation without big fuss (the focus
            # frame gets painted on top of the grid lines, while we're 
            # limited to the cell content), either use QTable.FollowStyle
            # or subclass QTable and fix it there.. The same happens with
            # QTable.FollowStyle, but the visual impact is much smaller.
            p.drawRect(r.x(), r.y(), r.width(), r.height())
            p.drawRect(r.x(), r.y(), r.width() - 1, r.height() - 1)
            p.drawRect(r.x() + 1, r.y() + 1, r.width() - 2, r.height() - 2)
        else:
            c = QColor(selected and self.colorGroup().highlight()
                                or self.colorGroup().base())
            table.style().drawPrimitive(QStyle.PE_FocusRect, p, r, self.colorGroup(),
                                        selected and QStyle.Style_FocusAtBorder
                                                 or QStyle.Style_Default,
                                        QStyleOption(c))


class CheckTableItem(QTableItem):
    def __init__(self, table, checked = False):
        QTableItem.__init__(self, table, QTableItem.WhenCurrent)
        #QTableItem.__init__(self, table, QTableItem.Always)
        #QTableItem.__init__(self, table, QTableItem.Never)
        self.checked = checked != False
        self.setReplaceable(False)

    def toggled(self, state):
        #print "CheckTableItem.toggled:", self.row(), self.col()
        self.table().emit(SIGNAL("valueChanged()"), (self.row(), self.col()))

    def createEditor(self):
        #print "CheckTableItem.createEditor"
        cb = TableCheckBox(self.table(), self, self.checked, self.table().viewport(), "tablecheckbox")
        #print "CheckTableItem.updateCell", self.row(), self.col()
        #self.table().updateCell(self.row(), self.col())
        QObject.connect(cb, PYSIGNAL("toggled"), self.toggled)
        return cb

    def setContentFromEditor(self, widget):
        if widget:
            self.checked = widget.isChecked()
        #print "CheckTableItem.setContentFromEditor:", widget, self.checked

    def setChecked(self, checked):
        #print "CheckTableItem.setChecked:", checked
        self.checked = checked != False
        cb = self.table().cellWidget(self.row(), self.col())
        if cb:
            cb.setChecked(self.checked)
        #self.table().updateCell(self.row(), self.col())
    
    def isChecked(self):
        cb = self.table().cellWidget(self.row(), self.col())
        if cb:
            ret = cb.isChecked()
        else:
            ret = self.checked
        #print "CheckTableItem.isChecked:", ret, cb
        return ret
    
    def paint(self, p, cg, cr, selected):
        #print "CheckTableItem.paint:", p, cg, cr, selected
        table = self.table()
        row = self.row()
        col = self.col()
        cb = table.cellWidget(row, col)
        if cb:
            #print "CheckTableItem.paint[%s,%s]:" % (row, col), cb
            return
        w = cr.width()
        h = cr.height()
        p.fillRect(0, 0, w, h,
                   selected and cg.brush(QColorGroup.Highlight)
                            or cg.brush(QColorGroup.Base))
        sz = QSize(table.style().pixelMetric(QStyle.PM_IndicatorWidth),
                   table.style().pixelMetric(QStyle.PM_IndicatorHeight))
        cbw = sz.width()
        cbh = sz.height()
        c = QColorGroup(cg)
        c.setBrush(QColorGroup.Background, c.brush(QColorGroup.Base))
        flags = QStyle.Style_Default
        if self.isEnabled() and self.table().isEnabled():
            flags |= QStyle.Style_Enabled
        if self.isChecked():
            flags |= QStyle.Style_On
        else:
            flags |= QStyle.Style_Off
        #print "CheckTableItem.paint[%s,%s]:" % (row, col), \
        #        w, h, cbw, cbh, (w - cbw) / 2, (h - cbh) / 2
        table.style().drawPrimitive(QStyle.PE_Indicator, p,
            QRect((w - cbw) / 2, (h - cbh) / 2, cbw, cbh), c, flags)

    def sizeHint(self):
        sz = QSize(self.table().style().pixelMetric(QStyle.PM_IndicatorWidth),
                   self.table().style().pixelMetric(QStyle.PM_IndicatorHeight))
        sh = QSize(QTableItem.sizeHint(self))
        ret = QSize(sh.width() + sz.width(), max(sh.height(), sz.height()) 
                     ).expandedTo(QApplication.globalStrut())
        #print "CheckTableItem.sizeHint:", ret.width(), ret.height()
        return ret


if __name__ == '__main__':
    import sys
    from qttable import QTable

    def cellchanged(row, col):
        print "Cell %s, %s changed:" % (row, col),
        if col == 0:
            print "text: %s" % t.text(row, col)
        else:
            print "checkbox: %s" % t.item(row, col).isChecked()

    ROWS = 10
    COLS = 2
    app = QApplication(sys.argv)
    t = QTable(ROWS, COLS)
    t.setFocusStyle(QTable.FollowStyle)
    for i in xrange(ROWS):
        t.setText(i, 0, "Row %s" % (i + 1))
        t.setItem(i, 1, CheckTableItem(t, i % 2))
    t.connect(t, SIGNAL("valueChanged(int, int)"), cellchanged)
    t.resize(t.sizeHint())
    t.show()
    app.setMainWidget(t)
    app.exec_loop()
    for i in xrange(ROWS):
        print "%s: checkbox %s" % (t.text(i, 0), t.item(i, 1).isChecked())
