#include "CheckBoxItemDelegate.h"

#include <QApplication>
#include <QStyleOptionButton>
#include <QPainter>
#include <QEvent>
#include <QMouseEvent>


CheckBoxItemDelegate::CheckBoxItemDelegate(QObject *parent) : QStyledItemDelegate( parent ) {

}

CheckBoxItemDelegate::~CheckBoxItemDelegate() {

}

void CheckBoxItemDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const {
    // Setting parameters
    Qt::CheckState state = (Qt::CheckState)index.data( Qt::CheckStateRole ).toInt();

    QStyleOptionButton opt;

    opt.state = 0;

    if (index.flags() & Qt::ItemIsEditable) {
        opt.state |= QStyle::State_Enabled;
    } else {
        opt.state |= QStyle::State_ReadOnly;
    }
    if ( option.state & QStyle::State_MouseOver )
        opt.state |= QStyle::State_MouseOver; // Mouse over sell
    if (option.state & QStyle::State_Selected)
        opt.state |= QStyle::State_Selected | QStyle::State_MouseOver;

    switch ( state ) {
    case Qt::Unchecked:
        opt.state |= QStyle::State_Off;
        break;
    case Qt::PartiallyChecked:
        opt.state |= QStyle::State_NoChange;
        break;
    case Qt::Checked:
        opt.state |= QStyle::State_On;
        break;
    }
    // Check box rect
    opt.rect = QApplication::style()->subElementRect( QStyle::SE_CheckBoxIndicator, &opt, NULL );
    const int x = option.rect.center().x() - opt.rect.width() / 2;
    const int y = option.rect.center().y() - opt.rect.height() / 2;
    opt.rect.moveTo( x, y );

    QVariant bgBrush = index.data(Qt::BackgroundRole);
    if (bgBrush.isValid()) {
        painter->fillRect(option.rect, bgBrush.value<QBrush>());
    } else if (option.state & QStyle::State_Selected) {
        painter->fillRect(option.rect, option.palette.highlight());
    }

    // Mandatory: drawing check box
    QApplication::style()->drawControl( QStyle::CE_CheckBox, &opt, painter );
}

bool CheckBoxItemDelegate::editorEvent( QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index ) {
    switch ( event->type() ) {
        case QEvent::MouseButtonPress:
            m_lastClickedIndex = index;
            break;
        case QEvent::MouseButtonRelease: {
                if ( index != m_lastClickedIndex )
                    break;
                QMouseEvent *e = static_cast< QMouseEvent * >( event );
                if ( e->button() != Qt::LeftButton )
                    break;
                m_lastClickedIndex = QModelIndex();

                QStyleOptionButton opt;
                opt.rect = QApplication::style()->subElementRect( QStyle::SE_CheckBoxIndicator, &opt, NULL );
                const int x = option.rect.center().x() - opt.rect.width() / 2;
                const int y = option.rect.center().y() - opt.rect.height() / 2;
                opt.rect.moveTo( x, y );

                if ( opt.rect.contains( e->pos() ) ) {
                    Qt::CheckState state = (Qt::CheckState)index.data( Qt::CheckStateRole ).toInt();
                    state = state == Qt::Checked ? Qt::Unchecked : Qt::Checked;
                    model->setData(index, state, Qt::CheckStateRole);
                }
            }
            break;
        case QEvent::MouseButtonDblClick:
            return true;
        default:
            break;
    }

    return QAbstractItemDelegate::editorEvent( event, model, option, index );
}
