VirtualBox

Changeset 43528 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Oct 3, 2012 2:09:25 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
81116
Message:

FE/Qt: VM group feature UI: Cleanup part 2 (Reordering content of UIGChooserModel).

Location:
trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserModel.cpp

    r43514 r43528  
    133133}
    134134
    135 UIGChooserItem* UIGChooserModel::mainRoot() const
    136 {
    137     return m_rootStack.first();
    138 }
    139 
    140 UIGChooserItem* UIGChooserModel::root() const
    141 {
    142     return m_rootStack.last();
    143 }
    144 
    145 void UIGChooserModel::indentRoot(UIGChooserItem *pNewRootItem)
    146 {
    147     /* Do nothing is sliding already: */
    148     if (m_fSliding)
    149         return;
    150 
    151     /* We are sliding: */
    152     m_fSliding = true;
    153     emit sigSlidingStarted();
    154 
    155     /* Hiding root: */
    156     root()->hide();
    157 
    158     /* Create left root: */
    159     bool fLeftRootIsMain = root() == mainRoot();
    160     m_pLeftRoot = new UIGChooserItemGroup(scene(), root()->toGroupItem(), fLeftRootIsMain);
    161     m_pLeftRoot->setPos(0, 0);
    162     m_pLeftRoot->resize(root()->geometry().size());
    163 
    164     /* Create right root: */
    165     m_pRightRoot = new UIGChooserItemGroup(scene(), pNewRootItem->toGroupItem(), false);
    166     m_pRightRoot->setPos(root()->geometry().width(), 0);
    167     m_pRightRoot->resize(root()->geometry().size());
    168 
    169     /* Indent root: */
    170     m_rootStack << pNewRootItem;
    171     root()->setRoot(true);
    172     m_pAfterSlidingFocus = root()->items().first();
    173 
    174     /* Slide root: */
    175     slideRoot(true);
    176 }
    177 
    178 void UIGChooserModel::unindentRoot()
    179 {
    180     /* Do nothing is sliding already: */
    181     if (m_fSliding)
    182         return;
    183 
    184     /* We are sliding: */
    185     m_fSliding = true;
    186     emit sigSlidingStarted();
    187 
    188     /* Hiding root: */
    189     root()->hide();
    190     root()->setRoot(false);
    191 
    192     /* Create left root: */
    193     bool fLeftRootIsMain = m_rootStack.at(m_rootStack.size() - 2) == mainRoot();
    194     m_pLeftRoot = new UIGChooserItemGroup(scene(), m_rootStack.at(m_rootStack.size() - 2)->toGroupItem(), fLeftRootIsMain);
    195     m_pLeftRoot->setPos(- root()->geometry().width(), 0);
    196     m_pLeftRoot->resize(root()->geometry().size());
    197 
    198     /* Create right root: */
    199     m_pRightRoot = new UIGChooserItemGroup(scene(), root()->toGroupItem(), false);
    200     m_pRightRoot->setPos(0, 0);
    201     m_pRightRoot->resize(root()->geometry().size());
    202 
    203     /* Unindent root: */
    204     m_pAfterSlidingFocus = root();
    205     m_rootStack.removeLast();
    206 
    207     /* Slide root: */
    208     slideRoot(false);
    209 }
    210 
    211 bool UIGChooserModel::isSlidingInProgress() const
    212 {
    213     return m_fSliding;
    214 }
    215 
    216 void UIGChooserModel::setCurrentItem(int iItemIndex)
    217 {
    218     /* Make sure passed index feats the bounds: */
    219     if (iItemIndex >= 0 && iItemIndex < navigationList().size())
    220     {
    221         /* And call for other wrapper: */
    222         setCurrentItem(navigationList().at(iItemIndex));
    223     }
    224     else
    225         AssertMsgFailed(("Passed index out of bounds!"));
    226 }
    227 
    228 void UIGChooserModel::setCurrentItem(UIGChooserItem *pItem)
    229 {
    230     /* If navigation list contains passed item: */
    231     if (navigationList().contains(pItem))
    232     {
    233         /* Pass focus/selection to that item: */
    234         setFocusItem(pItem, true);
    235     }
    236     else
    237         AssertMsgFailed(("Passed item not in navigation list!"));
    238 }
    239 
    240 void UIGChooserModel::unsetCurrentItem()
    241 {
    242     /* Clear focus/selection: */
    243     setFocusItem(0, true);
    244 }
    245 
    246 UIVMItem* UIGChooserModel::currentItem() const
    247 {
    248     /* Search for the first selected machine: */
    249     return searchCurrentItem(selectionList());
    250 }
    251 
    252 QList<UIVMItem*> UIGChooserModel::currentItems() const
    253 {
    254     /* Populate list of selected machines: */
    255     QList<UIVMItem*> currentItemList;
    256     enumerateCurrentItems(selectionList(), currentItemList);
    257     return currentItemList;
    258 }
    259 
    260 void UIGChooserModel::setCurrentItemDefinition(const QString &strDefinition)
    261 {
    262     /* Make sure something was passed: */
    263     if (strDefinition.isEmpty())
    264     {
    265         if (mainRoot()->hasItems())
    266             setCurrentItem(0);
    267         else
    268             unsetCurrentItem();
    269         return;
    270     }
    271 
    272     /* Parse definitions: */
    273     QString strItemType = strDefinition.section('=', 0, 0);
    274     QString strItemName = strDefinition.section('=', 1, -1);
    275     UIGChooserItem *pItem = 0;
    276 
    277     /* Its group item? */
    278     if (strItemType == "g")
    279     {
    280         /* Make sure group item with passed id exists: */
    281         pItem = findGroupItem(strItemName, mainRoot());
    282     }
    283     /* Its machine item? */
    284     else if (strItemType == "m")
    285     {
    286         /* Make sure machine with passed name registered: */
    287         CMachine machine = vboxGlobal().virtualBox().FindMachine(strItemName);
    288         if (!machine.isNull())
    289         {
    290             /* Make sure machine item with passed id exists: */
    291             pItem = findMachineItem(machine.GetName(), mainRoot());
    292         }
    293     }
    294 
    295     /* Found nothing? */
    296     if (!pItem)
    297     {
    298         setCurrentItem(0);
    299         return;
    300     }
    301 
    302     /* Select desired item: */
    303     if (navigationList().contains(pItem))
    304         setCurrentItem(pItem);
    305     else
    306         setCurrentItem(0);
    307 }
    308 
    309 QString UIGChooserModel::currentItemDefinition() const
    310 {
    311     /* Determine item type: */
    312     QString strItemType;
    313     QString strItemName;
    314 
    315     /* Get first selected item: */
    316     UIGChooserItem *pSelectedItem = selectionList().isEmpty() ? 0 : selectionList().first();
    317     /* Item exists? */
    318     if (pSelectedItem)
    319     {
    320         /* Update item type: */
    321         if (pSelectedItem->type() == UIGChooserItemType_Group)
    322             strItemType = "g";
    323         else if (pSelectedItem->type() == UIGChooserItemType_Machine)
    324             strItemType = "m";
    325 
    326         /* Update item name: */
    327         strItemName = pSelectedItem->name();
    328     }
    329 
    330     /* Return result: */
    331     return pSelectedItem ? strItemType + "=" + strItemName : QString();
    332 }
    333 
    334 bool UIGChooserModel::isSingleGroupSelected() const
    335 {
    336     return selectionList().size() == 1 &&
    337            selectionList().first()->type() == UIGChooserItemType_Group;
    338 }
    339 
    340 bool UIGChooserModel::isAllItemsOfOneGroupSelected() const
    341 {
    342     /* Make sure at least on item selected: */
    343     if (selectionList().isEmpty())
    344         return false;
    345 
    346     /* Determine the parent group of the first item: */
    347     UIGChooserItem *pFirstParent = selectionList().first()->parentItem();
    348 
    349     /* Make sure this parent is not main root item: */
    350     if (pFirstParent == mainRoot())
    351         return false;
    352 
    353     /* Enumerate selected set: */
    354     QSet<UIGChooserItem*> selectedSet;
    355     foreach (UIGChooserItem *pSelectedItem, selectionList())
    356         selectedSet << pSelectedItem;
    357 
    358     /* Enumerate first parent children set: */
    359     QSet<UIGChooserItem*> firstParentSet;
    360     foreach (UIGChooserItem *pSelectedItem, pFirstParent->items())
    361         firstParentSet << pSelectedItem;
    362 
    363     /* Check if both sets contains the same: */
    364     return selectedSet == firstParentSet;
    365 }
    366 
    367 void UIGChooserModel::setFocusItem(UIGChooserItem *pItem, bool fWithSelection /* = false */)
    368 {
    369     /* Make sure real focus unset: */
    370     clearRealFocus();
    371 
    372     /* Something changed? */
    373     if (m_pFocusItem != pItem || !pItem)
    374     {
    375         /* Remember previous focus item: */
    376         QPointer<UIGChooserItem> pPreviousFocusItem = m_pFocusItem;
    377         /* Set new focus item: */
    378         m_pFocusItem = pItem;
    379 
    380         /* Should we move selection too? */
    381         if (fWithSelection)
    382         {
    383             /* Clear selection: */
    384             clearSelectionList();
    385             /* Add focus item into selection (if any): */
    386             if (m_pFocusItem)
    387                 addToSelectionList(m_pFocusItem);
    388             /* Notify selection changed: */
    389             notifySelectionChanged();
    390         }
    391 
    392         /* Update previous focus item (if any): */
    393         if (pPreviousFocusItem)
    394         {
    395             disconnect(pPreviousFocusItem, SIGNAL(destroyed(QObject*)), this, SLOT(sltFocusItemDestroyed()));
    396             pPreviousFocusItem->update();
    397         }
    398         /* Update new focus item (if any): */
    399         if (m_pFocusItem)
    400         {
    401             connect(m_pFocusItem, SIGNAL(destroyed(QObject*)), this, SLOT(sltFocusItemDestroyed()));
    402             m_pFocusItem->update();
    403         }
    404 
    405         /* Notify focus changed: */
    406         emit sigFocusChanged(m_pFocusItem);
    407     }
    408 }
    409 
    410 UIGChooserItem* UIGChooserModel::focusItem() const
    411 {
    412     return m_pFocusItem;
    413 }
    414 
    415135QGraphicsItem* UIGChooserModel::itemAt(const QPointF &position, const QTransform &deviceTransform /* = QTransform() */) const
    416136{
    417137    return scene()->itemAt(position, deviceTransform);
    418 }
    419 
    420 void UIGChooserModel::updateGroupTree()
    421 {
    422     updateGroupTree(mainRoot());
    423 }
    424 
    425 const QList<UIGChooserItem*>& UIGChooserModel::navigationList() const
    426 {
    427     return m_navigationList;
    428 }
    429 
    430 void UIGChooserModel::removeFromNavigationList(UIGChooserItem *pItem)
    431 {
    432     AssertMsg(pItem, ("Passed item is invalid!"));
    433     m_navigationList.removeAll(pItem);
    434 }
    435 
    436 void UIGChooserModel::clearNavigationList()
    437 {
    438     m_navigationList.clear();
    439 }
    440 
    441 void UIGChooserModel::updateNavigation()
    442 {
    443     /* Recreate navigation list: */
    444     clearNavigationList();
    445     m_navigationList = createNavigationList(root());
    446 }
    447 
    448 const QList<UIGChooserItem*>& UIGChooserModel::selectionList() const
    449 {
    450     return m_selectionList;
    451 }
    452 
    453 void UIGChooserModel::addToSelectionList(UIGChooserItem *pItem)
    454 {
    455     AssertMsg(pItem, ("Passed item is invalid!"));
    456     m_selectionList << pItem;
    457     pItem->update();
    458 }
    459 
    460 void UIGChooserModel::removeFromSelectionList(UIGChooserItem *pItem)
    461 {
    462     AssertMsg(pItem, ("Passed item is invalid!"));
    463     m_selectionList.removeAll(pItem);
    464     pItem->update();
    465 }
    466 
    467 void UIGChooserModel::clearSelectionList()
    468 {
    469     QList<UIGChooserItem*> oldSelectedList = m_selectionList;
    470     m_selectionList.clear();
    471     foreach (UIGChooserItem *pItem, oldSelectedList)
    472         pItem->update();
    473 }
    474 
    475 void UIGChooserModel::notifySelectionChanged()
    476 {
    477     /* Make sure selection item list is never empty
    478      * if at least one item (for example 'focus') present: */
    479     if (selectionList().isEmpty() && focusItem())
    480         addToSelectionList(focusItem());
    481     /* Notify listeners about selection change: */
    482     emit sigSelectionChanged();
    483138}
    484139
     
    508163}
    509164
    510 void UIGChooserModel::startEditing()
    511 {
    512     sltStartEditingSelectedGroup();
    513 }
    514 
    515 void UIGChooserModel::setCurrentDragObject(QDrag *pDragObject)
     165const QList<UIGChooserItem*>& UIGChooserModel::navigationList() const
     166{
     167    return m_navigationList;
     168}
     169
     170void UIGChooserModel::removeFromNavigationList(UIGChooserItem *pItem)
     171{
     172    AssertMsg(pItem, ("Passed item is invalid!"));
     173    m_navigationList.removeAll(pItem);
     174}
     175
     176void UIGChooserModel::clearNavigationList()
     177{
     178    m_navigationList.clear();
     179}
     180
     181void UIGChooserModel::updateNavigation()
     182{
     183    /* Recreate navigation list: */
     184    clearNavigationList();
     185    m_navigationList = createNavigationList(root());
     186}
     187
     188UIVMItem* UIGChooserModel::currentItem() const
     189{
     190    /* Search for the first selected machine: */
     191    return searchCurrentItem(selectionList());
     192}
     193
     194QString UIGChooserModel::currentItemDefinition() const
     195{
     196    /* Determine item type: */
     197    QString strItemType;
     198    QString strItemName;
     199
     200    /* Get first selected item: */
     201    UIGChooserItem *pSelectedItem = selectionList().isEmpty() ? 0 : selectionList().first();
     202    /* Item exists? */
     203    if (pSelectedItem)
     204    {
     205        /* Update item type: */
     206        if (pSelectedItem->type() == UIGChooserItemType_Group)
     207            strItemType = "g";
     208        else if (pSelectedItem->type() == UIGChooserItemType_Machine)
     209            strItemType = "m";
     210
     211        /* Update item name: */
     212        strItemName = pSelectedItem->name();
     213    }
     214
     215    /* Return result: */
     216    return pSelectedItem ? strItemType + "=" + strItemName : QString();
     217}
     218
     219QList<UIVMItem*> UIGChooserModel::currentItems() const
     220{
     221    /* Populate list of selected machines: */
     222    QList<UIVMItem*> currentItemList;
     223    enumerateCurrentItems(selectionList(), currentItemList);
     224    return currentItemList;
     225}
     226
     227const QList<UIGChooserItem*>& UIGChooserModel::selectionList() const
     228{
     229    return m_selectionList;
     230}
     231
     232void UIGChooserModel::setCurrentItem(int iItemIndex)
     233{
     234    /* Make sure passed index feats the bounds: */
     235    if (iItemIndex >= 0 && iItemIndex < navigationList().size())
     236    {
     237        /* And call for other wrapper: */
     238        setCurrentItem(navigationList().at(iItemIndex));
     239    }
     240    else
     241        AssertMsgFailed(("Passed index out of bounds!"));
     242}
     243
     244void UIGChooserModel::setCurrentItem(UIGChooserItem *pItem)
     245{
     246    /* If navigation list contains passed item: */
     247    if (navigationList().contains(pItem))
     248    {
     249        /* Pass focus/selection to that item: */
     250        setFocusItem(pItem, true);
     251    }
     252    else
     253        AssertMsgFailed(("Passed item not in navigation list!"));
     254}
     255
     256void UIGChooserModel::setCurrentItemDefinition(const QString &strDefinition)
     257{
     258    /* Make sure something was passed: */
     259    if (strDefinition.isEmpty())
     260    {
     261        if (mainRoot()->hasItems())
     262            setCurrentItem(0);
     263        else
     264            unsetCurrentItem();
     265        return;
     266    }
     267
     268    /* Parse definitions: */
     269    QString strItemType = strDefinition.section('=', 0, 0);
     270    QString strItemName = strDefinition.section('=', 1, -1);
     271    UIGChooserItem *pItem = 0;
     272
     273    /* Its group item? */
     274    if (strItemType == "g")
     275    {
     276        /* Make sure group item with passed id exists: */
     277        pItem = findGroupItem(strItemName, mainRoot());
     278    }
     279    /* Its machine item? */
     280    else if (strItemType == "m")
     281    {
     282        /* Make sure machine with passed name registered: */
     283        CMachine machine = vboxGlobal().virtualBox().FindMachine(strItemName);
     284        if (!machine.isNull())
     285        {
     286            /* Make sure machine item with passed id exists: */
     287            pItem = findMachineItem(machine.GetName(), mainRoot());
     288        }
     289    }
     290
     291    /* Found nothing? */
     292    if (!pItem)
     293    {
     294        setCurrentItem(0);
     295        return;
     296    }
     297
     298    /* Select desired item: */
     299    if (navigationList().contains(pItem))
     300        setCurrentItem(pItem);
     301    else
     302        setCurrentItem(0);
     303}
     304
     305void UIGChooserModel::unsetCurrentItem()
     306{
     307    /* Clear focus/selection: */
     308    setFocusItem(0, true);
     309}
     310
     311void UIGChooserModel::addToSelectionList(UIGChooserItem *pItem)
     312{
     313    AssertMsg(pItem, ("Passed item is invalid!"));
     314    m_selectionList << pItem;
     315    pItem->update();
     316}
     317
     318void UIGChooserModel::removeFromSelectionList(UIGChooserItem *pItem)
     319{
     320    AssertMsg(pItem, ("Passed item is invalid!"));
     321    m_selectionList.removeAll(pItem);
     322    pItem->update();
     323}
     324
     325void UIGChooserModel::clearSelectionList()
     326{
     327    QList<UIGChooserItem*> oldSelectedList = m_selectionList;
     328    m_selectionList.clear();
     329    foreach (UIGChooserItem *pItem, oldSelectedList)
     330        pItem->update();
     331}
     332
     333void UIGChooserModel::notifySelectionChanged()
     334{
     335    /* Make sure selection item list is never empty
     336     * if at least one item (for example 'focus') present: */
     337    if (selectionList().isEmpty() && focusItem())
     338        addToSelectionList(focusItem());
     339    /* Notify listeners about selection change: */
     340    emit sigSelectionChanged();
     341}
     342
     343void UIGChooserModel::activate()
     344{
     345    gActionPool->action(UIActionIndexSelector_State_Common_StartOrShow)->activate(QAction::Trigger);
     346}
     347
     348bool UIGChooserModel::isSingleGroupSelected() const
     349{
     350    return selectionList().size() == 1 &&
     351           selectionList().first()->type() == UIGChooserItemType_Group;
     352}
     353
     354bool UIGChooserModel::isAllItemsOfOneGroupSelected() const
     355{
     356    /* Make sure at least on item selected: */
     357    if (selectionList().isEmpty())
     358        return false;
     359
     360    /* Determine the parent group of the first item: */
     361    UIGChooserItem *pFirstParent = selectionList().first()->parentItem();
     362
     363    /* Make sure this parent is not main root item: */
     364    if (pFirstParent == mainRoot())
     365        return false;
     366
     367    /* Enumerate selected set: */
     368    QSet<UIGChooserItem*> selectedSet;
     369    foreach (UIGChooserItem *pSelectedItem, selectionList())
     370        selectedSet << pSelectedItem;
     371
     372    /* Enumerate first parent children set: */
     373    QSet<UIGChooserItem*> firstParentSet;
     374    foreach (UIGChooserItem *pSelectedItem, pFirstParent->items())
     375        firstParentSet << pSelectedItem;
     376
     377    /* Check if both sets contains the same: */
     378    return selectedSet == firstParentSet;
     379}
     380
     381UIGChooserItem* UIGChooserModel::focusItem() const
     382{
     383    return m_pFocusItem;
     384}
     385
     386void UIGChooserModel::setFocusItem(UIGChooserItem *pItem, bool fWithSelection /* = false */)
    516387{
    517388    /* Make sure real focus unset: */
    518389    clearRealFocus();
    519390
    520     /* Remember new drag-object: */
    521     m_pCurrentDragObject = pDragObject;
    522     connect(m_pCurrentDragObject, SIGNAL(destroyed(QObject*)), this, SLOT(sltCurrentDragObjectDestroyed()));
    523 }
    524 
    525 void UIGChooserModel::activate()
    526 {
    527     gActionPool->action(UIActionIndexSelector_State_Common_StartOrShow)->activate(QAction::Trigger);
     391    /* Something changed? */
     392    if (m_pFocusItem != pItem || !pItem)
     393    {
     394        /* Remember previous focus item: */
     395        QPointer<UIGChooserItem> pPreviousFocusItem = m_pFocusItem;
     396        /* Set new focus item: */
     397        m_pFocusItem = pItem;
     398
     399        /* Should we move selection too? */
     400        if (fWithSelection)
     401        {
     402            /* Clear selection: */
     403            clearSelectionList();
     404            /* Add focus item into selection (if any): */
     405            if (m_pFocusItem)
     406                addToSelectionList(m_pFocusItem);
     407            /* Notify selection changed: */
     408            notifySelectionChanged();
     409        }
     410
     411        /* Update previous focus item (if any): */
     412        if (pPreviousFocusItem)
     413        {
     414            disconnect(pPreviousFocusItem, SIGNAL(destroyed(QObject*)), this, SLOT(sltFocusItemDestroyed()));
     415            pPreviousFocusItem->update();
     416        }
     417        /* Update new focus item (if any): */
     418        if (m_pFocusItem)
     419        {
     420            connect(m_pFocusItem, SIGNAL(destroyed(QObject*)), this, SLOT(sltFocusItemDestroyed()));
     421            m_pFocusItem->update();
     422        }
     423
     424        /* Notify focus changed: */
     425        emit sigFocusChanged(m_pFocusItem);
     426    }
     427}
     428
     429UIGChooserItem* UIGChooserModel::mainRoot() const
     430{
     431    return m_rootStack.first();
     432}
     433
     434UIGChooserItem* UIGChooserModel::root() const
     435{
     436    return m_rootStack.last();
     437}
     438
     439void UIGChooserModel::indentRoot(UIGChooserItem *pNewRootItem)
     440{
     441    /* Do nothing is sliding already: */
     442    if (m_fSliding)
     443        return;
     444
     445    /* We are sliding: */
     446    m_fSliding = true;
     447    emit sigSlidingStarted();
     448
     449    /* Hiding root: */
     450    root()->hide();
     451
     452    /* Create left root: */
     453    bool fLeftRootIsMain = root() == mainRoot();
     454    m_pLeftRoot = new UIGChooserItemGroup(scene(), root()->toGroupItem(), fLeftRootIsMain);
     455    m_pLeftRoot->setPos(0, 0);
     456    m_pLeftRoot->resize(root()->geometry().size());
     457
     458    /* Create right root: */
     459    m_pRightRoot = new UIGChooserItemGroup(scene(), pNewRootItem->toGroupItem(), false);
     460    m_pRightRoot->setPos(root()->geometry().width(), 0);
     461    m_pRightRoot->resize(root()->geometry().size());
     462
     463    /* Indent root: */
     464    m_rootStack << pNewRootItem;
     465    root()->setRoot(true);
     466    m_pAfterSlidingFocus = root()->items().first();
     467
     468    /* Slide root: */
     469    slideRoot(true);
     470}
     471
     472void UIGChooserModel::unindentRoot()
     473{
     474    /* Do nothing is sliding already: */
     475    if (m_fSliding)
     476        return;
     477
     478    /* We are sliding: */
     479    m_fSliding = true;
     480    emit sigSlidingStarted();
     481
     482    /* Hiding root: */
     483    root()->hide();
     484    root()->setRoot(false);
     485
     486    /* Create left root: */
     487    bool fLeftRootIsMain = m_rootStack.at(m_rootStack.size() - 2) == mainRoot();
     488    m_pLeftRoot = new UIGChooserItemGroup(scene(), m_rootStack.at(m_rootStack.size() - 2)->toGroupItem(), fLeftRootIsMain);
     489    m_pLeftRoot->setPos(- root()->geometry().width(), 0);
     490    m_pLeftRoot->resize(root()->geometry().size());
     491
     492    /* Create right root: */
     493    m_pRightRoot = new UIGChooserItemGroup(scene(), root()->toGroupItem(), false);
     494    m_pRightRoot->setPos(0, 0);
     495    m_pRightRoot->resize(root()->geometry().size());
     496
     497    /* Unindent root: */
     498    m_pAfterSlidingFocus = root();
     499    m_rootStack.removeLast();
     500
     501    /* Slide root: */
     502    slideRoot(false);
     503}
     504
     505bool UIGChooserModel::isSlidingInProgress() const
     506{
     507    return m_fSliding;
    528508}
    529509
     
    559539}
    560540
    561 void UIGChooserModel::saveGroupSettings()
    562 {
    563     emit sigStartGroupSaving();
    564 }
    565 
    566 bool UIGChooserModel::isGroupSavingInProgress() const
    567 {
    568     return UIGroupDefinitionSaveThread::instance() ||
    569            UIGroupOrderSaveThread::instance();
     541void UIGChooserModel::startEditing()
     542{
     543    sltStartEditingSelectedGroup();
     544}
     545
     546void UIGChooserModel::updateGroupTree()
     547{
     548    updateGroupTree(mainRoot());
     549}
     550
     551void UIGChooserModel::setCurrentDragObject(QDrag *pDragObject)
     552{
     553    /* Make sure real focus unset: */
     554    clearRealFocus();
     555
     556    /* Remember new drag-object: */
     557    m_pCurrentDragObject = pDragObject;
     558    connect(m_pCurrentDragObject, SIGNAL(destroyed(QObject*)), this, SLOT(sltCurrentDragObjectDestroyed()));
    570559}
    571560
     
    590579{
    591580    return m_pLookupTimer->isActive();
     581}
     582
     583void UIGChooserModel::saveGroupSettings()
     584{
     585    emit sigStartGroupSaving();
     586}
     587
     588bool UIGChooserModel::isGroupSavingInProgress() const
     589{
     590    return UIGroupDefinitionSaveThread::instance() ||
     591           UIGroupOrderSaveThread::instance();
    592592}
    593593
     
    656656}
    657657
    658 void UIGChooserModel::sltCurrentDragObjectDestroyed()
    659 {
    660     /* Reset drag tokens starting from the root item: */
    661     root()->resetDragToken();
    662 }
    663 
    664 void UIGChooserModel::sltStartScrolling()
    665 {
    666     /* Should we scroll? */
    667     if (!m_fIsScrollingInProgress)
    668         return;
    669 
    670     /* Reset scrolling progress: */
    671     m_fIsScrollingInProgress = false;
    672 
    673     /* Get view/scrollbar: */
    674     QGraphicsView *pView = scene()->views()[0];
    675     QScrollBar *pVerticalScrollBar = pView->verticalScrollBar();
    676 
    677     /* Request still valid? */
    678     QPoint mousePos = pView->mapFromGlobal(QCursor::pos());
    679     if (mousePos.y() < m_iScrollingTokenSize)
    680     {
    681         int iValue = mousePos.y();
    682         if (!iValue) iValue = 1;
    683         int iDelta = m_iScrollingTokenSize / iValue;
    684         if (pVerticalScrollBar->value() > pVerticalScrollBar->minimum())
    685         {
    686             /* Backward scrolling: */
    687             pVerticalScrollBar->setValue(pVerticalScrollBar->value() - 2 * iDelta);
    688             m_fIsScrollingInProgress = true;
    689             QTimer::singleShot(10, this, SLOT(sltStartScrolling()));
    690         }
    691     }
    692     else if (mousePos.y() > pView->height() - m_iScrollingTokenSize)
    693     {
    694         int iValue = pView->height() - mousePos.y();
    695         if (!iValue) iValue = 1;
    696         int iDelta = m_iScrollingTokenSize / iValue;
    697         if (pVerticalScrollBar->value() < pVerticalScrollBar->maximum())
    698         {
    699             /* Forward scrolling: */
    700             pVerticalScrollBar->setValue(pVerticalScrollBar->value() + 2 * iDelta);
    701             m_fIsScrollingInProgress = true;
    702             QTimer::singleShot(10, this, SLOT(sltStartScrolling()));
    703         }
    704     }
    705 }
    706 
    707 void UIGChooserModel::sltRemoveCurrentlySelectedGroup()
    708 {
    709     /* Make sure focus item is of group type! */
    710     AssertMsg(focusItem()->type() == UIGChooserItemType_Group, ("This is not group item!"));
    711 
    712     /* Check if we have collisions with our siblings: */
    713     UIGChooserItem *pFocusItem = focusItem();
    714     UIGChooserItem *pParentItem = pFocusItem->parentItem();
    715     QList<UIGChooserItem*> siblings = pParentItem->items();
    716     QList<UIGChooserItem*> toBeRenamed;
    717     QList<UIGChooserItem*> toBeRemoved;
    718     foreach (UIGChooserItem *pItem, pFocusItem->items())
    719     {
    720         QString strItemName = pItem->name();
    721         UIGChooserItem *pCollisionSibling = 0;
    722         foreach (UIGChooserItem *pSibling, siblings)
    723             if (pSibling != pFocusItem && pSibling->name() == strItemName)
    724                 pCollisionSibling = pSibling;
    725         if (pCollisionSibling)
    726         {
    727             if (pItem->type() == UIGChooserItemType_Machine)
    728             {
    729                 if (pCollisionSibling->type() == UIGChooserItemType_Machine)
    730                     toBeRemoved << pItem;
    731                 else if (pCollisionSibling->type() == UIGChooserItemType_Group)
    732                 {
    733                     msgCenter().notifyAboutCollisionOnGroupRemovingCantBeResolved(strItemName, pParentItem->name());
    734                     return;
    735                 }
    736             }
    737             else if (pItem->type() == UIGChooserItemType_Group)
    738             {
    739                 if (msgCenter().askAboutCollisionOnGroupRemoving(strItemName, pParentItem->name()) == QIMessageBox::Ok)
    740                     toBeRenamed << pItem;
    741                 else
    742                     return;
    743             }
    744         }
    745     }
    746 
    747     /* Copy all the children into our parent: */
    748     foreach (UIGChooserItem *pItem, pFocusItem->items())
    749     {
    750         if (toBeRemoved.contains(pItem))
    751             continue;
    752         switch (pItem->type())
    753         {
    754             case UIGChooserItemType_Group:
    755             {
    756                 UIGChooserItemGroup *pGroupItem = new UIGChooserItemGroup(pParentItem, pItem->toGroupItem());
    757                 if (toBeRenamed.contains(pItem))
    758                     pGroupItem->setName(uniqueGroupName(pParentItem));
    759                 break;
    760             }
    761             case UIGChooserItemType_Machine:
    762             {
    763                 new UIGChooserItemMachine(pParentItem, pItem->toMachineItem());
    764                 break;
    765             }
    766         }
    767     }
    768 
    769     /* Delete focus group: */
    770     delete focusItem();
    771 
    772     /* And update model: */
     658void UIGChooserModel::sltFocusItemDestroyed()
     659{
     660    AssertMsgFailed(("Focus item destroyed!"));
     661}
     662
     663void UIGChooserModel::sltLeftRootSlidingProgress()
     664{
     665    /* Update left root: */
     666    m_pLeftRoot->updateSizeHint();
     667    m_pLeftRoot->updateLayout();
     668}
     669
     670void UIGChooserModel::sltRightRootSlidingProgress()
     671{
     672    /* Update right root: */
     673    m_pRightRoot->updateSizeHint();
     674    m_pRightRoot->updateLayout();
     675}
     676
     677void UIGChooserModel::sltSlidingComplete()
     678{
     679    /* Delete temporary roots: */
     680    delete m_pLeftRoot;
     681    m_pLeftRoot = 0;
     682    delete m_pRightRoot;
     683    m_pRightRoot = 0;
     684
     685    /* We are no more sliding: */
     686    m_fSliding = false;
     687
     688    /* Update model: */
    773689    updateGroupTree();
    774690    updateNavigation();
    775691    updateLayout();
    776     if (mainRoot()->hasItems())
    777         setCurrentItem(0);
     692    if (m_pAfterSlidingFocus)
     693    {
     694        setCurrentItem(m_pAfterSlidingFocus);
     695        m_pAfterSlidingFocus = 0;
     696    }
    778697    else
    779         unsetCurrentItem();
    780     saveGroupSettings();
    781 }
    782 
    783 void UIGChooserModel::sltRemoveCurrentlySelectedMachine()
    784 {
    785     /* Enumerate all the selected machine items: */
    786     QList<UIGChooserItem*> selectedMachineItemList = gatherMachineItems(selectionList());
    787     /* Enumerate all the existing machine items: */
    788     QList<UIGChooserItem*> existingMachineItemList = gatherMachineItems(mainRoot()->items());
    789 
    790     /* Prepare maps: */
    791     QMap<QString, bool> verdictMap;
    792     QMap<QString, QString> namesMap;
    793 
    794     /* For each selected machine item: */
    795     foreach (UIGChooserItem *pItem, selectedMachineItemList)
    796     {
    797         /* Get item name/id: */
    798         QString strName = pItem->name();
    799         QString strId = pItem->toMachineItem()->id();
    800 
    801         /* Check if we already decided for that machine: */
    802         if (verdictMap.contains(strId))
    803             continue;
    804 
    805         /* Selected copy count: */
    806         int iSelectedCopyCount = 0;
    807         foreach (UIGChooserItem *pSelectedItem, selectedMachineItemList)
    808             if (pSelectedItem->toMachineItem()->id() == strId)
    809                 ++iSelectedCopyCount;
    810 
    811         /* Existing copy count: */
    812         int iExistingCopyCount = 0;
    813         foreach (UIGChooserItem *pExistingItem, existingMachineItemList)
    814             if (pExistingItem->toMachineItem()->id() == strId)
    815                 ++iExistingCopyCount;
    816 
    817         /* If selected copy count equal to existing copy count,
    818          * we will propose ro unregister machine fully else
    819          * we will just propose to remove selected items: */
    820         verdictMap.insert(strId, iSelectedCopyCount == iExistingCopyCount);
    821         namesMap.insert(strId, strName);
    822     }
    823 
    824     /* If we have something to remove: */
    825     if (verdictMap.values().contains(false))
    826     {
    827         /* Gather names: */
    828         QStringList names;
    829         foreach (const QString &strId, verdictMap.keys())
    830             if (!verdictMap[strId])
    831                 names << namesMap[strId];
    832         removeMachineItems(names, selectedMachineItemList);
    833     }
    834     /* If we have something to unregister: */
    835     if (verdictMap.values().contains(true))
    836     {
    837         /* Gather ids: */
    838         QStringList ids;
    839         foreach (const QString &strId, verdictMap.keys())
    840             if (verdictMap[strId])
    841                 ids << strId;
    842         unregisterMachines(ids);
     698    {
     699        if (root()->hasItems())
     700            setCurrentItem(root()->items().first());
     701        else
     702            unsetCurrentItem();
    843703    }
    844704}
     
    905765}
    906766
     767void UIGChooserModel::sltSortGroup()
     768{
     769    if (isSingleGroupSelected())
     770        sortItems(selectionList().first());
     771}
     772
     773void UIGChooserModel::sltRemoveCurrentlySelectedGroup()
     774{
     775    /* Make sure focus item is of group type! */
     776    AssertMsg(focusItem()->type() == UIGChooserItemType_Group, ("This is not group item!"));
     777
     778    /* Check if we have collisions with our siblings: */
     779    UIGChooserItem *pFocusItem = focusItem();
     780    UIGChooserItem *pParentItem = pFocusItem->parentItem();
     781    QList<UIGChooserItem*> siblings = pParentItem->items();
     782    QList<UIGChooserItem*> toBeRenamed;
     783    QList<UIGChooserItem*> toBeRemoved;
     784    foreach (UIGChooserItem *pItem, pFocusItem->items())
     785    {
     786        QString strItemName = pItem->name();
     787        UIGChooserItem *pCollisionSibling = 0;
     788        foreach (UIGChooserItem *pSibling, siblings)
     789            if (pSibling != pFocusItem && pSibling->name() == strItemName)
     790                pCollisionSibling = pSibling;
     791        if (pCollisionSibling)
     792        {
     793            if (pItem->type() == UIGChooserItemType_Machine)
     794            {
     795                if (pCollisionSibling->type() == UIGChooserItemType_Machine)
     796                    toBeRemoved << pItem;
     797                else if (pCollisionSibling->type() == UIGChooserItemType_Group)
     798                {
     799                    msgCenter().notifyAboutCollisionOnGroupRemovingCantBeResolved(strItemName, pParentItem->name());
     800                    return;
     801                }
     802            }
     803            else if (pItem->type() == UIGChooserItemType_Group)
     804            {
     805                if (msgCenter().askAboutCollisionOnGroupRemoving(strItemName, pParentItem->name()) == QIMessageBox::Ok)
     806                    toBeRenamed << pItem;
     807                else
     808                    return;
     809            }
     810        }
     811    }
     812
     813    /* Copy all the children into our parent: */
     814    foreach (UIGChooserItem *pItem, pFocusItem->items())
     815    {
     816        if (toBeRemoved.contains(pItem))
     817            continue;
     818        switch (pItem->type())
     819        {
     820            case UIGChooserItemType_Group:
     821            {
     822                UIGChooserItemGroup *pGroupItem = new UIGChooserItemGroup(pParentItem, pItem->toGroupItem());
     823                if (toBeRenamed.contains(pItem))
     824                    pGroupItem->setName(uniqueGroupName(pParentItem));
     825                break;
     826            }
     827            case UIGChooserItemType_Machine:
     828            {
     829                new UIGChooserItemMachine(pParentItem, pItem->toMachineItem());
     830                break;
     831            }
     832        }
     833    }
     834
     835    /* Delete focus group: */
     836    delete focusItem();
     837
     838    /* And update model: */
     839    updateGroupTree();
     840    updateNavigation();
     841    updateLayout();
     842    if (mainRoot()->hasItems())
     843        setCurrentItem(0);
     844    else
     845        unsetCurrentItem();
     846    saveGroupSettings();
     847}
     848
    907849void UIGChooserModel::sltCreateNewMachine()
    908850{
     
    922864}
    923865
    924 void UIGChooserModel::sltActionHovered(QAction *pAction)
    925 {
    926     emit sigShowStatusMessage(pAction->statusTip());
    927 }
    928 
    929 void UIGChooserModel::sltFocusItemDestroyed()
    930 {
    931     AssertMsgFailed(("Focus item destroyed!"));
    932 }
    933 
    934 void UIGChooserModel::sltLeftRootSlidingProgress()
    935 {
    936     /* Update left root: */
    937     m_pLeftRoot->updateSizeHint();
    938     m_pLeftRoot->updateLayout();
    939 }
    940 
    941 void UIGChooserModel::sltRightRootSlidingProgress()
    942 {
    943     /* Update right root: */
    944     m_pRightRoot->updateSizeHint();
    945     m_pRightRoot->updateLayout();
    946 }
    947 
    948 void UIGChooserModel::sltSlidingComplete()
    949 {
    950     /* Delete temporary roots: */
    951     delete m_pLeftRoot;
    952     m_pLeftRoot = 0;
    953     delete m_pRightRoot;
    954     m_pRightRoot = 0;
    955 
    956     /* We are no more sliding: */
    957     m_fSliding = false;
    958 
    959     /* Update model: */
     866void UIGChooserModel::sltReloadMachine(const QString &strId)
     867{
     868    /* Remove all the items first: */
     869    removeMachineItems(strId, mainRoot());
     870
     871    /* Check if such machine still present: */
     872    CMachine machine = vboxGlobal().virtualBox().FindMachine(strId);
     873    if (machine.isNull())
     874        return;
     875
     876    /* Add machine into the tree: */
     877    addMachineIntoTheTree(machine);
     878
     879    /* And update model: */
    960880    updateGroupTree();
    961881    updateNavigation();
    962882    updateLayout();
    963     if (m_pAfterSlidingFocus)
    964     {
    965         setCurrentItem(m_pAfterSlidingFocus);
    966         m_pAfterSlidingFocus = 0;
    967     }
    968     else
    969     {
    970         if (root()->hasItems())
    971             setCurrentItem(root()->items().first());
    972         else
    973             unsetCurrentItem();
    974     }
     883
     884    /* Notify listeners about selection change: */
     885    emit sigSelectionChanged();
     886}
     887
     888void UIGChooserModel::sltSortParentGroup()
     889{
     890    if (!selectionList().isEmpty())
     891        sortItems(selectionList().first()->parentItem());
    975892}
    976893
     
    1008925}
    1009926
    1010 void UIGChooserModel::sltSortParentGroup()
    1011 {
    1012     if (!selectionList().isEmpty())
    1013         sortItems(selectionList().first()->parentItem());
    1014 }
    1015 
    1016 void UIGChooserModel::sltSortGroup()
    1017 {
    1018     if (isSingleGroupSelected())
    1019         sortItems(selectionList().first());
     927void UIGChooserModel::sltRemoveCurrentlySelectedMachine()
     928{
     929    /* Enumerate all the selected machine items: */
     930    QList<UIGChooserItem*> selectedMachineItemList = gatherMachineItems(selectionList());
     931    /* Enumerate all the existing machine items: */
     932    QList<UIGChooserItem*> existingMachineItemList = gatherMachineItems(mainRoot()->items());
     933
     934    /* Prepare maps: */
     935    QMap<QString, bool> verdictMap;
     936    QMap<QString, QString> namesMap;
     937
     938    /* For each selected machine item: */
     939    foreach (UIGChooserItem *pItem, selectedMachineItemList)
     940    {
     941        /* Get item name/id: */
     942        QString strName = pItem->name();
     943        QString strId = pItem->toMachineItem()->id();
     944
     945        /* Check if we already decided for that machine: */
     946        if (verdictMap.contains(strId))
     947            continue;
     948
     949        /* Selected copy count: */
     950        int iSelectedCopyCount = 0;
     951        foreach (UIGChooserItem *pSelectedItem, selectedMachineItemList)
     952            if (pSelectedItem->toMachineItem()->id() == strId)
     953                ++iSelectedCopyCount;
     954
     955        /* Existing copy count: */
     956        int iExistingCopyCount = 0;
     957        foreach (UIGChooserItem *pExistingItem, existingMachineItemList)
     958            if (pExistingItem->toMachineItem()->id() == strId)
     959                ++iExistingCopyCount;
     960
     961        /* If selected copy count equal to existing copy count,
     962         * we will propose ro unregister machine fully else
     963         * we will just propose to remove selected items: */
     964        verdictMap.insert(strId, iSelectedCopyCount == iExistingCopyCount);
     965        namesMap.insert(strId, strName);
     966    }
     967
     968    /* If we have something to remove: */
     969    if (verdictMap.values().contains(false))
     970    {
     971        /* Gather names: */
     972        QStringList names;
     973        foreach (const QString &strId, verdictMap.keys())
     974            if (!verdictMap[strId])
     975                names << namesMap[strId];
     976        removeMachineItems(names, selectedMachineItemList);
     977    }
     978    /* If we have something to unregister: */
     979    if (verdictMap.values().contains(true))
     980    {
     981        /* Gather ids: */
     982        QStringList ids;
     983        foreach (const QString &strId, verdictMap.keys())
     984            if (verdictMap[strId])
     985                ids << strId;
     986        unregisterMachines(ids);
     987    }
     988}
     989
     990void UIGChooserModel::sltStartScrolling()
     991{
     992    /* Should we scroll? */
     993    if (!m_fIsScrollingInProgress)
     994        return;
     995
     996    /* Reset scrolling progress: */
     997    m_fIsScrollingInProgress = false;
     998
     999    /* Get view/scrollbar: */
     1000    QGraphicsView *pView = scene()->views()[0];
     1001    QScrollBar *pVerticalScrollBar = pView->verticalScrollBar();
     1002
     1003    /* Request still valid? */
     1004    QPoint mousePos = pView->mapFromGlobal(QCursor::pos());
     1005    if (mousePos.y() < m_iScrollingTokenSize)
     1006    {
     1007        int iValue = mousePos.y();
     1008        if (!iValue) iValue = 1;
     1009        int iDelta = m_iScrollingTokenSize / iValue;
     1010        if (pVerticalScrollBar->value() > pVerticalScrollBar->minimum())
     1011        {
     1012            /* Backward scrolling: */
     1013            pVerticalScrollBar->setValue(pVerticalScrollBar->value() - 2 * iDelta);
     1014            m_fIsScrollingInProgress = true;
     1015            QTimer::singleShot(10, this, SLOT(sltStartScrolling()));
     1016        }
     1017    }
     1018    else if (mousePos.y() > pView->height() - m_iScrollingTokenSize)
     1019    {
     1020        int iValue = pView->height() - mousePos.y();
     1021        if (!iValue) iValue = 1;
     1022        int iDelta = m_iScrollingTokenSize / iValue;
     1023        if (pVerticalScrollBar->value() < pVerticalScrollBar->maximum())
     1024        {
     1025            /* Forward scrolling: */
     1026            pVerticalScrollBar->setValue(pVerticalScrollBar->value() + 2 * iDelta);
     1027            m_fIsScrollingInProgress = true;
     1028            QTimer::singleShot(10, this, SLOT(sltStartScrolling()));
     1029        }
     1030    }
     1031}
     1032
     1033void UIGChooserModel::sltCurrentDragObjectDestroyed()
     1034{
     1035    /* Reset drag tokens starting from the root item: */
     1036    root()->resetDragToken();
     1037}
     1038
     1039void UIGChooserModel::sltActionHovered(QAction *pAction)
     1040{
     1041    emit sigShowStatusMessage(pAction->statusTip());
     1042}
     1043
     1044void UIGChooserModel::sltEraseLookupTimer()
     1045{
     1046    m_pLookupTimer->stop();
     1047    m_strLookupString = QString();
    10201048}
    10211049
     
    10361064    makeSureGroupOrdersSaveIsFinished();
    10371065    emit sigGroupSavingStateChanged();
    1038 }
    1039 
    1040 void UIGChooserModel::sltReloadMachine(const QString &strId)
    1041 {
    1042     /* Remove all the items first: */
    1043     removeMachineItems(strId, mainRoot());
    1044 
    1045     /* Check if such machine still present: */
    1046     CMachine machine = vboxGlobal().virtualBox().FindMachine(strId);
    1047     if (machine.isNull())
    1048         return;
    1049 
    1050     /* Add machine into the tree: */
    1051     addMachineIntoTheTree(machine);
    1052 
    1053     /* And update model: */
    1054     updateGroupTree();
    1055     updateNavigation();
    1056     updateLayout();
    1057 
    1058     /* Notify listeners about selection change: */
    1059     emit sigSelectionChanged();
    1060 }
    1061 
    1062 void UIGChooserModel::sltEraseLookupTimer()
    1063 {
    1064     m_pLookupTimer->stop();
    1065     m_strLookupString = QString();
    10661066}
    10671067
     
    13191319}
    13201320
    1321 void UIGChooserModel::clearRealFocus()
    1322 {
    1323     /* Set real focus to null: */
    1324     scene()->setFocusItem(0);
     1321QList<UIGChooserItem*> UIGChooserModel::createNavigationList(UIGChooserItem *pItem)
     1322{
     1323    /* Prepare navigation list: */
     1324    QList<UIGChooserItem*> navigationItems;
     1325
     1326    /* Iterate over all the group items: */
     1327    foreach (UIGChooserItem *pGroupItem, pItem->items(UIGChooserItemType_Group))
     1328    {
     1329        navigationItems << pGroupItem;
     1330        if (pGroupItem->toGroupItem()->opened())
     1331            navigationItems << createNavigationList(pGroupItem);
     1332    }
     1333    /* Iterate over all the machine items: */
     1334    foreach (UIGChooserItem *pMachineItem, pItem->items(UIGChooserItemType_Machine))
     1335        navigationItems << pMachineItem;
     1336
     1337    /* Return navigation list: */
     1338    return navigationItems;
    13251339}
    13261340
     
    13841398}
    13851399
    1386 void UIGChooserModel::loadGroupTree()
    1387 {
    1388     /* Add all the machines we have into the group-tree: */
    1389     LogRel(("Loading VMs started...\n"));
    1390     foreach (const CMachine &machine, vboxGlobal().virtualBox().GetMachines())
    1391         addMachineIntoTheTree(machine);
    1392     LogRel(("Loading VMs finished.\n"));
    1393 }
    1394 
    1395 void UIGChooserModel::addMachineIntoTheTree(const CMachine &machine, bool fMakeItVisible /* = false */)
    1396 {
    1397     /* Which VM we are loading: */
    1398     if (machine.isNull())
    1399         LogRel((" ERROR: VM is NULL!\n"));
    1400     else
    1401         LogRel((" Loading VM {%s}...\n", machine.GetId().toAscii().constData()));
    1402     /* Is that machine accessible? */
    1403     if (machine.GetAccessible())
    1404     {
    1405         /* VM is accessible: */
    1406         QString strName = machine.GetName();
    1407         LogRel((" VM {%s} is accessible.\n", strName.toAscii().constData()));
    1408         /* Which groups passed machine attached to? */
    1409         QVector<QString> groups = machine.GetGroups();
    1410         QStringList groupList = groups.toList();
    1411         QString strGroups = groupList.join(", ");
    1412         LogRel((" VM {%s} groups are {%s}.\n", strName.toAscii().constData(),
    1413                                                strGroups.toAscii().constData()));
    1414         foreach (QString strGroup, groups)
    1415         {
    1416             /* Remove last '/' if any: */
    1417             if (strGroup.right(1) == "/")
    1418                 strGroup.truncate(strGroup.size() - 1);
    1419             /* Create machine item with found group item as parent: */
    1420             LogRel(("  Creating item for VM {%s}, group {%s}.\n", strName.toAscii().constData(),
    1421                                                                   strGroup.toAscii().constData()));
    1422             createMachineItem(machine, getGroupItem(strGroup, mainRoot(), fMakeItVisible));
    1423         }
    1424         /* Update group definitions: */
    1425         m_groups[machine.GetId()] = groupList;
    1426     }
    1427     /* Inaccessible machine: */
    1428     else
    1429     {
    1430         /* VM is accessible: */
    1431         LogRel((" VM {%s} is inaccessible.\n", machine.GetId().toAscii().constData()));
    1432         /* Create machine item with main-root group item as parent: */
    1433         createMachineItem(machine, mainRoot());
    1434     }
    1435 }
    1436 
    1437 UIGChooserItem* UIGChooserModel::getGroupItem(const QString &strName, UIGChooserItem *pParentItem, bool fAllGroupsOpened)
    1438 {
    1439     /* Check passed stuff: */
    1440     if (pParentItem->name() == strName)
    1441         return pParentItem;
    1442 
    1443     /* Prepare variables: */
    1444     QString strFirstSubName = strName.section('/', 0, 0);
    1445     QString strFirstSuffix = strName.section('/', 1, -1);
    1446     QString strSecondSubName = strFirstSuffix.section('/', 0, 0);
    1447     QString strSecondSuffix = strFirstSuffix.section('/', 1, -1);
    1448 
    1449     /* Passed group name equal to first sub-name: */
    1450     if (pParentItem->name() == strFirstSubName)
    1451     {
    1452         /* Make sure first-suffix is NOT empty: */
    1453         AssertMsg(!strFirstSuffix.isEmpty(), ("Invalid group name!"));
    1454         /* Trying to get group item among our children: */
    1455         foreach (UIGChooserItem *pGroupItem, pParentItem->items(UIGChooserItemType_Group))
    1456         {
    1457             if (pGroupItem->name() == strSecondSubName)
    1458             {
    1459                 UIGChooserItem *pFoundItem = getGroupItem(strFirstSuffix, pGroupItem, fAllGroupsOpened);
    1460                 if (UIGChooserItemGroup *pFoundGroupItem = pFoundItem->toGroupItem())
    1461                     if (fAllGroupsOpened && pFoundGroupItem->closed())
    1462                         pFoundGroupItem->open(false);
    1463                 return pFoundItem;
    1464             }
    1465         }
    1466     }
    1467 
    1468     /* Found nothing? Creating: */
    1469     UIGChooserItemGroup *pNewGroupItem =
    1470             new UIGChooserItemGroup(/* Parent item and desired group name: */
    1471                                     pParentItem, strSecondSubName,
    1472                                     /* Should be new group opened when created? */
    1473                                     fAllGroupsOpened || shouldBeGroupOpened(pParentItem, strSecondSubName),
    1474                                     /* Which position new group item should be placed in? */
    1475                                     getDesiredPosition(pParentItem, UIGChooserItemType_Group, strSecondSubName));
    1476     return strSecondSuffix.isEmpty() ? pNewGroupItem : getGroupItem(strFirstSuffix, pNewGroupItem, fAllGroupsOpened);
    1477 }
    1478 
    1479 bool UIGChooserModel::shouldBeGroupOpened(UIGChooserItem *pParentItem, const QString &strName)
    1480 {
    1481     /* Prepare extra-data key for the parent-item: */
    1482     QString strExtraDataKey = UIDefs::GUI_GroupDefinitions + fullName(pParentItem);
    1483     /* Read group definitions: */
    1484     QStringList definitions = vboxGlobal().virtualBox().GetExtraDataStringList(strExtraDataKey);
    1485     /* Return 'false' if no definitions found: */
    1486     if (definitions.isEmpty())
    1487         return false;
    1488 
    1489     /* Prepare required group definition reg-exp: */
    1490     QString strDefinitionTemplate = QString("g(\\S)*=%1").arg(strName);
    1491     QRegExp definitionRegExp(strDefinitionTemplate);
    1492     /* For each the group definition: */
    1493     for (int i = 0; i < definitions.size(); ++i)
    1494     {
    1495         /* Get current definition: */
    1496         const QString &strDefinition = definitions[i];
    1497         /* Check if this is required definition: */
    1498         if (definitionRegExp.indexIn(strDefinition) == 0)
    1499         {
    1500             /* Get group descriptor: */
    1501             QString strDescriptor(definitionRegExp.cap(1));
    1502             if (strDescriptor.contains('o'))
    1503                 return true;
    1504         }
    1505     }
    1506 
    1507     /* Return 'false' by default: */
    1508     return false;
    1509 }
    1510 
    1511 int UIGChooserModel::getDesiredPosition(UIGChooserItem *pParentItem, UIGChooserItemType type, const QString &strName)
    1512 {
    1513     /* End of list (by default)? */
    1514     int iNewItemDesiredPosition = -1;
    1515     /* Which position should be new item placed by definitions: */
    1516     int iNewItemDefinitionPosition = positionFromDefinitions(pParentItem, type, strName);
    1517     /* If some position wanted: */
    1518     if (iNewItemDefinitionPosition != -1)
    1519     {
    1520         /* Start of list if some definition present: */
    1521         iNewItemDesiredPosition = 0;
    1522         /* We have to check all the existing item positions: */
    1523         QList<UIGChooserItem*> items = pParentItem->items(type);
    1524         for (int i = items.size() - 1; i >= 0; --i)
    1525         {
    1526             /* Get current item: */
    1527             UIGChooserItem *pItem = items[i];
    1528             /* Which position should be current item placed by definitions? */
    1529             QString strDefinitionName = pItem->type() == UIGChooserItemType_Group ? pItem->name() :
    1530                                         pItem->type() == UIGChooserItemType_Machine ? pItem->toMachineItem()->id() :
    1531                                         QString();
    1532             AssertMsg(!strDefinitionName.isEmpty(), ("Wrong definition name!"));
    1533             int iItemDefinitionPosition = positionFromDefinitions(pParentItem, type, strDefinitionName);
    1534             /* If some position wanted: */
    1535             if (iItemDefinitionPosition != -1)
    1536             {
    1537                 AssertMsg(iItemDefinitionPosition != iNewItemDefinitionPosition, ("Incorrect definitions!"));
    1538                 if (iItemDefinitionPosition < iNewItemDefinitionPosition)
    1539                 {
    1540                     iNewItemDesiredPosition = i + 1;
    1541                     break;
    1542                 }
    1543             }
    1544         }
    1545     }
    1546     /* Return desired item position: */
    1547     return iNewItemDesiredPosition;
    1548 }
    1549 
    1550 int UIGChooserModel::positionFromDefinitions(UIGChooserItem *pParentItem, UIGChooserItemType type, const QString &strName)
    1551 {
    1552     /* Prepare extra-data key for the parent-item: */
    1553     QString strExtraDataKey = UIDefs::GUI_GroupDefinitions + fullName(pParentItem);
    1554     /* Read group definitions: */
    1555     QStringList definitions = vboxGlobal().virtualBox().GetExtraDataStringList(strExtraDataKey);
    1556     /* Return 'false' if no definitions found: */
    1557     if (definitions.isEmpty())
    1558         return -1;
    1559 
    1560     /* Prepare definition reg-exp: */
    1561     QString strDefinitionTemplateShort;
    1562     QString strDefinitionTemplateFull;
    1563     switch (type)
    1564     {
    1565         case UIGChooserItemType_Group:
    1566             strDefinitionTemplateShort = QString("^g(\\S)*=");
    1567             strDefinitionTemplateFull = QString("^g(\\S)*=%1$").arg(strName);
    1568             break;
    1569         case UIGChooserItemType_Machine:
    1570             strDefinitionTemplateShort = QString("^m=");
    1571             strDefinitionTemplateFull = QString("^m=%1$").arg(strName);
    1572             break;
    1573         default: return -1;
    1574     }
    1575     QRegExp definitionRegExpShort(strDefinitionTemplateShort);
    1576     QRegExp definitionRegExpFull(strDefinitionTemplateFull);
    1577 
    1578     /* For each the definition: */
    1579     int iDefinitionIndex = -1;
    1580     for (int i = 0; i < definitions.size(); ++i)
    1581     {
    1582         /* Get current definition: */
    1583         QString strDefinition = definitions[i];
    1584         /* Check if this definition is of required type: */
    1585         if (definitionRegExpShort.indexIn(strDefinition) == 0)
    1586         {
    1587             ++iDefinitionIndex;
    1588             /* Check if this definition is exactly what we need: */
    1589             if (definitionRegExpFull.indexIn(strDefinition) == 0)
    1590                 return iDefinitionIndex;
    1591         }
    1592     }
    1593 
    1594     /* Return result: */
    1595     return -1;
    1596 }
    1597 
    1598 void UIGChooserModel::createMachineItem(const CMachine &machine, UIGChooserItem *pParentItem)
    1599 {
    1600     /* Create corresponding item: */
    1601     new UIGChooserItemMachine(/* Parent item and corresponding machine: */
    1602                               pParentItem, machine,
    1603                               /* Which position new group item should be placed in? */
    1604                               getDesiredPosition(pParentItem, UIGChooserItemType_Machine, machine.GetId()));
    1605 }
    1606 
    1607 void UIGChooserModel::saveGroupDefinitions()
    1608 {
    1609     /* Make sure there is no group save activity: */
    1610     if (UIGroupDefinitionSaveThread::instance())
    1611         return;
    1612 
    1613     /* Prepare full group map: */
    1614     QMap<QString, QStringList> groups;
    1615     gatherGroupDefinitions(groups, mainRoot());
    1616 
    1617     /* Save information in other thread: */
    1618     UIGroupDefinitionSaveThread::prepare();
    1619     emit sigGroupSavingStateChanged();
    1620     connect(UIGroupDefinitionSaveThread::instance(), SIGNAL(sigReload(QString)),
    1621             this, SLOT(sltReloadMachine(QString)));
    1622     UIGroupDefinitionSaveThread::instance()->configure(this, m_groups, groups);
    1623     UIGroupDefinitionSaveThread::instance()->start();
    1624     m_groups = groups;
    1625 }
    1626 
    1627 void UIGChooserModel::saveGroupOrders()
    1628 {
    1629     /* Make sure there is no group save activity: */
    1630     if (UIGroupOrderSaveThread::instance())
    1631         return;
    1632 
    1633     /* Prepare full group map: */
    1634     QMap<QString, QStringList> groups;
    1635     gatherGroupOrders(groups, mainRoot());
    1636 
    1637     /* Save information in other thread: */
    1638     UIGroupOrderSaveThread::prepare();
    1639     emit sigGroupSavingStateChanged();
    1640     UIGroupOrderSaveThread::instance()->configure(this, groups);
    1641     UIGroupOrderSaveThread::instance()->start();
    1642 }
    1643 
    1644 void UIGChooserModel::gatherGroupDefinitions(QMap<QString, QStringList> &groups,
    1645                                              UIGChooserItem *pParentGroup)
    1646 {
    1647     /* Iterate over all the machine items: */
    1648     foreach (UIGChooserItem *pItem, pParentGroup->items(UIGChooserItemType_Machine))
    1649         if (UIGChooserItemMachine *pMachineItem = pItem->toMachineItem())
    1650             if (pMachineItem->accessible())
    1651                 groups[pMachineItem->id()] << fullName(pParentGroup);
    1652     /* Iterate over all the group items: */
    1653     foreach (UIGChooserItem *pItem, pParentGroup->items(UIGChooserItemType_Group))
    1654         gatherGroupDefinitions(groups, pItem);
    1655 }
    1656 
    1657 void UIGChooserModel::gatherGroupOrders(QMap<QString, QStringList> &groups,
    1658                                         UIGChooserItem *pParentItem)
    1659 {
    1660     /* Prepare extra-data key for current group: */
    1661     QString strExtraDataKey = UIDefs::GUI_GroupDefinitions + fullName(pParentItem);
    1662     /* Iterate over all the group items: */
    1663     foreach (UIGChooserItem *pItem, pParentItem->items(UIGChooserItemType_Group))
    1664     {
    1665         QString strGroupDescriptor(pItem->toGroupItem()->opened() ? "go" : "gc");
    1666         groups[strExtraDataKey] << QString("%1=%2").arg(strGroupDescriptor, pItem->name());
    1667         gatherGroupOrders(groups, pItem);
    1668     }
    1669     /* Iterate over all the machine items: */
    1670     foreach (UIGChooserItem *pItem, pParentItem->items(UIGChooserItemType_Machine))
    1671         groups[strExtraDataKey] << QString("m=%1").arg(pItem->toMachineItem()->id());
    1672 }
    1673 
    1674 QString UIGChooserModel::fullName(UIGChooserItem *pItem)
    1675 {
    1676     /* Return '/' for root-group: */
    1677     if (!pItem->parentItem())
    1678         return QString("/");
    1679     /* Get full parent name, append with '/' if not yet appended: */
    1680     QString strParentFullName = fullName(pItem->parentItem());
    1681     if (!strParentFullName.endsWith("/"))
    1682         strParentFullName += QString("/");
    1683     /* Return full item name based on parent prefix: */
    1684     return strParentFullName + pItem->name();
     1400void UIGChooserModel::clearRealFocus()
     1401{
     1402    /* Set real focus to null: */
     1403    scene()->setFocusItem(0);
     1404}
     1405
     1406void UIGChooserModel::slideRoot(bool fForward)
     1407{
     1408    /* Animation group: */
     1409    QParallelAnimationGroup *pAnimation = new QParallelAnimationGroup(this);
     1410    connect(pAnimation, SIGNAL(finished()), this, SLOT(sltSlidingComplete()), Qt::QueuedConnection);
     1411
     1412    /* Left root animation: */
     1413    {
     1414        QPropertyAnimation *pLeftAnimation = new QPropertyAnimation(m_pLeftRoot, "geometry", this);
     1415        connect(pLeftAnimation, SIGNAL(valueChanged(const QVariant&)), this, SLOT(sltLeftRootSlidingProgress()));
     1416        QRectF startGeo = m_pLeftRoot->geometry();
     1417        QRectF endGeo = fForward ? startGeo.translated(- startGeo.width(), 0) :
     1418                                   startGeo.translated(startGeo.width(), 0);
     1419        pLeftAnimation->setEasingCurve(QEasingCurve::InCubic);
     1420        pLeftAnimation->setDuration(500);
     1421        pLeftAnimation->setStartValue(startGeo);
     1422        pLeftAnimation->setEndValue(endGeo);
     1423        pAnimation->addAnimation(pLeftAnimation);
     1424    }
     1425
     1426    /* Right root animation: */
     1427    {
     1428        QPropertyAnimation *pRightAnimation = new QPropertyAnimation(m_pRightRoot, "geometry", this);
     1429        connect(pRightAnimation, SIGNAL(valueChanged(const QVariant&)), this, SLOT(sltRightRootSlidingProgress()));
     1430        QRectF startGeo = m_pRightRoot->geometry();
     1431        QRectF endGeo = fForward ? startGeo.translated(- startGeo.width(), 0) :
     1432                                   startGeo.translated(startGeo.width(), 0);
     1433        pRightAnimation->setEasingCurve(QEasingCurve::InCubic);
     1434        pRightAnimation->setDuration(500);
     1435        pRightAnimation->setStartValue(startGeo);
     1436        pRightAnimation->setEndValue(endGeo);
     1437        pAnimation->addAnimation(pRightAnimation);
     1438    }
     1439
     1440    /* Start animation: */
     1441    pAnimation->start();
     1442}
     1443
     1444UIGChooserItem* UIGChooserModel::findGroupItem(const QString &strName, UIGChooserItem *pParent)
     1445{
     1446    /* Search among all the group items of passed parent: */
     1447    foreach (UIGChooserItem *pGroupItem, pParent->items(UIGChooserItemType_Group))
     1448        if (pGroupItem->name() == strName)
     1449            return pGroupItem;
     1450    /* Recursively iterate into each the group item of the passed parent: */
     1451    foreach (UIGChooserItem *pGroupItem, pParent->items(UIGChooserItemType_Group))
     1452        if (UIGChooserItem *pSubGroupItem = findGroupItem(strName, pGroupItem))
     1453            return pSubGroupItem;
     1454    /* Nothing found? */
     1455    return 0;
    16851456}
    16861457
     
    17011472}
    17021473
    1703 QList<UIGChooserItem*> UIGChooserModel::createNavigationList(UIGChooserItem *pItem)
    1704 {
    1705     /* Prepare navigation list: */
    1706     QList<UIGChooserItem*> navigationItems;
    1707 
    1708     /* Iterate over all the group items: */
    1709     foreach (UIGChooserItem *pGroupItem, pItem->items(UIGChooserItemType_Group))
    1710     {
    1711         navigationItems << pGroupItem;
    1712         if (pGroupItem->toGroupItem()->opened())
    1713             navigationItems << createNavigationList(pGroupItem);
    1714     }
    1715     /* Iterate over all the machine items: */
    1716     foreach (UIGChooserItem *pMachineItem, pItem->items(UIGChooserItemType_Machine))
    1717         navigationItems << pMachineItem;
    1718 
    1719     /* Return navigation list: */
    1720     return navigationItems;
     1474UIGChooserItem* UIGChooserModel::findMachineItem(const QString &strName, UIGChooserItem *pParent)
     1475{
     1476    /* Search among all the machine items of passed parent: */
     1477    foreach (UIGChooserItem *pMachineItem, pParent->items(UIGChooserItemType_Machine))
     1478        if (pMachineItem->name() == strName)
     1479            return pMachineItem;
     1480    /* Recursively iterate into each the group item of the passed parent: */
     1481    foreach (UIGChooserItem *pGroupItem, pParent->items(UIGChooserItemType_Group))
     1482        if (UIGChooserItem *pSubMachineItem = findMachineItem(strName, pGroupItem))
     1483            return pSubMachineItem;
     1484    /* Nothing found? */
     1485    return 0;
     1486}
     1487
     1488QList<UIGChooserItem*> UIGChooserModel::gatherMachineItems(const QList<UIGChooserItem*> &selectedItems) const
     1489{
     1490    QList<UIGChooserItem*> machineItems;
     1491    foreach (UIGChooserItem *pItem, selectedItems)
     1492    {
     1493        if (pItem->type() == UIGChooserItemType_Machine)
     1494            machineItems << pItem;
     1495        if (pItem->type() == UIGChooserItemType_Group)
     1496            machineItems << gatherMachineItems(pItem->items());
     1497    }
     1498    return machineItems;
     1499}
     1500
     1501void UIGChooserModel::enumerateInaccessibleItems(const QList<UIGChooserItem*> &il, QList<UIGChooserItem*> &ol) const
     1502{
     1503    /* Enumerate all the passed items: */
     1504    foreach (UIGChooserItem *pItem, il)
     1505    {
     1506        /* If item is inaccessible machine: */
     1507        if (pItem->type() == UIGChooserItemType_Machine)
     1508        {
     1509            if (UIGChooserItemMachine *pMachineItem = pItem->toMachineItem())
     1510                if (!pMachineItem->accessible() && !contains(ol, pItem))
     1511                    ol << pMachineItem;
     1512        }
     1513        /* If item is group: */
     1514        else if (pItem->type() == UIGChooserItemType_Group)
     1515        {
     1516            /* Enumerate all the machine items recursively: */
     1517            enumerateInaccessibleItems(pItem->items(UIGChooserItemType_Machine), ol);
     1518            /* Enumerate all the group items recursively: */
     1519            enumerateInaccessibleItems(pItem->items(UIGChooserItemType_Group), ol);
     1520        }
     1521    }
     1522}
     1523
     1524bool UIGChooserModel::contains(const QList<UIGChooserItem*> &il, UIGChooserItem *pLookupItem) const
     1525{
     1526    /* We assume passed list contains only machine items: */
     1527    foreach (UIGChooserItem *pItem, il)
     1528        if (UIGChooserItemMachine *pMachineItem = pItem->toMachineItem())
     1529            if (pMachineItem->id() == pLookupItem->toMachineItem()->id())
     1530                return true;
     1531    return false;
     1532}
     1533
     1534void UIGChooserModel::sortItems(UIGChooserItem *pParent, bool fRecursively /* = false */)
     1535{
     1536    /* Sort group items: */
     1537    QMap<QString, UIGChooserItem*> sorter;
     1538    foreach (UIGChooserItem *pItem, pParent->items(UIGChooserItemType_Group))
     1539    {
     1540        sorter.insert(pItem->name().toLower(), pItem);
     1541        if (fRecursively)
     1542            sortItems(pItem, fRecursively);
     1543    }
     1544    pParent->setItems(sorter.values(), UIGChooserItemType_Group);
     1545
     1546    /* Sort machine items: */
     1547    sorter.clear();
     1548    foreach (UIGChooserItem *pItem, pParent->items(UIGChooserItemType_Machine))
     1549        sorter.insert(pItem->name().toLower(), pItem);
     1550    pParent->setItems(sorter.values(), UIGChooserItemType_Machine);
     1551
     1552    /* Update model: */
     1553    updateNavigation();
     1554    updateLayout();
    17211555}
    17221556
     
    17531587}
    17541588
    1755 UIGChooserItem* UIGChooserModel::findGroupItem(const QString &strName, UIGChooserItem *pParent)
    1756 {
    1757     /* Search among all the group items of passed parent: */
    1758     foreach (UIGChooserItem *pGroupItem, pParent->items(UIGChooserItemType_Group))
    1759         if (pGroupItem->name() == strName)
    1760             return pGroupItem;
    1761     /* Recursively iterate into each the group item of the passed parent: */
    1762     foreach (UIGChooserItem *pGroupItem, pParent->items(UIGChooserItemType_Group))
    1763         if (UIGChooserItem *pSubGroupItem = findGroupItem(strName, pGroupItem))
    1764             return pSubGroupItem;
    1765     /* Nothing found? */
    1766     return 0;
    1767 }
    1768 
    1769 UIGChooserItem* UIGChooserModel::findMachineItem(const QString &strName, UIGChooserItem *pParent)
    1770 {
    1771     /* Search among all the machine items of passed parent: */
    1772     foreach (UIGChooserItem *pMachineItem, pParent->items(UIGChooserItemType_Machine))
    1773         if (pMachineItem->name() == strName)
    1774             return pMachineItem;
    1775     /* Recursively iterate into each the group item of the passed parent: */
    1776     foreach (UIGChooserItem *pGroupItem, pParent->items(UIGChooserItemType_Group))
    1777         if (UIGChooserItem *pSubMachineItem = findMachineItem(strName, pGroupItem))
    1778             return pSubMachineItem;
    1779     /* Nothing found? */
    1780     return 0;
     1589void UIGChooserModel::removeMachineItems(const QStringList &names, QList<UIGChooserItem*> &selectedItems)
     1590{
     1591    /* Show machine items remove dialog: */
     1592    int rc = msgCenter().confirmMachineItemRemoval(names);
     1593    if (rc == QIMessageBox::Cancel)
     1594        return;
     1595
     1596    /* Remove all the required items: */
     1597    foreach (UIGChooserItem *pItem, selectedItems)
     1598        if (names.contains(pItem->name()))
     1599            delete pItem;
     1600
     1601    /* And update model: */
     1602    updateGroupTree();
     1603    updateNavigation();
     1604    updateLayout();
     1605    if (mainRoot()->hasItems())
     1606        setCurrentItem(0);
     1607    else
     1608        unsetCurrentItem();
     1609    saveGroupSettings();
     1610}
     1611
     1612void UIGChooserModel::unregisterMachines(const QStringList &ids)
     1613{
     1614    /* Populate machine list: */
     1615    QList<CMachine> machines;
     1616    CVirtualBox vbox = vboxGlobal().virtualBox();
     1617    foreach (const QString &strId, ids)
     1618    {
     1619        CMachine machine = vbox.FindMachine(strId);
     1620        if (!machine.isNull())
     1621            machines << machine;
     1622    }
     1623
     1624    /* Show machine remove dialog: */
     1625    int rc = msgCenter().confirmMachineDeletion(machines);
     1626    if (rc != QIMessageBox::Cancel)
     1627    {
     1628        /* For every selected item: */
     1629        foreach (CMachine machine, machines)
     1630        {
     1631            if (rc == QIMessageBox::Yes)
     1632            {
     1633                /* Unregister and cleanup machine's data & hard-disks: */
     1634                CMediumVector mediums = machine.Unregister(KCleanupMode_DetachAllReturnHardDisksOnly);
     1635                if (machine.isOk())
     1636                {
     1637                    /* Delete machine hard-disks: */
     1638                    CProgress progress = machine.Delete(mediums);
     1639                    if (machine.isOk())
     1640                    {
     1641                        msgCenter().showModalProgressDialog(progress, machine.GetName(), ":/progress_delete_90px.png", 0, true);
     1642                        if (progress.GetResultCode() != 0)
     1643                            msgCenter().cannotDeleteMachine(machine, progress);
     1644                    }
     1645                }
     1646                if (!machine.isOk())
     1647                    msgCenter().cannotDeleteMachine(machine);
     1648            }
     1649            else
     1650            {
     1651                /* Just unregister machine: */
     1652                machine.Unregister(KCleanupMode_DetachAllReturnNone);
     1653                if (!machine.isOk())
     1654                    msgCenter().cannotDeleteMachine(machine);
     1655            }
     1656        }
     1657    }
    17811658}
    17821659
     
    19041781}
    19051782
    1906 void UIGChooserModel::slideRoot(bool fForward)
    1907 {
    1908     /* Animation group: */
    1909     QParallelAnimationGroup *pAnimation = new QParallelAnimationGroup(this);
    1910     connect(pAnimation, SIGNAL(finished()), this, SLOT(sltSlidingComplete()), Qt::QueuedConnection);
    1911 
    1912     /* Left root animation: */
    1913     {
    1914         QPropertyAnimation *pLeftAnimation = new QPropertyAnimation(m_pLeftRoot, "geometry", this);
    1915         connect(pLeftAnimation, SIGNAL(valueChanged(const QVariant&)), this, SLOT(sltLeftRootSlidingProgress()));
    1916         QRectF startGeo = m_pLeftRoot->geometry();
    1917         QRectF endGeo = fForward ? startGeo.translated(- startGeo.width(), 0) :
    1918                                    startGeo.translated(startGeo.width(), 0);
    1919         pLeftAnimation->setEasingCurve(QEasingCurve::InCubic);
    1920         pLeftAnimation->setDuration(500);
    1921         pLeftAnimation->setStartValue(startGeo);
    1922         pLeftAnimation->setEndValue(endGeo);
    1923         pAnimation->addAnimation(pLeftAnimation);
    1924     }
    1925 
    1926     /* Right root animation: */
    1927     {
    1928         QPropertyAnimation *pRightAnimation = new QPropertyAnimation(m_pRightRoot, "geometry", this);
    1929         connect(pRightAnimation, SIGNAL(valueChanged(const QVariant&)), this, SLOT(sltRightRootSlidingProgress()));
    1930         QRectF startGeo = m_pRightRoot->geometry();
    1931         QRectF endGeo = fForward ? startGeo.translated(- startGeo.width(), 0) :
    1932                                    startGeo.translated(startGeo.width(), 0);
    1933         pRightAnimation->setEasingCurve(QEasingCurve::InCubic);
    1934         pRightAnimation->setDuration(500);
    1935         pRightAnimation->setStartValue(startGeo);
    1936         pRightAnimation->setEndValue(endGeo);
    1937         pAnimation->addAnimation(pRightAnimation);
    1938     }
    1939 
    1940     /* Start animation: */
    1941     pAnimation->start();
    1942 }
    1943 
    1944 QList<UIGChooserItem*> UIGChooserModel::gatherMachineItems(const QList<UIGChooserItem*> &selectedItems) const
    1945 {
    1946     QList<UIGChooserItem*> machineItems;
    1947     foreach (UIGChooserItem *pItem, selectedItems)
    1948     {
    1949         if (pItem->type() == UIGChooserItemType_Machine)
    1950             machineItems << pItem;
    1951         if (pItem->type() == UIGChooserItemType_Group)
    1952             machineItems << gatherMachineItems(pItem->items());
    1953     }
    1954     return machineItems;
    1955 }
    1956 
    1957 void UIGChooserModel::removeMachineItems(const QStringList &names, QList<UIGChooserItem*> &selectedItems)
    1958 {
    1959     /* Show machine items remove dialog: */
    1960     int rc = msgCenter().confirmMachineItemRemoval(names);
    1961     if (rc == QIMessageBox::Cancel)
    1962         return;
    1963 
    1964     /* Remove all the required items: */
    1965     foreach (UIGChooserItem *pItem, selectedItems)
    1966         if (names.contains(pItem->name()))
    1967             delete pItem;
    1968 
    1969     /* And update model: */
    1970     updateGroupTree();
    1971     updateNavigation();
    1972     updateLayout();
    1973     if (mainRoot()->hasItems())
    1974         setCurrentItem(0);
    1975     else
    1976         unsetCurrentItem();
    1977     saveGroupSettings();
    1978 }
    1979 
    1980 void UIGChooserModel::unregisterMachines(const QStringList &ids)
    1981 {
    1982     /* Populate machine list: */
    1983     QList<CMachine> machines;
    1984     CVirtualBox vbox = vboxGlobal().virtualBox();
    1985     foreach (const QString &strId, ids)
    1986     {
    1987         CMachine machine = vbox.FindMachine(strId);
    1988         if (!machine.isNull())
    1989             machines << machine;
    1990     }
    1991 
    1992     /* Show machine remove dialog: */
    1993     int rc = msgCenter().confirmMachineDeletion(machines);
    1994     if (rc != QIMessageBox::Cancel)
    1995     {
    1996         /* For every selected item: */
    1997         foreach (CMachine machine, machines)
    1998         {
    1999             if (rc == QIMessageBox::Yes)
    2000             {
    2001                 /* Unregister and cleanup machine's data & hard-disks: */
    2002                 CMediumVector mediums = machine.Unregister(KCleanupMode_DetachAllReturnHardDisksOnly);
    2003                 if (machine.isOk())
    2004                 {
    2005                     /* Delete machine hard-disks: */
    2006                     CProgress progress = machine.Delete(mediums);
    2007                     if (machine.isOk())
    2008                     {
    2009                         msgCenter().showModalProgressDialog(progress, machine.GetName(), ":/progress_delete_90px.png", 0, true);
    2010                         if (progress.GetResultCode() != 0)
    2011                             msgCenter().cannotDeleteMachine(machine, progress);
    2012                     }
    2013                 }
    2014                 if (!machine.isOk())
    2015                     msgCenter().cannotDeleteMachine(machine);
    2016             }
    2017             else
    2018             {
    2019                 /* Just unregister machine: */
    2020                 machine.Unregister(KCleanupMode_DetachAllReturnNone);
    2021                 if (!machine.isOk())
    2022                     msgCenter().cannotDeleteMachine(machine);
    2023             }
    2024         }
    2025     }
    2026 }
    2027 
    2028 void UIGChooserModel::enumerateInaccessibleItems(const QList<UIGChooserItem*> &il, QList<UIGChooserItem*> &ol) const
    2029 {
    2030     /* Enumerate all the passed items: */
    2031     foreach (UIGChooserItem *pItem, il)
    2032     {
    2033         /* If item is inaccessible machine: */
    2034         if (pItem->type() == UIGChooserItemType_Machine)
    2035         {
    2036             if (UIGChooserItemMachine *pMachineItem = pItem->toMachineItem())
    2037                 if (!pMachineItem->accessible() && !contains(ol, pItem))
    2038                     ol << pMachineItem;
    2039         }
    2040         /* If item is group: */
    2041         else if (pItem->type() == UIGChooserItemType_Group)
    2042         {
    2043             /* Enumerate all the machine items recursively: */
    2044             enumerateInaccessibleItems(pItem->items(UIGChooserItemType_Machine), ol);
    2045             /* Enumerate all the group items recursively: */
    2046             enumerateInaccessibleItems(pItem->items(UIGChooserItemType_Group), ol);
    2047         }
    2048     }
    2049 }
    2050 
    2051 bool UIGChooserModel::contains(const QList<UIGChooserItem*> &il, UIGChooserItem *pLookupItem) const
    2052 {
    2053     /* We assume passed list contains only machine items: */
    2054     foreach (UIGChooserItem *pItem, il)
    2055         if (UIGChooserItemMachine *pMachineItem = pItem->toMachineItem())
    2056             if (pMachineItem->id() == pLookupItem->toMachineItem()->id())
    2057                 return true;
    2058     return false;
    2059 }
    2060 
    2061 void UIGChooserModel::sortItems(UIGChooserItem *pParent, bool fRecursively /* = false */)
    2062 {
    2063     /* Sort group items: */
    2064     QMap<QString, UIGChooserItem*> sorter;
    2065     foreach (UIGChooserItem *pItem, pParent->items(UIGChooserItemType_Group))
    2066     {
    2067         sorter.insert(pItem->name().toLower(), pItem);
    2068         if (fRecursively)
    2069             sortItems(pItem, fRecursively);
    2070     }
    2071     pParent->setItems(sorter.values(), UIGChooserItemType_Group);
    2072 
    2073     /* Sort machine items: */
    2074     sorter.clear();
    2075     foreach (UIGChooserItem *pItem, pParent->items(UIGChooserItemType_Machine))
    2076         sorter.insert(pItem->name().toLower(), pItem);
    2077     pParent->setItems(sorter.values(), UIGChooserItemType_Machine);
    2078 
    2079     /* Update model: */
    2080     updateNavigation();
    2081     updateLayout();
    2082 }
    2083 
    2084 void UIGChooserModel::makeSureGroupDefinitionsSaveIsFinished()
    2085 {
    2086     /* Cleanup if necessary: */
    2087     if (UIGroupDefinitionSaveThread::instance())
    2088         UIGroupDefinitionSaveThread::cleanup();
    2089 }
    2090 
    2091 void UIGChooserModel::makeSureGroupOrdersSaveIsFinished()
    2092 {
    2093     /* Cleanup if necessary: */
    2094     if (UIGroupOrderSaveThread::instance())
    2095         UIGroupOrderSaveThread::cleanup();
    2096 }
    2097 
    20981783UIGChooserItem* UIGChooserModel::lookForItem(UIGChooserItem *pParent, const QString &strStartingFrom)
    20991784{
     
    21121797    /* Nothing found: */
    21131798    return 0;
     1799}
     1800
     1801void UIGChooserModel::loadGroupTree()
     1802{
     1803    /* Add all the machines we have into the group-tree: */
     1804    LogRel(("Loading VMs started...\n"));
     1805    foreach (const CMachine &machine, vboxGlobal().virtualBox().GetMachines())
     1806        addMachineIntoTheTree(machine);
     1807    LogRel(("Loading VMs finished.\n"));
     1808}
     1809
     1810void UIGChooserModel::addMachineIntoTheTree(const CMachine &machine, bool fMakeItVisible /* = false */)
     1811{
     1812    /* Which VM we are loading: */
     1813    if (machine.isNull())
     1814        LogRel((" ERROR: VM is NULL!\n"));
     1815    else
     1816        LogRel((" Loading VM {%s}...\n", machine.GetId().toAscii().constData()));
     1817    /* Is that machine accessible? */
     1818    if (machine.GetAccessible())
     1819    {
     1820        /* VM is accessible: */
     1821        QString strName = machine.GetName();
     1822        LogRel((" VM {%s} is accessible.\n", strName.toAscii().constData()));
     1823        /* Which groups passed machine attached to? */
     1824        QVector<QString> groups = machine.GetGroups();
     1825        QStringList groupList = groups.toList();
     1826        QString strGroups = groupList.join(", ");
     1827        LogRel((" VM {%s} groups are {%s}.\n", strName.toAscii().constData(),
     1828                                               strGroups.toAscii().constData()));
     1829        foreach (QString strGroup, groups)
     1830        {
     1831            /* Remove last '/' if any: */
     1832            if (strGroup.right(1) == "/")
     1833                strGroup.truncate(strGroup.size() - 1);
     1834            /* Create machine item with found group item as parent: */
     1835            LogRel(("  Creating item for VM {%s}, group {%s}.\n", strName.toAscii().constData(),
     1836                                                                  strGroup.toAscii().constData()));
     1837            createMachineItem(machine, getGroupItem(strGroup, mainRoot(), fMakeItVisible));
     1838        }
     1839        /* Update group definitions: */
     1840        m_groups[machine.GetId()] = groupList;
     1841    }
     1842    /* Inaccessible machine: */
     1843    else
     1844    {
     1845        /* VM is accessible: */
     1846        LogRel((" VM {%s} is inaccessible.\n", machine.GetId().toAscii().constData()));
     1847        /* Create machine item with main-root group item as parent: */
     1848        createMachineItem(machine, mainRoot());
     1849    }
     1850}
     1851
     1852UIGChooserItem* UIGChooserModel::getGroupItem(const QString &strName, UIGChooserItem *pParentItem, bool fAllGroupsOpened)
     1853{
     1854    /* Check passed stuff: */
     1855    if (pParentItem->name() == strName)
     1856        return pParentItem;
     1857
     1858    /* Prepare variables: */
     1859    QString strFirstSubName = strName.section('/', 0, 0);
     1860    QString strFirstSuffix = strName.section('/', 1, -1);
     1861    QString strSecondSubName = strFirstSuffix.section('/', 0, 0);
     1862    QString strSecondSuffix = strFirstSuffix.section('/', 1, -1);
     1863
     1864    /* Passed group name equal to first sub-name: */
     1865    if (pParentItem->name() == strFirstSubName)
     1866    {
     1867        /* Make sure first-suffix is NOT empty: */
     1868        AssertMsg(!strFirstSuffix.isEmpty(), ("Invalid group name!"));
     1869        /* Trying to get group item among our children: */
     1870        foreach (UIGChooserItem *pGroupItem, pParentItem->items(UIGChooserItemType_Group))
     1871        {
     1872            if (pGroupItem->name() == strSecondSubName)
     1873            {
     1874                UIGChooserItem *pFoundItem = getGroupItem(strFirstSuffix, pGroupItem, fAllGroupsOpened);
     1875                if (UIGChooserItemGroup *pFoundGroupItem = pFoundItem->toGroupItem())
     1876                    if (fAllGroupsOpened && pFoundGroupItem->closed())
     1877                        pFoundGroupItem->open(false);
     1878                return pFoundItem;
     1879            }
     1880        }
     1881    }
     1882
     1883    /* Found nothing? Creating: */
     1884    UIGChooserItemGroup *pNewGroupItem =
     1885            new UIGChooserItemGroup(/* Parent item and desired group name: */
     1886                                    pParentItem, strSecondSubName,
     1887                                    /* Should be new group opened when created? */
     1888                                    fAllGroupsOpened || shouldBeGroupOpened(pParentItem, strSecondSubName),
     1889                                    /* Which position new group item should be placed in? */
     1890                                    getDesiredPosition(pParentItem, UIGChooserItemType_Group, strSecondSubName));
     1891    return strSecondSuffix.isEmpty() ? pNewGroupItem : getGroupItem(strFirstSuffix, pNewGroupItem, fAllGroupsOpened);
     1892}
     1893
     1894bool UIGChooserModel::shouldBeGroupOpened(UIGChooserItem *pParentItem, const QString &strName)
     1895{
     1896    /* Prepare extra-data key for the parent-item: */
     1897    QString strExtraDataKey = UIDefs::GUI_GroupDefinitions + fullName(pParentItem);
     1898    /* Read group definitions: */
     1899    QStringList definitions = vboxGlobal().virtualBox().GetExtraDataStringList(strExtraDataKey);
     1900    /* Return 'false' if no definitions found: */
     1901    if (definitions.isEmpty())
     1902        return false;
     1903
     1904    /* Prepare required group definition reg-exp: */
     1905    QString strDefinitionTemplate = QString("g(\\S)*=%1").arg(strName);
     1906    QRegExp definitionRegExp(strDefinitionTemplate);
     1907    /* For each the group definition: */
     1908    for (int i = 0; i < definitions.size(); ++i)
     1909    {
     1910        /* Get current definition: */
     1911        const QString &strDefinition = definitions[i];
     1912        /* Check if this is required definition: */
     1913        if (definitionRegExp.indexIn(strDefinition) == 0)
     1914        {
     1915            /* Get group descriptor: */
     1916            QString strDescriptor(definitionRegExp.cap(1));
     1917            if (strDescriptor.contains('o'))
     1918                return true;
     1919        }
     1920    }
     1921
     1922    /* Return 'false' by default: */
     1923    return false;
     1924}
     1925
     1926int UIGChooserModel::getDesiredPosition(UIGChooserItem *pParentItem, UIGChooserItemType type, const QString &strName)
     1927{
     1928    /* End of list (by default)? */
     1929    int iNewItemDesiredPosition = -1;
     1930    /* Which position should be new item placed by definitions: */
     1931    int iNewItemDefinitionPosition = positionFromDefinitions(pParentItem, type, strName);
     1932    /* If some position wanted: */
     1933    if (iNewItemDefinitionPosition != -1)
     1934    {
     1935        /* Start of list if some definition present: */
     1936        iNewItemDesiredPosition = 0;
     1937        /* We have to check all the existing item positions: */
     1938        QList<UIGChooserItem*> items = pParentItem->items(type);
     1939        for (int i = items.size() - 1; i >= 0; --i)
     1940        {
     1941            /* Get current item: */
     1942            UIGChooserItem *pItem = items[i];
     1943            /* Which position should be current item placed by definitions? */
     1944            QString strDefinitionName = pItem->type() == UIGChooserItemType_Group ? pItem->name() :
     1945                                        pItem->type() == UIGChooserItemType_Machine ? pItem->toMachineItem()->id() :
     1946                                        QString();
     1947            AssertMsg(!strDefinitionName.isEmpty(), ("Wrong definition name!"));
     1948            int iItemDefinitionPosition = positionFromDefinitions(pParentItem, type, strDefinitionName);
     1949            /* If some position wanted: */
     1950            if (iItemDefinitionPosition != -1)
     1951            {
     1952                AssertMsg(iItemDefinitionPosition != iNewItemDefinitionPosition, ("Incorrect definitions!"));
     1953                if (iItemDefinitionPosition < iNewItemDefinitionPosition)
     1954                {
     1955                    iNewItemDesiredPosition = i + 1;
     1956                    break;
     1957                }
     1958            }
     1959        }
     1960    }
     1961    /* Return desired item position: */
     1962    return iNewItemDesiredPosition;
     1963}
     1964
     1965int UIGChooserModel::positionFromDefinitions(UIGChooserItem *pParentItem, UIGChooserItemType type, const QString &strName)
     1966{
     1967    /* Prepare extra-data key for the parent-item: */
     1968    QString strExtraDataKey = UIDefs::GUI_GroupDefinitions + fullName(pParentItem);
     1969    /* Read group definitions: */
     1970    QStringList definitions = vboxGlobal().virtualBox().GetExtraDataStringList(strExtraDataKey);
     1971    /* Return 'false' if no definitions found: */
     1972    if (definitions.isEmpty())
     1973        return -1;
     1974
     1975    /* Prepare definition reg-exp: */
     1976    QString strDefinitionTemplateShort;
     1977    QString strDefinitionTemplateFull;
     1978    switch (type)
     1979    {
     1980        case UIGChooserItemType_Group:
     1981            strDefinitionTemplateShort = QString("^g(\\S)*=");
     1982            strDefinitionTemplateFull = QString("^g(\\S)*=%1$").arg(strName);
     1983            break;
     1984        case UIGChooserItemType_Machine:
     1985            strDefinitionTemplateShort = QString("^m=");
     1986            strDefinitionTemplateFull = QString("^m=%1$").arg(strName);
     1987            break;
     1988        default: return -1;
     1989    }
     1990    QRegExp definitionRegExpShort(strDefinitionTemplateShort);
     1991    QRegExp definitionRegExpFull(strDefinitionTemplateFull);
     1992
     1993    /* For each the definition: */
     1994    int iDefinitionIndex = -1;
     1995    for (int i = 0; i < definitions.size(); ++i)
     1996    {
     1997        /* Get current definition: */
     1998        QString strDefinition = definitions[i];
     1999        /* Check if this definition is of required type: */
     2000        if (definitionRegExpShort.indexIn(strDefinition) == 0)
     2001        {
     2002            ++iDefinitionIndex;
     2003            /* Check if this definition is exactly what we need: */
     2004            if (definitionRegExpFull.indexIn(strDefinition) == 0)
     2005                return iDefinitionIndex;
     2006        }
     2007    }
     2008
     2009    /* Return result: */
     2010    return -1;
     2011}
     2012
     2013void UIGChooserModel::createMachineItem(const CMachine &machine, UIGChooserItem *pParentItem)
     2014{
     2015    /* Create corresponding item: */
     2016    new UIGChooserItemMachine(/* Parent item and corresponding machine: */
     2017                              pParentItem, machine,
     2018                              /* Which position new group item should be placed in? */
     2019                              getDesiredPosition(pParentItem, UIGChooserItemType_Machine, machine.GetId()));
     2020}
     2021
     2022void UIGChooserModel::saveGroupDefinitions()
     2023{
     2024    /* Make sure there is no group save activity: */
     2025    if (UIGroupDefinitionSaveThread::instance())
     2026        return;
     2027
     2028    /* Prepare full group map: */
     2029    QMap<QString, QStringList> groups;
     2030    gatherGroupDefinitions(groups, mainRoot());
     2031
     2032    /* Save information in other thread: */
     2033    UIGroupDefinitionSaveThread::prepare();
     2034    emit sigGroupSavingStateChanged();
     2035    connect(UIGroupDefinitionSaveThread::instance(), SIGNAL(sigReload(QString)),
     2036            this, SLOT(sltReloadMachine(QString)));
     2037    UIGroupDefinitionSaveThread::instance()->configure(this, m_groups, groups);
     2038    UIGroupDefinitionSaveThread::instance()->start();
     2039    m_groups = groups;
     2040}
     2041
     2042void UIGChooserModel::saveGroupOrders()
     2043{
     2044    /* Make sure there is no group save activity: */
     2045    if (UIGroupOrderSaveThread::instance())
     2046        return;
     2047
     2048    /* Prepare full group map: */
     2049    QMap<QString, QStringList> groups;
     2050    gatherGroupOrders(groups, mainRoot());
     2051
     2052    /* Save information in other thread: */
     2053    UIGroupOrderSaveThread::prepare();
     2054    emit sigGroupSavingStateChanged();
     2055    UIGroupOrderSaveThread::instance()->configure(this, groups);
     2056    UIGroupOrderSaveThread::instance()->start();
     2057}
     2058
     2059void UIGChooserModel::gatherGroupDefinitions(QMap<QString, QStringList> &groups,
     2060                                             UIGChooserItem *pParentGroup)
     2061{
     2062    /* Iterate over all the machine items: */
     2063    foreach (UIGChooserItem *pItem, pParentGroup->items(UIGChooserItemType_Machine))
     2064        if (UIGChooserItemMachine *pMachineItem = pItem->toMachineItem())
     2065            if (pMachineItem->accessible())
     2066                groups[pMachineItem->id()] << fullName(pParentGroup);
     2067    /* Iterate over all the group items: */
     2068    foreach (UIGChooserItem *pItem, pParentGroup->items(UIGChooserItemType_Group))
     2069        gatherGroupDefinitions(groups, pItem);
     2070}
     2071
     2072void UIGChooserModel::gatherGroupOrders(QMap<QString, QStringList> &groups,
     2073                                        UIGChooserItem *pParentItem)
     2074{
     2075    /* Prepare extra-data key for current group: */
     2076    QString strExtraDataKey = UIDefs::GUI_GroupDefinitions + fullName(pParentItem);
     2077    /* Iterate over all the group items: */
     2078    foreach (UIGChooserItem *pItem, pParentItem->items(UIGChooserItemType_Group))
     2079    {
     2080        QString strGroupDescriptor(pItem->toGroupItem()->opened() ? "go" : "gc");
     2081        groups[strExtraDataKey] << QString("%1=%2").arg(strGroupDescriptor, pItem->name());
     2082        gatherGroupOrders(groups, pItem);
     2083    }
     2084    /* Iterate over all the machine items: */
     2085    foreach (UIGChooserItem *pItem, pParentItem->items(UIGChooserItemType_Machine))
     2086        groups[strExtraDataKey] << QString("m=%1").arg(pItem->toMachineItem()->id());
     2087}
     2088
     2089QString UIGChooserModel::fullName(UIGChooserItem *pItem)
     2090{
     2091    /* Return '/' for root-group: */
     2092    if (!pItem->parentItem())
     2093        return QString("/");
     2094    /* Get full parent name, append with '/' if not yet appended: */
     2095    QString strParentFullName = fullName(pItem->parentItem());
     2096    if (!strParentFullName.endsWith("/"))
     2097        strParentFullName += QString("/");
     2098    /* Return full item name based on parent prefix: */
     2099    return strParentFullName + pItem->name();
     2100}
     2101
     2102
     2103void UIGChooserModel::makeSureGroupDefinitionsSaveIsFinished()
     2104{
     2105    /* Cleanup if necessary: */
     2106    if (UIGroupDefinitionSaveThread::instance())
     2107        UIGroupDefinitionSaveThread::cleanup();
     2108}
     2109
     2110void UIGChooserModel::makeSureGroupOrdersSaveIsFinished()
     2111{
     2112    /* Cleanup if necessary: */
     2113    if (UIGroupOrderSaveThread::instance())
     2114        UIGroupOrderSaveThread::cleanup();
    21142115}
    21152116
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/chooser/UIGChooserModel.h

    r43514 r43528  
    4242class QAction;
    4343class QGraphicsSceneContextMenuEvent;
    44 class CMachine;
     44class QTimer;
     45class QPaintDevice;
    4546class UIVMItem;
    4647class UIGChooserHandlerMouse;
    4748class UIGChooserHandlerKeyboard;
    48 class QTimer;
    49 class QPaintDevice;
     49class CMachine;
    5050
    5151/* Context-menu type: */
     
    6363signals:
    6464
    65     /* Notifier: Root-item resize stuff: */
     65    /* Notifiers: Status-bar stuff: */
     66    void sigShowStatusMessage(const QString &strStatusMessage);
     67    void sigClearStatusMessage();
     68
     69    /* Notifier: Current-item stuff: */
     70    void sigSelectionChanged();
     71
     72    /* Notifier: Focus-item stuff: */
     73    void sigFocusChanged(UIGChooserItem *pFocusItem);
     74
     75    /* Notifiers: Root-item stuff: */
    6676    void sigRootItemResized(const QSizeF &size, int iMinimumWidth);
    67 
    68     /* Notifier: Focus change: */
    69     void sigFocusChanged(UIGChooserItem *pFocusItem);
    70 
    71     /* Notifier: Selection change: */
    72     void sigSelectionChanged();
    73 
    74     /* Notifiers Status-bar stuff: */
    75     void sigClearStatusMessage();
    76     void sigShowStatusMessage(const QString &strStatusMessage);
    77 
    78     /* Notifier: Sliding start: */
    7977    void sigSlidingStarted();
    8078
    81     /* Notifiers: Toggle stuff: */
     79    /* Notifiers: Group-item stuff: */
    8280    void sigToggleStarted();
    8381    void sigToggleFinished();
    8482
    85     /* Notifiers: Group saving stuff: */
     83    /* Notifiers: Group-saving stuff: */
    8684    void sigStartGroupSaving();
    8785    void sigGroupSavingStateChanged();
     
    9795    void cleanup();
    9896
    99     /* API: Scene getter: */
     97    /* API: Scene stuff: */
    10098    QGraphicsScene* scene() const;
    101 
    102     /* API: Paint-device getter: */
    10399    QPaintDevice* paintDevice() const;
    104 
    105     /* API: Root stuff: */
     100    QGraphicsItem* itemAt(const QPointF &position, const QTransform &deviceTransform = QTransform()) const;
     101
     102    /* API: Layout stuff: */
     103    void updateLayout();
     104
     105    /* API: Navigation stuff: */
     106    const QList<UIGChooserItem*>& navigationList() const;
     107    void removeFromNavigationList(UIGChooserItem *pItem);
     108    void clearNavigationList();
     109    void updateNavigation();
     110
     111    /* API: Current-item stuff: */
     112    UIVMItem* currentItem() const;
     113    QString currentItemDefinition() const;
     114    QList<UIVMItem*> currentItems() const;
     115    const QList<UIGChooserItem*>& selectionList() const;
     116    void setCurrentItem(int iItemIndex);
     117    void setCurrentItem(UIGChooserItem *pItem);
     118    void setCurrentItemDefinition(const QString &strDefinition);
     119    void unsetCurrentItem();
     120    void addToSelectionList(UIGChooserItem *pItem);
     121    void removeFromSelectionList(UIGChooserItem *pItem);
     122    void clearSelectionList();
     123    void notifySelectionChanged();
     124    void activate();
     125    bool isSingleGroupSelected() const;
     126    bool isAllItemsOfOneGroupSelected() const;
     127
     128    /* API: Focus-item stuff: */
     129    UIGChooserItem* focusItem() const;
     130    void setFocusItem(UIGChooserItem *pItem, bool fWithSelection = false);
     131
     132    /* API: Root-item stuff: */
    106133    UIGChooserItem* mainRoot() const;
    107134    UIGChooserItem* root() const;
     
    110137    bool isSlidingInProgress() const;
    111138
    112     /* API: Current item stuff: */
    113     void setCurrentItem(int iItemIndex);
    114     void setCurrentItem(UIGChooserItem *pItem);
    115     void unsetCurrentItem();
    116     UIVMItem* currentItem() const;
    117     QList<UIVMItem*> currentItems() const;
    118     void setCurrentItemDefinition(const QString &strDefinition);
    119     QString currentItemDefinition() const;
    120     bool isSingleGroupSelected() const;
    121     bool isAllItemsOfOneGroupSelected() const;
    122 
    123     /* API: Focus item stuff: */
    124     void setFocusItem(UIGChooserItem *pItem, bool fWithSelection = false);
    125     UIGChooserItem* focusItem() const;
    126 
    127     /* API: Positioning item stuff: */
    128     QGraphicsItem* itemAt(const QPointF &position, const QTransform &deviceTransform = QTransform()) const;
    129 
    130     /* API: Update stuff: */
     139    /* API: Group-item stuff: */
     140    QString uniqueGroupName(UIGChooserItem *pRoot);
     141    void startEditing();
    131142    void updateGroupTree();
    132143
    133     /* API: Navigation stuff: */
    134     const QList<UIGChooserItem*>& navigationList() const;
    135     void removeFromNavigationList(UIGChooserItem *pItem);
    136     void clearNavigationList();
    137     void updateNavigation();
    138 
    139     /* API: Selection stuff: */
    140     const QList<UIGChooserItem*>& selectionList() const;
    141     void addToSelectionList(UIGChooserItem *pItem);
    142     void removeFromSelectionList(UIGChooserItem *pItem);
    143     void clearSelectionList();
    144     void notifySelectionChanged();
    145 
    146     /* API: Layout stuff: */
    147     void updateLayout();
    148 
    149     /* API: Editing stuff: */
    150     void startEditing();
    151 
    152     /* API: Drag and drop stuff: */
     144    /* API: Drag&drop stuff: */
    153145    void setCurrentDragObject(QDrag *pDragObject);
    154146
    155     /* API: Activate stuff: */
    156     void activate();
    157 
    158     /* API: Group name stuff: */
    159     QString uniqueGroupName(UIGChooserItem *pRoot);
    160 
    161     /* API: Group saving stuff: */
     147    /* API: Item lookup stuff: */
     148    void lookFor(const QString &strLookupSymbol);
     149    bool isPerformingLookup() const;
     150
     151    /* API: Saving stuff: */
    162152    void saveGroupSettings();
    163153    bool isGroupSavingInProgress() const;
    164 
    165     /* API: Lookup stuff: */
    166     void lookFor(const QString &strLookupSymbol);
    167     bool isPerformingLookup() const;
    168154
    169155private slots:
     
    176162    void sltSnapshotChanged(QString strId, QString strSnapshotId);
    177163
    178     /* Handler: View-resize: */
     164    /* Handler: Chooser-view stuff: */
    179165    void sltHandleViewResized();
    180166
    181     /* Handler: Drag object destruction: */
    182     void sltCurrentDragObjectDestroyed();
    183     void sltStartScrolling();
    184 
    185     /* Handlers: Remove currently selected items: */
    186     void sltRemoveCurrentlySelectedGroup();
    187     void sltRemoveCurrentlySelectedMachine();
    188 
    189     /* Handler: Group add stuff: */
    190     void sltAddGroupBasedOnChosenItems();
    191 
    192     /* Handler: Group name editing stuff: */
    193     void sltStartEditingSelectedGroup();
    194 
    195     /* Handler: Create new machine stuff: */
    196     void sltCreateNewMachine();
    197 
    198     /* Handler: Context menu hovering: */
    199     void sltActionHovered(QAction *pAction);
    200 
    201     /* Handler: Focus item destruction: */
     167    /* Handler: Focus-item stuff: */
    202168    void sltFocusItemDestroyed();
    203169
    204     /* Handlers: Root-sliding stuff: */
     170    /* Handlers: Root-item stuff: */
    205171    void sltLeftRootSlidingProgress();
    206172    void sltRightRootSlidingProgress();
    207173    void sltSlidingComplete();
    208174
    209     /* Handler: Refresh stuff: */
     175    /* Handlers: Group-item stuff: */
     176    void sltAddGroupBasedOnChosenItems();
     177    void sltStartEditingSelectedGroup();
     178    void sltSortGroup();
     179    void sltRemoveCurrentlySelectedGroup();
     180
     181    /* Handlers: Machine-item stuff: */
     182    void sltCreateNewMachine();
     183    void sltReloadMachine(const QString &strId);
     184    void sltSortParentGroup();
    210185    void sltPerformRefreshAction();
    211 
    212     /* Handlers: Sorting stuff: */
    213     void sltSortParentGroup();
    214     void sltSortGroup();
    215 
    216     /* Handlers: Group saving stuff: */
     186    void sltRemoveCurrentlySelectedMachine();
     187
     188    /* Handlers: Drag&drop stuff: */
     189    void sltStartScrolling();
     190    void sltCurrentDragObjectDestroyed();
     191
     192    /* Handler: Context-menu stuff: */
     193    void sltActionHovered(QAction *pAction);
     194
     195    /* Handler: Item lookup stuff: */
     196    void sltEraseLookupTimer();
     197
     198    /* Handlers: Saving stuff: */
    217199    void sltGroupSavingStart();
    218200    void sltGroupDefinitionsSaveComplete();
    219201    void sltGroupOrdersSaveComplete();
    220     void sltReloadMachine(const QString &strId);
    221 
    222     /* Handler: Lookup stuff: */
    223     void sltEraseLookupTimer();
    224202
    225203private:
     
    253231    void cleanupScene();
    254232
    255     /* Event handler: */
     233    /* Handler: Event-filter: */
    256234    bool eventFilter(QObject *pWatched, QEvent *pEvent);
    257235
    258     /* Helpers: Focus item stuff: */
    259     void clearRealFocus();
    260 
    261     /* Helpers: Current item stuff: */
     236    /* Helper: Navigation stuff: */
     237    QList<UIGChooserItem*> createNavigationList(UIGChooserItem *pItem);
     238
     239    /* Helpers: Current-item stuff: */
    262240    UIVMItem* searchCurrentItem(const QList<UIGChooserItem*> &list) const;
    263241    void enumerateCurrentItems(const QList<UIGChooserItem*> &il, QList<UIVMItem*> &ol) const;
    264242    bool contains(const QList<UIVMItem*> &list, UIVMItem *pItem) const;
    265243
    266     /* Helpers: Loading: */
     244    /* Helper: Focus-item stuff: */
     245    void clearRealFocus();
     246
     247    /* Helper: Root-item stuff: */
     248    void slideRoot(bool fForward);
     249
     250    /* Helper: Group-item stuff: */
     251    UIGChooserItem* findGroupItem(const QString &strName, UIGChooserItem *pParent);
     252    void updateGroupTree(UIGChooserItem *pGroupItem);
     253
     254    /* Helpers: Machine-item stuff: */
     255    UIGChooserItem* findMachineItem(const QString &strName, UIGChooserItem *pParent);
     256    QList<UIGChooserItem*> gatherMachineItems(const QList<UIGChooserItem*> &selectedItems) const;
     257    void enumerateInaccessibleItems(const QList<UIGChooserItem*> &il, QList<UIGChooserItem*> &ol) const;
     258    bool contains(const QList<UIGChooserItem*> &il, UIGChooserItem *pLookupItem) const;
     259    void sortItems(UIGChooserItem *pParent, bool fRecursively = false);
     260    void updateMachineItems(const QString &strId, UIGChooserItem *pParent);
     261    void removeMachineItems(const QString &strId, UIGChooserItem *pParent);
     262    void removeMachineItems(const QStringList &names, QList<UIGChooserItem*> &selectedItems);
     263    void unregisterMachines(const QStringList &ids);
     264
     265    /* Helpers: Context-menu stuff: */
     266    bool processContextMenuEvent(QGraphicsSceneContextMenuEvent *pEvent);
     267    void popupContextMenu(UIGraphicsSelectorContextMenuType type, QPoint point);
     268
     269    /* Handler: Drag&drop event: */
     270    bool processDragMoveEvent(QGraphicsSceneDragDropEvent *pEvent);
     271
     272    /* Helper: Lookup stuff: */
     273    UIGChooserItem* lookForItem(UIGChooserItem *pParent, const QString &strStartingFrom);
     274
     275    /* Helpers: Loading stuff: */
    267276    void loadGroupTree();
    268277    void addMachineIntoTheTree(const CMachine &machine, bool fMakeItVisible = false);
     
    273282    void createMachineItem(const CMachine &machine, UIGChooserItem *pParentItem);
    274283
    275     /* Helpers: Group saving stuff: */
     284    /* Helpers: Saving stuff: */
    276285    void saveGroupDefinitions();
    277286    void saveGroupOrders();
     
    279288    void gatherGroupOrders(QMap<QString, QStringList> &groups, UIGChooserItem *pParentItem);
    280289    QString fullName(UIGChooserItem *pItem);
    281 
    282     /* Helpers: Update stuff: */
    283     void updateGroupTree(UIGChooserItem *pGroupItem);
    284 
    285     /* Helpers: Navigation stuff: */
    286     QList<UIGChooserItem*> createNavigationList(UIGChooserItem *pItem);
    287 
    288     /* Helpers: Search stuff: */
    289     UIGChooserItem* findGroupItem(const QString &strName, UIGChooserItem *pParent);
    290     UIGChooserItem* findMachineItem(const QString &strName, UIGChooserItem *pParent);
    291 
    292     /* Helpers: Global event stuff: */
    293     void updateMachineItems(const QString &strId, UIGChooserItem *pParent);
    294     void removeMachineItems(const QString &strId, UIGChooserItem *pParent);
    295 
    296     /* Helpers: Context menu stuff: */
    297     bool processContextMenuEvent(QGraphicsSceneContextMenuEvent *pEvent);
    298     void popupContextMenu(UIGraphicsSelectorContextMenuType type, QPoint point);
    299 
    300     /* Handlers: Scroll event: */
    301     bool processDragMoveEvent(QGraphicsSceneDragDropEvent *pEvent);
    302 
    303     /* Helper: Root item stuff: */
    304     void slideRoot(bool fForward);
    305 
    306     /* Helper: Search stuff: */
    307     QList<UIGChooserItem*> gatherMachineItems(const QList<UIGChooserItem*> &selectedItems) const;
    308 
    309     /* Helpers: Remove stuff: */
    310     void removeMachineItems(const QStringList &names, QList<UIGChooserItem*> &selectedItems);
    311     void unregisterMachines(const QStringList &ids);
    312 
    313     /* Helper: Refresh stuff: */
    314     void enumerateInaccessibleItems(const QList<UIGChooserItem*> &il, QList<UIGChooserItem*> &ol) const;
    315     bool contains(const QList<UIGChooserItem*> &il, UIGChooserItem *pLookupItem) const;
    316 
    317     /* Helper: Sorting stuff: */
    318     void sortItems(UIGChooserItem *pParent, bool fRecursively = false);
    319 
    320     /* Helpers: Group saving stuff: */
    321290    void makeSureGroupDefinitionsSaveIsFinished();
    322291    void makeSureGroupOrdersSaveIsFinished();
    323 
    324     /* Helper: Lookup stuff: */
    325     UIGChooserItem* lookForItem(UIGChooserItem *pParent, const QString &strStartingFrom);
    326292
    327293    /* Variables: */
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette