bool UIGChooserItemMachine::isDropAllowed(QGraphicsSceneDragDropEvent *pEvent, DragToken where) const
{
    /* No drops while saving groups: */
    if (model()->isGroupSavingInProgress())
        return false;
    /* No drops for immutable item: */
    if (isLockedMachine())
        return false;
    /* Get mime: */
    const QMimeData *pMimeData = pEvent->mimeData();
    /* If drag token is shown, its up to parent to decide: */
    if (where != DragToken_Off)
        return parentItem()->isDropAllowed(pEvent);
    /* Else we should make sure machine is accessible: */
    if (!accessible())
        return false;
    /* Else we should try to cast mime to known classes: */
    if (pMimeData->hasFormat(UIGChooserItemMachine::className()))
    {
        /* Make sure passed item id is not ours: */
        const UIGChooserItemMimeData *pCastedMimeData = qobject_cast<const UIGChooserItemMimeData*>(pMimeData);
        AssertMsg(pCastedMimeData, ("Can't cast passed mime-data to UIGChooserItemMimeData!"));
        UIGChooserItem *pItem = pCastedMimeData->item();
        UIGChooserItemMachine *pMachineItem = pItem->toMachineItem();
        /* Make sure passed machine is mutable: */
        if (pMachineItem->isLockedMachine())
            return false;
        return pMachineItem->id() != id();
    }
    /* That was invalid mime: */
    return false;
}
void UIGChooserItemMachine::processDrop(QGraphicsSceneDragDropEvent *pEvent, UIGChooserItem *pFromWho, DragToken where)
{
    /* Get mime: */
    const QMimeData *pMime = pEvent->mimeData();
    /* Make sure this handler called by this item (not by children): */
    AssertMsg(!pFromWho && where == DragToken_Off, ("Machine graphics item do NOT support children!"));
    Q_UNUSED(pFromWho);
    Q_UNUSED(where);
    if (pMime->hasFormat(UIGChooserItemMachine::className()))
    {
        switch (pEvent->proposedAction())
        {
            case Qt::MoveAction:
            case Qt::CopyAction:
            {
                /* Remember scene: */
                UIGChooserModel *pModel = model();

                /* Get passed item: */
                const UIGChooserItemMimeData *pCastedMime = qobject_cast<const UIGChooserItemMimeData*>(pMime);
                AssertMsg(pCastedMime, ("Can't cast passed mime-data to UIGChooserItemMimeData!"));
                UIGChooserItem *pItem = pCastedMime->item();

                /* Group passed item with current item into the new group: */
                UIGChooserItemGroup *pNewGroupItem = new UIGChooserItemGroup(parentItem(),
                                                                             model()->uniqueGroupName(parentItem()),
                                                                             true);
                new UIGChooserItemMachine(pNewGroupItem, this);
                new UIGChooserItemMachine(pNewGroupItem, pItem->toMachineItem());

                /* If proposed action is 'move': */
                if (pEvent->proposedAction() == Qt::MoveAction)
                {
                    /* Delete passed item: */
                    delete pItem;
                }
                /* Delete this item: */
                delete this;

                /* Update model: */
                pModel->updateGroupTree();
                pModel->updateNavigation();
                pModel->updateLayout();
                pModel->setCurrentItem(pNewGroupItem);
                pModel->saveGroupSettings();
                break;
            }
            default:
                break;
        }
    }
}
bool UIGChooserHandlerKeyboard::handleKeyPress(QKeyEvent *pEvent) const
{
    /* Which key it was? */
    switch (pEvent->key())
    {
        /* Key UP? */
        case Qt::Key_Up:
        {
            /* Not during sliding: */
            if (model()->isSlidingInProgress())
                return false;

            /* Determine focus item position: */
            int iPosition = model()->navigationList().indexOf(model()->focusItem());
            /* Determine 'previous' item: */
            UIGChooserItem *pPreviousItem = iPosition > 0 ?
                                             model()->navigationList().at(iPosition - 1) : 0;
            if (pPreviousItem)
            {
                /* Make sure 'previous' item is visible: */
                pPreviousItem->makeSureItsVisible();
                /* Move focus to 'previous' item: */
                model()->setFocusItem(pPreviousItem);
                /* Was 'shift' modifier pressed? */
#ifdef Q_WS_MAC
                if (pEvent->modifiers() & Qt::ShiftModifier &&
                    pEvent->modifiers() & Qt::KeypadModifier)
#else /* Q_WS_MAC */
                if (pEvent->modifiers() == Qt::ShiftModifier)
#endif /* !Q_WS_MAC */
                {
                    /* Calculate positions: */
                    UIGChooserItem *pFirstItem = model()->selectionList().first();
                    int iFirstPosition = model()->navigationList().indexOf(pFirstItem);
                    int iPreviousPosition = model()->navigationList().indexOf(pPreviousItem);
                    /* Clear selection: */
                    model()->clearSelectionList();
                    /* Select all the items from 'first' to 'previous': */
                    if (iFirstPosition <= iPreviousPosition)
                        for (int i = iFirstPosition; i <= iPreviousPosition; ++i)
                            model()->addToSelectionList(model()->navigationList().at(i));
                    else
                        for (int i = iFirstPosition; i >= iPreviousPosition; --i)
                            model()->addToSelectionList(model()->navigationList().at(i));
                }
                /* There is no modifiers pressed? */
#ifdef Q_WS_MAC
                else if (pEvent->modifiers() == Qt::KeypadModifier)
#else /* Q_WS_MAC */
                else if (pEvent->modifiers() == Qt::NoModifier)
#endif /* !Q_WS_MAC */
                {
                    /* Move selection to 'previous' item: */
                    model()->clearSelectionList();
                    model()->addToSelectionList(pPreviousItem);
                }
                /* Notify selection changed: */
                model()->notifySelectionChanged();
                /* Filter-out this event: */
                return true;
            }
            /* Pass this event: */
            return false;
        }
        /* Key DOWN? */
        case Qt::Key_Down:
        {
            /* Not during sliding: */
            if (model()->isSlidingInProgress())
                return false;

            /* Determine focus item position: */
            int iPosition = model()->navigationList().indexOf(model()->focusItem());
            /* Determine 'next' item: */
            UIGChooserItem *pNextItem = iPosition < model()->navigationList().size() - 1 ?
                                          model()->navigationList().at(iPosition + 1) : 0;
            if (pNextItem)
            {
                /* Make sure 'next' item is visible: */
                pNextItem->makeSureItsVisible();
                /* Move focus to 'next' item: */
                model()->setFocusItem(pNextItem);
                /* Was shift modifier pressed? */
#ifdef Q_WS_MAC
                if (pEvent->modifiers() & Qt::ShiftModifier &&
                    pEvent->modifiers() & Qt::KeypadModifier)
#else /* Q_WS_MAC */
                if (pEvent->modifiers() == Qt::ShiftModifier)
#endif /* !Q_WS_MAC */
                {
                    /* Calculate positions: */
                    UIGChooserItem *pFirstItem = model()->selectionList().first();
                    int iFirstPosition = model()->navigationList().indexOf(pFirstItem);
                    int iNextPosition = model()->navigationList().indexOf(pNextItem);
                    /* Clear selection: */
                    model()->clearSelectionList();
                    /* Select all the items from 'first' to 'next': */
                    if (iFirstPosition <= iNextPosition)
                        for (int i = iFirstPosition; i <= iNextPosition; ++i)
                            model()->addToSelectionList(model()->navigationList().at(i));
                    else
                        for (int i = iFirstPosition; i >= iNextPosition; --i)
                            model()->addToSelectionList(model()->navigationList().at(i));
                }
                /* There is no modifiers pressed? */
#ifdef Q_WS_MAC
                else if (pEvent->modifiers() == Qt::KeypadModifier)
#else /* Q_WS_MAC */
                else if (pEvent->modifiers() == Qt::NoModifier)
#endif /* !Q_WS_MAC */
                {
                    /* Move selection to 'next' item: */
                    model()->clearSelectionList();
                    model()->addToSelectionList(pNextItem);
                }
                /* Notify selection changed: */
                model()->notifySelectionChanged();
                /* Filter-out this event: */
                return true;
            }
            /* Pass this event: */
            return false;
        }
        /* Key LEFT? */
        case Qt::Key_Left:
        {
            /* If there is a focus item: */
            if (UIGChooserItem *pFocusItem = model()->focusItem())
            {
                /* Of the known type: */
                switch (pFocusItem->type())
                {
                    case UIGChooserItemType_Group:
                    case UIGChooserItemType_Machine:
                    {
                        /* Unindent root if its NOT main: */
                        if (model()->root() != model()->mainRoot())
                            model()->unindentRoot();
                        break;
                    }
                    default:
                        break;
                }
            }
            /* Pass that event: */
            return false;
        }
        /* Key RIGHT? */
        case Qt::Key_Right:
        {
            /* If there is focus item: */
            if (UIGChooserItem *pFocusItem = model()->focusItem())
            {
                /* Of the group type: */
                if (pFocusItem->type() == UIGChooserItemType_Group)
                {
                    /* Indent root with this item: */
                    model()->indentRoot(pFocusItem);
                }
            }
            /* Pass that event: */
            return false;
        }
        /* Key F2? */
        case Qt::Key_F2:
        {
            /* If this item is of group type: */
            if (model()->focusItem()->type() == UIGChooserItemType_Group)
            {
                /* Start embedded editing focus item: */
                model()->focusItem()->startEditing();
                /* Filter that event out: */
                return true;
            }
            /* Pass event to other items: */
            return false;
        }
        case Qt::Key_Return:
        case Qt::Key_Enter:
        {
            /* Activate item: */
            model()->activate();
            /* And filter out that event: */
            return true;
        }
        case Qt::Key_Space:
        {
            /* If there is a focus item: */
            if (UIGChooserItem *pFocusItem = model()->focusItem())
            {
                /* Of the group type: */
                if (pFocusItem->type() == UIGChooserItemType_Group)
                {
                    /* Toggle that group: */
                    UIGChooserItemGroup *pGroupItem = pFocusItem->toGroupItem();
                    if (pGroupItem->closed())
                        pGroupItem->open();
                    else
                        pGroupItem->close();
                    /* Filter that event out: */
                    return true;
                }
            }
            /* Pass event to other items: */
            return false;
        }
        default:
            break;
    }
    /* Pass all other events: */
    return false;
}
bool UIGChooserHandlerMouse::handleMousePress(QGraphicsSceneMouseEvent *pEvent) const
{
    /* Get item under mouse cursor: */
    QPointF scenePos = pEvent->scenePos();
    if (QGraphicsItem *pItemUnderMouse = model()->itemAt(scenePos))
    {
        /* Which button it was? */
        switch (pEvent->button())
        {
            /* Left one? */
            case Qt::LeftButton:
            {
                /* Which item we just clicked? */
                UIGChooserItem *pClickedItem = 0;
                /* Was that a group item? */
                if (UIGChooserItemGroup *pGroupItem = qgraphicsitem_cast<UIGChooserItemGroup*>(pItemUnderMouse))
                    pClickedItem = pGroupItem;
                /* Or a machine one? */
                else if (UIGChooserItemMachine *pMachineItem = qgraphicsitem_cast<UIGChooserItemMachine*>(pItemUnderMouse))
                    pClickedItem = pMachineItem;
                /* If we had clicked one of required item types: */
                if (pClickedItem && !pClickedItem->isRoot())
                {
                    /* Was 'shift' modifier pressed? */
                    if (pEvent->modifiers() == Qt::ShiftModifier)
                    {
                        /* Calculate positions: */
                        UIGChooserItem *pFirstItem = model()->currentItem();
                        int iFirstPosition = model()->navigationList().indexOf(pFirstItem);
                        int iClickedPosition = model()->navigationList().indexOf(pClickedItem);
                        /* Populate list of items from 'first' to 'clicked': */
                        QList<UIGChooserItem*> items;
                        if (iFirstPosition <= iClickedPosition)
                            for (int i = iFirstPosition; i <= iClickedPosition; ++i)
                                items << model()->navigationList().at(i);
                        else
                            for (int i = iFirstPosition; i >= iClickedPosition; --i)
                                items << model()->navigationList().at(i);
                        /* Set that list as current: */
                        model()->setCurrentItems(items);
                        /* Move focus to clicked item: */
                        model()->setFocusItem(pClickedItem);
                    }
                    /* Was 'control' modifier pressed? */
                    else if (pEvent->modifiers() == Qt::ControlModifier)
                    {
                        /* Invert selection state for clicked item: */
                        if (model()->currentItems().contains(pClickedItem))
                            model()->removeFromCurrentItems(pClickedItem);
                        else
                            model()->addToCurrentItems(pClickedItem);
                        /* Move focus to clicked item: */
                        model()->setFocusItem(pClickedItem);
                    }
                    /* Was no modifiers pressed? */
                    else if (pEvent->modifiers() == Qt::NoModifier)
                    {
                        /* Make clicked item the current one: */
                        model()->setCurrentItem(pClickedItem);
                    }
                }
                break;
            }
            /* Right one? */
            case Qt::RightButton:
            {
                /* Which item we just clicked? */
                UIGChooserItem *pClickedItem = 0;
                /* Was that a group item? */
                if (UIGChooserItemGroup *pGroupItem = qgraphicsitem_cast<UIGChooserItemGroup*>(pItemUnderMouse))
                    pClickedItem = pGroupItem;
                /* Or a machine one? */
                else if (UIGChooserItemMachine *pMachineItem = qgraphicsitem_cast<UIGChooserItemMachine*>(pItemUnderMouse))
                    pClickedItem = pMachineItem;
                /* If we had clicked one of required item types: */
                if (pClickedItem && !pClickedItem->isRoot())
                {
                    /* Select clicked item if not selected yet: */
                    if (!model()->currentItems().contains(pClickedItem))
                        model()->setCurrentItem(pClickedItem);
                }
                break;
            }
            default:
                break;
        }
    }
    /* Pass all other events: */
    return false;
}
bool UIGChooserHandlerMouse::handleMousePress(QGraphicsSceneMouseEvent *pEvent) const
{
    /* Get item under mouse cursor: */
    QPointF scenePos = pEvent->scenePos();
    if (QGraphicsItem *pItemUnderMouse = model()->itemAt(scenePos))
    {
        /* Which button it was? */
        switch (pEvent->button())
        {
            /* Left one? */
            case Qt::LeftButton:
            {
                /* Which item we just clicked? */
                UIGChooserItem *pClickedItem = 0;
                /* Was that a group item? */
                if (UIGChooserItemGroup *pGroupItem = qgraphicsitem_cast<UIGChooserItemGroup*>(pItemUnderMouse))
                    pClickedItem = pGroupItem;
                /* Or a machine one? */
                else if (UIGChooserItemMachine *pMachineItem = qgraphicsitem_cast<UIGChooserItemMachine*>(pItemUnderMouse))
                    pClickedItem = pMachineItem;
                /* If we had clicked one of the required item types: */
                if (pClickedItem && !pClickedItem->isRoot())
                {
                    /* Old selection list: */
                    QList<UIGChooserItem*> oldSelectionList = model()->selectionList();
                    /* Move focus to clicked item: */
                    model()->setFocusItem(pClickedItem);
                    /* Was 'shift' modifier pressed? */
                    if (pEvent->modifiers() == Qt::ShiftModifier)
                    {
                        /* Calculate positions: */
                        UIGChooserItem *pFirstItem = model()->selectionList().first();
                        int iFirstPosition = model()->navigationList().indexOf(pFirstItem);
                        int iClickedPosition = model()->navigationList().indexOf(pClickedItem);
                        /* Clear selection: */
                        model()->clearSelectionList();
                        /* Select all the items from 'first' to 'clicked': */
                        if (iFirstPosition <= iClickedPosition)
                            for (int i = iFirstPosition; i <= iClickedPosition; ++i)
                                model()->addToSelectionList(model()->navigationList().at(i));
                        else
                            for (int i = iFirstPosition; i >= iClickedPosition; --i)
                                model()->addToSelectionList(model()->navigationList().at(i));
                    }
                    /* Was 'control' modifier pressed? */
                    else if (pEvent->modifiers() == Qt::ControlModifier)
                    {
                        /* Select clicked item, inverting if necessary: */
                        if (model()->selectionList().contains(pClickedItem))
                            model()->removeFromSelectionList(pClickedItem);
                        else
                            model()->addToSelectionList(pClickedItem);
                    }
                    /* Was no modifiers pressed? */
                    else if (pEvent->modifiers() == Qt::NoModifier)
                    {
                        /* Move selection to clicked item: */
                        model()->clearSelectionList();
                        model()->addToSelectionList(pClickedItem);
                    }
                    /* Selection list changed?: */
                    if (oldSelectionList != model()->selectionList())
                        model()->notifySelectionChanged();
                }
                break;
            }
            /* Right one? */
            case Qt::RightButton:
            {
                /* Which item we just clicked? */
                UIGChooserItem *pClickedItem = 0;
                /* Was that a group item? */
                if (UIGChooserItemGroup *pGroupItem = qgraphicsitem_cast<UIGChooserItemGroup*>(pItemUnderMouse))
                    pClickedItem = pGroupItem;
                /* Or a machine one? */
                else if (UIGChooserItemMachine *pMachineItem = qgraphicsitem_cast<UIGChooserItemMachine*>(pItemUnderMouse))
                    pClickedItem = pMachineItem;
                /* If we had clicked one of the required item types: */
                if (pClickedItem)
                {
                    /* For non-root items: */
                    if (!pClickedItem->isRoot())
                    {
                        /* Is clicked item in selection list: */
                        bool fIsClickedItemInSelectionList = contains(model()->selectionList(), pClickedItem);
                        /* Move focus to clicked item (with selection if not selected yet): */
                        model()->setFocusItem(pClickedItem, !fIsClickedItemInSelectionList);
                    }
                }
                break;
            }
            default:
                break;
        }
    }
    /* Pass all other events: */
    return false;
}