/**
  * \brief Rectangle corresponding to the color at the given index
  */
 QRectF indexRect(int index)
 {
     QSize rc = rowcols();
     if ( index == -1 || !rc.isValid() )
         return QRectF();
     return indexRect(index, rc, actualColorSize(rc));
 }
void AppListView::prepareDropSwap()
{
    if (m_lastFakeAni || m_dropThresholdTimer->isActive())
        return;
    const QModelIndex dropIndex = indexAt(m_dropToPos);
    if (!dropIndex.isValid())
        return;
    const QModelIndex dragStartIndex = indexAt(m_dragStartPos);
    if (dragStartIndex == dropIndex)
        return;

    AppsListModel *listModel = qobject_cast<AppsListModel *>(model());
    if (!listModel)
        return;

    listModel->clearDragingIndex();
    listModel->setDragingIndex(dragStartIndex);
    listModel->setDragDropIndex(dropIndex);

    const int startIndex = dragStartIndex.row();
    const bool moveToNext = startIndex <= m_dropToPos;
    const int start = moveToNext ? startIndex : m_dropToPos;
    const int end = !moveToNext ? startIndex : m_dropToPos;

    if (start == end)
        return;

    for (int i(start + moveToNext); i != end - !moveToNext; ++i)
        createFakeAnimation(i, moveToNext);
    // last animation
    createFakeAnimation(end - !moveToNext, moveToNext, true);

    m_dragStartPos = indexRect(dropIndex).center();
}
void AppListView::createFakeAnimation(const int pos, const bool moveNext, const bool isLastAni)
{
    const QModelIndex index(indexAt(pos));

    QLabel *floatLabel = new QLabel(this);
    QPropertyAnimation *ani = new QPropertyAnimation(floatLabel, "pos", this);

    const QSize rectSize = index.data(AppsListModel::ItemSizeHintRole).toSize();
    const QPixmap iconPix = index.data(AppsListModel::AppIconRole).value<QPixmap>();

    QStyleOptionViewItem item;
    item.rect = QRect(QPoint(0, 0), rectSize);
    item.features |= QStyleOptionViewItem::HasDisplay;

    QPixmap pixmap(rectSize);
    pixmap.fill(Qt::transparent);

    QPainter painter(&pixmap);
    itemDelegate()->paint(&painter, item, index);

    floatLabel->setFixedSize(rectSize);
    floatLabel->setPixmap(pixmap);
//  lastLabel->setStyleSheet("background-color:red;");
    floatLabel->show();

    ani->setStartValue(indexRect(index).topLeft());
    ani->setEndValue(indexRect(indexAt(moveNext ? pos - 1 : pos + 1)).topLeft());
    ani->setEasingCurve(QEasingCurve::OutQuad);
    ani->setDuration(300);

    connect(ani, &QPropertyAnimation::finished, floatLabel, &QLabel::deleteLater);
    if (isLastAni)
    {
        m_lastFakeAni = ani;
        connect(ani, &QPropertyAnimation::finished, this, &AppListView::dropSwap, Qt::QueuedConnection);
//        connect(ani, &QPropertyAnimation::finished, [this] {dropSwap(); m_lastFakeAni = nullptr;});
        connect(ani, &QPropertyAnimation::valueChanged, m_dropThresholdTimer, &QTimer::stop);
    }

    ani->start(QPropertyAnimation::DeleteWhenStopped);
}
    /**
     * \brief Sets the drop properties
     */
    void dropEvent(QDropEvent* event)
    {
        // Find the output location
        drop_index = owner->indexAt(event->pos());
        if ( drop_index == -1 )
            drop_index = palette.count();

        // Gather up the color
        if ( event->mimeData()->hasColor() )
        {
            drop_color = event->mimeData()->colorData().value<QColor>();

        }
        else if ( event->mimeData()->hasText() )
        {
            drop_color = QColor(event->mimeData()->text());
        }

        drop_overwrite = false;
        QRectF drop_rect = indexRect(drop_index);
        if ( drop_index < palette.count() && drop_rect.isValid() )
        {
            // 1 column => vertical style
            if ( palette.columns() == 1 || forced_columns == 1 )
            {
                // Dragged to the last quarter of the size of the square, add after
                if ( event->posF().y() >= drop_rect.top() + drop_rect.height() * 3.0 / 4 )
                    drop_index++;
                // Dragged to the middle of the square, overwrite existing color
                else if ( event->posF().x() > drop_rect.top() + drop_rect.height() / 4 &&
                        ( event->dropAction() != Qt::MoveAction || event->source() != owner ||
                          palette.colorAt(drop_index) == emptyColor ) )
                    drop_overwrite = true;
            }
            else
            {
                // Dragged to the last quarter of the size of the square, add after
                if ( event->posF().x() >= drop_rect.left() + drop_rect.width() * 3.0 / 4 )
                    drop_index++;
                // Dragged to the middle of the square, overwrite existing color
                else if ( event->posF().x() > drop_rect.left() + drop_rect.width() / 4 &&
                        ( event->dropAction() != Qt::MoveAction || event->source() != owner ||
                          palette.colorAt(drop_index) == emptyColor ) )
                    drop_overwrite = true;
            }
        }

        owner->update();
    }
///
/// \brief AppListView::indexYOffset return item Y offset of current view
/// \param index item index
/// \return pixel of Y offset
///
int AppListView::indexYOffset(const QModelIndex &index) const
{
    return indexRect(index).y();
}