VirtualBox

Changeset 77890 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Mar 26, 2019 5:16:28 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
129595
Message:

FE/Qt: bugref:9241: VirtualBox Manager: Chooser pane: Split off abstract model functionality to separate UIChooserAbstractModel class, will be moved to separate files.

Location:
trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser/UIChooserItemMachine.cpp

    r77847 r77890  
    419419                                                                           false /* favorite */,
    420420                                                                           parentItem()->node()->nodes().size(),
    421                                                                            UIChooserModel::uniqueGroupName(parentItem()),
     421                                                                           UIChooserModel::uniqueGroupName(parentItem()->node()),
    422422                                                                           true /* true */);
    423423                UIChooserItemGroup *pNewGroupItem = new UIChooserItemGroup(parentItem(), pNewGroupNode);
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser/UIChooserModel.cpp

    r77847 r77890  
    5656
    5757/*********************************************************************************************************************************
     58*   Class UIChooserAbstractModel implementation.                                                                                 *
     59*********************************************************************************************************************************/
     60
     61UIChooserAbstractModel:: UIChooserAbstractModel(UIChooser *pParent)
     62    : QObject(pParent)
     63    , m_pInvisibleRootNode(0)
     64{
     65    prepare();
     66}
     67
     68void UIChooserAbstractModel::init()
     69{
     70    /* Load tree: */
     71    loadTree();
     72}
     73
     74void UIChooserAbstractModel::deinit()
     75{
     76    /* Currently we are not saving group descriptors
     77     * (which reflecting group toggle-state) on-the-fly,
     78     * so, for now we are additionally save group orders
     79     * when exiting application: */
     80    saveGroupOrders();
     81
     82    /* Make sure all saving steps complete: */
     83    makeSureGroupDefinitionsSaveIsFinished();
     84    makeSureGroupOrdersSaveIsFinished();
     85
     86    /* Delete tree: */
     87    delete m_pInvisibleRootNode;
     88    m_pInvisibleRootNode = 0;
     89}
     90
     91UIChooserNode *UIChooserAbstractModel::invisibleRoot() const
     92{
     93    return m_pInvisibleRootNode;
     94}
     95
     96void UIChooserAbstractModel::wipeOutEmptyGroups()
     97{
     98    wipeOutEmptyGroups(invisibleRoot());
     99}
     100
     101/* static */
     102QString UIChooserAbstractModel::uniqueGroupName(UIChooserNode *pRoot)
     103{
     104    /* Enumerate all the group names: */
     105    QStringList groupNames;
     106    foreach (UIChooserNode *pNode, pRoot->nodes(UIChooserItemType_Group))
     107        groupNames << pNode->name();
     108
     109    /* Prepare reg-exp: */
     110    const QString strMinimumName = tr("New group");
     111    const QString strShortTemplate = strMinimumName;
     112    const QString strFullTemplate = strShortTemplate + QString(" (\\d+)");
     113    const QRegExp shortRegExp(strShortTemplate);
     114    const QRegExp fullRegExp(strFullTemplate);
     115
     116    /* Search for the maximum index: */
     117    int iMinimumPossibleNumber = 0;
     118    foreach (const QString &strName, groupNames)
     119    {
     120        if (shortRegExp.exactMatch(strName))
     121            iMinimumPossibleNumber = qMax(iMinimumPossibleNumber, 2);
     122        else if (fullRegExp.exactMatch(strName))
     123            iMinimumPossibleNumber = qMax(iMinimumPossibleNumber, fullRegExp.cap(1).toInt() + 1);
     124    }
     125
     126    /* Prepare result: */
     127    QString strResult = strMinimumName;
     128    if (iMinimumPossibleNumber)
     129        strResult += " " + QString::number(iMinimumPossibleNumber);
     130    return strResult;
     131}
     132
     133void UIChooserAbstractModel::saveGroupSettings()
     134{
     135    emit sigGroupSavingStarted();
     136}
     137
     138bool UIChooserAbstractModel::isGroupSavingInProgress() const
     139{
     140    return    UIThreadGroupDefinitionSave::instance()
     141           || UIThreadGroupOrderSave::instance();
     142}
     143
     144void UIChooserAbstractModel::sltMachineStateChanged(const QUuid &uId, const KMachineState)
     145{
     146    /* Update machine-nodes with passed id: */
     147    invisibleRoot()->updateAllNodes(uId);
     148}
     149
     150void UIChooserAbstractModel::sltMachineDataChanged(const QUuid &uId)
     151{
     152    /* Update machine-nodes with passed id: */
     153    invisibleRoot()->updateAllNodes(uId);
     154}
     155
     156void UIChooserAbstractModel::sltMachineRegistered(const QUuid &uId, const bool fRegistered)
     157{
     158    /* Existing VM unregistered? */
     159    if (!fRegistered)
     160    {
     161        /* Remove machine-items with passed id: */
     162        invisibleRoot()->removeAllNodes(uId);
     163        /* Wipe out empty groups: */
     164        wipeOutEmptyGroups();
     165    }
     166    /* New VM registered? */
     167    else
     168    {
     169        /* Should we show this VM? */
     170        if (gEDataManager->showMachineInVirtualBoxManagerChooser(uId))
     171        {
     172            /* Add new machine-item: */
     173            CMachine comMachine = vboxGlobal().virtualBox().FindMachine(uId.toString());
     174            addMachineIntoTheTree(comMachine, true /* make it visible */);
     175        }
     176    }
     177}
     178
     179void UIChooserAbstractModel::sltSessionStateChanged(const QUuid &uId, const KSessionState)
     180{
     181    /* Update machine-nodes with passed id: */
     182    invisibleRoot()->updateAllNodes(uId);
     183}
     184
     185void UIChooserAbstractModel::sltSnapshotChanged(const QUuid &uId, const QUuid &)
     186{
     187    /* Update machine-nodes with passed id: */
     188    invisibleRoot()->updateAllNodes(uId);
     189}
     190
     191void UIChooserAbstractModel::sltReloadMachine(const QUuid &uId)
     192{
     193    /* Remove machine-items with passed id: */
     194    invisibleRoot()->removeAllNodes(uId);
     195    /* Wipe out empty groups: */
     196    wipeOutEmptyGroups();
     197
     198    /* Should we show this VM? */
     199    if (gEDataManager->showMachineInVirtualBoxManagerChooser(uId))
     200    {
     201        /* Add new machine-item: */
     202        CMachine comMachine = vboxGlobal().virtualBox().FindMachine(uId.toString());
     203        addMachineIntoTheTree(comMachine, true /* make it visible */);
     204    }
     205}
     206
     207void UIChooserAbstractModel::sltGroupSavingStart()
     208{
     209    saveGroupDefinitions();
     210    saveGroupOrders();
     211}
     212
     213void UIChooserAbstractModel::sltGroupDefinitionsSaveComplete()
     214{
     215    makeSureGroupDefinitionsSaveIsFinished();
     216    emit sigGroupSavingStateChanged();
     217}
     218
     219void UIChooserAbstractModel::sltGroupOrdersSaveComplete()
     220{
     221    makeSureGroupOrdersSaveIsFinished();
     222    emit sigGroupSavingStateChanged();
     223}
     224
     225void UIChooserAbstractModel::prepare()
     226{
     227    prepareConnections();
     228}
     229
     230void UIChooserAbstractModel::prepareConnections()
     231{
     232    /* Setup parent connections: */
     233    connect(this, SIGNAL(sigGroupSavingStateChanged()),
     234            parent(), SIGNAL(sigGroupSavingStateChanged()));
     235
     236    /* Setup global connections: */
     237    connect(gVBoxEvents, SIGNAL(sigMachineStateChange(QUuid, KMachineState)),
     238            this, SLOT(sltMachineStateChanged(QUuid, KMachineState)));
     239    connect(gVBoxEvents, SIGNAL(sigMachineDataChange(QUuid)),
     240            this, SLOT(sltMachineDataChanged(QUuid)));
     241    connect(gVBoxEvents, SIGNAL(sigMachineRegistered(QUuid, bool)),
     242            this, SLOT(sltMachineRegistered(QUuid, bool)));
     243    connect(gVBoxEvents, SIGNAL(sigSessionStateChange(QUuid, KSessionState)),
     244            this, SLOT(sltSessionStateChanged(QUuid, KSessionState)));
     245    connect(gVBoxEvents, SIGNAL(sigSnapshotTake(QUuid, QUuid)),
     246            this, SLOT(sltSnapshotChanged(QUuid, QUuid)));
     247    connect(gVBoxEvents, SIGNAL(sigSnapshotDelete(QUuid, QUuid)),
     248            this, SLOT(sltSnapshotChanged(QUuid, QUuid)));
     249    connect(gVBoxEvents, SIGNAL(sigSnapshotChange(QUuid, QUuid)),
     250            this, SLOT(sltSnapshotChanged(QUuid, QUuid)));
     251    connect(gVBoxEvents, SIGNAL(sigSnapshotRestore(QUuid, QUuid)),
     252            this, SLOT(sltSnapshotChanged(QUuid, QUuid)));
     253
     254    /* Setup group saving connections: */
     255    connect(this, &UIChooserAbstractModel::sigGroupSavingStarted,
     256            this, &UIChooserAbstractModel::sltGroupSavingStart,
     257            Qt::QueuedConnection);
     258}
     259
     260void UIChooserAbstractModel::loadTree()
     261{
     262    /* Create invisible root group node: */
     263    m_pInvisibleRootNode = new UIChooserNodeGroup(0 /* parent */,
     264                                                  false /* favorite */,
     265                                                  0 /* position */,
     266                                                  QString() /* name */,
     267                                                  true /* opened */);
     268    if (invisibleRoot())
     269    {
     270        /* Create global node: */
     271        new UIChooserNodeGlobal(m_pInvisibleRootNode,
     272                                isGlobalNodeFavorite(m_pInvisibleRootNode),
     273                                0 /* position */,
     274                                QString() /* tip */);
     275
     276        /* Add all the approved machine nodes into the tree: */
     277        LogRelFlow(("UIChooserModel: Loading VMs...\n"));
     278        foreach (const CMachine &comMachine, vboxGlobal().virtualBox().GetMachines())
     279        {
     280            const QUuid uMachineID = comMachine.GetId();
     281            if (!uMachineID.isNull() && gEDataManager->showMachineInVirtualBoxManagerChooser(uMachineID))
     282                addMachineIntoTheTree(comMachine);
     283        }
     284        LogRelFlow(("UIChooserModel: VMs loaded.\n"));
     285    }
     286}
     287
     288void UIChooserAbstractModel::addMachineIntoTheTree(const CMachine &comMachine, bool fMakeItVisible /* = false */)
     289{
     290    /* Make sure passed VM is not NULL: */
     291    if (comMachine.isNull())
     292        LogRelFlow(("UIChooserModel: ERROR: Passed VM is NULL!\n"));
     293    AssertReturnVoid(!comMachine.isNull());
     294
     295    /* Which VM we are loading: */
     296    LogRelFlow(("UIChooserModel: Loading VM with ID={%s}...\n", toOldStyleUuid(comMachine.GetId()).toUtf8().constData()));
     297    /* Is that machine accessible? */
     298    if (comMachine.GetAccessible())
     299    {
     300        /* VM is accessible: */
     301        const QString strName = comMachine.GetName();
     302        LogRelFlow(("UIChooserModel:  VM {%s} is accessible.\n", strName.toUtf8().constData()));
     303        /* Which groups passed machine attached to? */
     304        const QVector<QString> groups = comMachine.GetGroups();
     305        const QStringList groupList = groups.toList();
     306        const QString strGroups = groupList.join(", ");
     307        LogRelFlow(("UIChooserModel:  VM {%s} has groups: {%s}.\n", strName.toUtf8().constData(),
     308                                                                    strGroups.toUtf8().constData()));
     309        foreach (QString strGroup, groups)
     310        {
     311            /* Remove last '/' if any: */
     312            if (strGroup.right(1) == "/")
     313                strGroup.truncate(strGroup.size() - 1);
     314            /* Create machine-item with found group-item as parent: */
     315            LogRelFlow(("UIChooserModel:   Creating item for VM {%s} in group {%s}.\n", strName.toUtf8().constData(),
     316                                                                                        strGroup.toUtf8().constData()));
     317            createMachineNode(getGroupNode(strGroup, invisibleRoot(), fMakeItVisible), comMachine);
     318        }
     319        /* Update group definitions: */
     320        m_groups[toOldStyleUuid(comMachine.GetId())] = groupList;
     321    }
     322    /* Inaccessible machine: */
     323    else
     324    {
     325        /* VM is accessible: */
     326        LogRelFlow(("UIChooserModel:  VM {%s} is inaccessible.\n", toOldStyleUuid(comMachine.GetId()).toUtf8().constData()));
     327        /* Create machine-item with main-root group-item as parent: */
     328        createMachineNode(invisibleRoot(), comMachine);
     329    }
     330}
     331
     332UIChooserNode *UIChooserAbstractModel::getGroupNode(const QString &strName, UIChooserNode *pParentNode, bool fAllGroupsOpened)
     333{
     334    /* Check passed stuff: */
     335    if (pParentNode->name() == strName)
     336        return pParentNode;
     337
     338    /* Prepare variables: */
     339    const QString strFirstSubName = strName.section('/', 0, 0);
     340    const QString strFirstSuffix = strName.section('/', 1, -1);
     341    const QString strSecondSubName = strFirstSuffix.section('/', 0, 0);
     342    const QString strSecondSuffix = strFirstSuffix.section('/', 1, -1);
     343
     344    /* Passed group name equal to first sub-name: */
     345    if (pParentNode->name() == strFirstSubName)
     346    {
     347        /* Make sure first-suffix is NOT empty: */
     348        AssertMsg(!strFirstSuffix.isEmpty(), ("Invalid group name!"));
     349        /* Trying to get group node among our children: */
     350        foreach (UIChooserNode *pGroupNode, pParentNode->nodes(UIChooserItemType_Group))
     351        {
     352            if (pGroupNode->name() == strSecondSubName)
     353            {
     354                UIChooserNode *pFoundNode = getGroupNode(strFirstSuffix, pGroupNode, fAllGroupsOpened);
     355                if (UIChooserNodeGroup *pFoundGroupNode = pFoundNode->toGroupNode())
     356                    if (fAllGroupsOpened && pFoundGroupNode->isClosed())
     357                        pFoundGroupNode->open();
     358                return pFoundNode;
     359            }
     360        }
     361    }
     362
     363    /* Found nothing? Creating: */
     364    UIChooserNodeGroup *pNewGroupNode =
     365        new UIChooserNodeGroup(pParentNode,
     366                               false /* favorite */,
     367                               getDesiredPosition(pParentNode, UIChooserItemType_Group, strSecondSubName),
     368                               strSecondSubName,
     369                               fAllGroupsOpened || shouldBeGroupOpened(pParentNode, strSecondSubName));
     370    return strSecondSuffix.isEmpty() ? pNewGroupNode : getGroupNode(strFirstSuffix, pNewGroupNode, fAllGroupsOpened);
     371}
     372
     373bool UIChooserAbstractModel::shouldBeGroupOpened(UIChooserNode *pParentNode, const QString &strName)
     374{
     375    /* Read group definitions: */
     376    const QStringList definitions = gEDataManager->selectorWindowGroupsDefinitions(pParentNode->fullName());
     377    /* Return 'false' if no definitions found: */
     378    if (definitions.isEmpty())
     379        return false;
     380
     381    /* Prepare required group definition reg-exp: */
     382    const QString strDefinitionTemplate = QString("g(\\S)*=%1").arg(strName);
     383    const QRegExp definitionRegExp(strDefinitionTemplate);
     384    /* For each the group definition: */
     385    foreach (const QString &strDefinition, definitions)
     386    {
     387        /* Check if this is required definition: */
     388        if (definitionRegExp.indexIn(strDefinition) == 0)
     389        {
     390            /* Get group descriptor: */
     391            const QString strDescriptor(definitionRegExp.cap(1));
     392            if (strDescriptor.contains('o'))
     393                return true;
     394        }
     395    }
     396
     397    /* Return 'false' by default: */
     398    return false;
     399}
     400
     401void UIChooserAbstractModel::wipeOutEmptyGroups(UIChooserNode *pParent)
     402{
     403    /* Cleanup all the group-items recursively first: */
     404    foreach (UIChooserNode *pNode, pParent->nodes(UIChooserItemType_Group))
     405        wipeOutEmptyGroups(pNode);
     406    /* If parent has no nodes: */
     407    if (!pParent->hasNodes())
     408    {
     409        /* If that is non-root item: */
     410        if (!pParent->isRoot())
     411        {
     412            /* Delete parent node and item: */
     413            delete pParent;
     414        }
     415    }
     416}
     417
     418bool UIChooserAbstractModel::isGlobalNodeFavorite(UIChooserNode *pParentNode) const
     419{
     420    /* Read group definitions: */
     421    const QStringList definitions = gEDataManager->selectorWindowGroupsDefinitions(pParentNode->fullName());
     422    /* Return 'false' if no definitions found: */
     423    if (definitions.isEmpty())
     424        return false;
     425
     426    /* Prepare required group definition reg-exp: */
     427    const QString strDefinitionTemplate = QString("n(\\S)*=GLOBAL");
     428    const QRegExp definitionRegExp = QRegExp(strDefinitionTemplate);
     429    /* For each the group definition: */
     430    foreach (const QString &strDefinition, definitions)
     431    {
     432        /* Check if this is required definition: */
     433        if (definitionRegExp.indexIn(strDefinition) == 0)
     434        {
     435            /* Get group descriptor: */
     436            const QString strDescriptor(definitionRegExp.cap(1));
     437            if (strDescriptor.contains('f'))
     438                return true;
     439        }
     440    }
     441
     442    /* Return 'false' by default: */
     443    return false;
     444}
     445
     446int UIChooserAbstractModel::getDesiredPosition(UIChooserNode *pParentNode, UIChooserItemType enmType, const QString &strName)
     447{
     448    /* End of list (by default)? */
     449    int iNewNodeDesiredPosition = -1;
     450    /* Which position should be new node placed by definitions: */
     451    int iNewNodeDefinitionPosition = positionFromDefinitions(pParentNode, enmType, strName);
     452    /* If some position wanted: */
     453    if (iNewNodeDefinitionPosition != -1)
     454    {
     455        /* Start of list if some definition present: */
     456        iNewNodeDesiredPosition = 0;
     457        /* We have to check all the existing node positions: */
     458        QList<UIChooserNode*> nodes = pParentNode->nodes(enmType);
     459        for (int i = nodes.size() - 1; i >= 0; --i)
     460        {
     461            /* Get current node: */
     462            UIChooserNode *pNode = nodes[i];
     463            /* Which position should be current node placed by definitions? */
     464            QString strDefinitionName = pNode->type() == UIChooserItemType_Group ? pNode->name() :
     465                                        pNode->type() == UIChooserItemType_Machine ? toOldStyleUuid(pNode->toMachineNode()->id()) :
     466                                        QString();
     467            AssertMsg(!strDefinitionName.isEmpty(), ("Wrong definition name!"));
     468            int iNodeDefinitionPosition = positionFromDefinitions(pParentNode, enmType, strDefinitionName);
     469            /* If some position wanted: */
     470            if (iNodeDefinitionPosition != -1)
     471            {
     472                AssertMsg(iNodeDefinitionPosition != iNewNodeDefinitionPosition, ("Incorrect definitions!"));
     473                if (iNodeDefinitionPosition < iNewNodeDefinitionPosition)
     474                {
     475                    iNewNodeDesiredPosition = i + 1;
     476                    break;
     477                }
     478            }
     479        }
     480    }
     481    /* Return desired node position: */
     482    return iNewNodeDesiredPosition;
     483}
     484
     485int UIChooserAbstractModel::positionFromDefinitions(UIChooserNode *pParentNode, UIChooserItemType enmType, const QString &strName)
     486{
     487    /* Read group definitions: */
     488    const QStringList definitions = gEDataManager->selectorWindowGroupsDefinitions(pParentNode->fullName());
     489    /* Return 'false' if no definitions found: */
     490    if (definitions.isEmpty())
     491        return -1;
     492
     493    /* Prepare definition reg-exp: */
     494    QString strDefinitionTemplateShort;
     495    QString strDefinitionTemplateFull;
     496    switch (enmType)
     497    {
     498        case UIChooserItemType_Group:
     499            strDefinitionTemplateShort = QString("^g(\\S)*=");
     500            strDefinitionTemplateFull = QString("^g(\\S)*=%1$").arg(strName);
     501            break;
     502        case UIChooserItemType_Machine:
     503            strDefinitionTemplateShort = QString("^m=");
     504            strDefinitionTemplateFull = QString("^m=%1$").arg(strName);
     505            break;
     506        default: return -1;
     507    }
     508    QRegExp definitionRegExpShort(strDefinitionTemplateShort);
     509    QRegExp definitionRegExpFull(strDefinitionTemplateFull);
     510
     511    /* For each the definition: */
     512    int iDefinitionIndex = -1;
     513    foreach (const QString &strDefinition, definitions)
     514    {
     515        /* Check if this definition is of required type: */
     516        if (definitionRegExpShort.indexIn(strDefinition) == 0)
     517        {
     518            ++iDefinitionIndex;
     519            /* Check if this definition is exactly what we need: */
     520            if (definitionRegExpFull.indexIn(strDefinition) == 0)
     521                return iDefinitionIndex;
     522        }
     523    }
     524
     525    /* Return result: */
     526    return -1;
     527}
     528
     529void UIChooserAbstractModel::createMachineNode(UIChooserNode *pParentNode, const CMachine &comMachine)
     530{
     531    /* Create machine node: */
     532    new UIChooserNodeMachine(pParentNode,
     533                             false /* favorite */,
     534                             getDesiredPosition(pParentNode, UIChooserItemType_Machine, toOldStyleUuid(comMachine.GetId())),
     535                             comMachine);
     536}
     537
     538void UIChooserAbstractModel::saveGroupDefinitions()
     539{
     540    /* Make sure there is no group save activity: */
     541    if (UIThreadGroupDefinitionSave::instance())
     542        return;
     543
     544    /* Prepare full group map: */
     545    QMap<QString, QStringList> groups;
     546    gatherGroupDefinitions(groups, invisibleRoot());
     547
     548    /* Save information in other thread: */
     549    UIThreadGroupDefinitionSave::prepare();
     550    emit sigGroupSavingStateChanged();
     551    connect(UIThreadGroupDefinitionSave::instance(), SIGNAL(sigReload(QUuid)),
     552            this, SLOT(sltReloadMachine(QUuid)));
     553    UIThreadGroupDefinitionSave::instance()->configure(this, m_groups, groups);
     554    UIThreadGroupDefinitionSave::instance()->start();
     555    m_groups = groups;
     556}
     557
     558void UIChooserAbstractModel::saveGroupOrders()
     559{
     560    /* Make sure there is no group save activity: */
     561    if (UIThreadGroupOrderSave::instance())
     562        return;
     563
     564    /* Prepare full group map: */
     565    QMap<QString, QStringList> groups;
     566    gatherGroupOrders(groups, invisibleRoot());
     567
     568    /* Save information in other thread: */
     569    UIThreadGroupOrderSave::prepare();
     570    emit sigGroupSavingStateChanged();
     571    UIThreadGroupOrderSave::instance()->configure(this, groups);
     572    UIThreadGroupOrderSave::instance()->start();
     573}
     574
     575void UIChooserAbstractModel::gatherGroupDefinitions(QMap<QString, QStringList> &definitions,
     576                                                    UIChooserNode *pParentGroup)
     577{
     578    /* Iterate over all the machine-nodes: */
     579    foreach (UIChooserNode *pNode, pParentGroup->nodes(UIChooserItemType_Machine))
     580        if (UIChooserNodeMachine *pMachineNode = pNode->toMachineNode())
     581            if (pMachineNode->accessible())
     582                definitions[toOldStyleUuid(pMachineNode->id())] << pParentGroup->fullName();
     583    /* Iterate over all the group-nodes: */
     584    foreach (UIChooserNode *pNode, pParentGroup->nodes(UIChooserItemType_Group))
     585        gatherGroupDefinitions(definitions, pNode);
     586}
     587
     588void UIChooserAbstractModel::gatherGroupOrders(QMap<QString, QStringList> &orders,
     589                                               UIChooserNode *pParentItem)
     590{
     591    /* Prepare extra-data key for current group: */
     592    const QString strExtraDataKey = pParentItem->fullName();
     593    /* Iterate over all the global-nodes: */
     594    foreach (UIChooserNode *pNode, pParentItem->nodes(UIChooserItemType_Global))
     595    {
     596        const QString strGlobalDescriptor(pNode->isFavorite() ? "nf" : "n");
     597        orders[strExtraDataKey] << QString("%1=GLOBAL").arg(strGlobalDescriptor);
     598    }
     599    /* Iterate over all the group-nodes: */
     600    foreach (UIChooserNode *pNode, pParentItem->nodes(UIChooserItemType_Group))
     601    {
     602        const QString strGroupDescriptor(pNode->toGroupNode()->isOpened() ? "go" : "gc");
     603        orders[strExtraDataKey] << QString("%1=%2").arg(strGroupDescriptor, pNode->name());
     604        gatherGroupOrders(orders, pNode);
     605    }
     606    /* Iterate over all the machine-nodes: */
     607    foreach (UIChooserNode *pNode, pParentItem->nodes(UIChooserItemType_Machine))
     608        orders[strExtraDataKey] << QString("m=%1").arg(toOldStyleUuid(pNode->toMachineNode()->id()));
     609}
     610
     611void UIChooserAbstractModel::makeSureGroupDefinitionsSaveIsFinished()
     612{
     613    /* Cleanup if necessary: */
     614    if (UIThreadGroupDefinitionSave::instance())
     615        UIThreadGroupDefinitionSave::cleanup();
     616}
     617
     618void UIChooserAbstractModel::makeSureGroupOrdersSaveIsFinished()
     619{
     620    /* Cleanup if necessary: */
     621    if (UIThreadGroupOrderSave::instance())
     622        UIThreadGroupOrderSave::cleanup();
     623}
     624
     625/* static */
     626QString UIChooserAbstractModel::toOldStyleUuid(const QUuid &uId)
     627{
     628    return uId.toString().remove(QRegExp("[{}]"));
     629}
     630
     631
     632/*********************************************************************************************************************************
    58633*   Class UIChooserModel implementation.                                                                                         *
    59634*********************************************************************************************************************************/
    60635
    61636UIChooserModel:: UIChooserModel(UIChooser *pParent)
    62     : QObject(pParent)
     637    : UIChooserAbstractModel(pParent)
    63638    , m_pChooser(pParent)
    64639    , m_pScene(0)
     
    69644    , m_pContextMenuMachine(0)
    70645    , m_iCurrentScrolledIndex(-1)
    71     , m_pInvisibleRootNode(0)
    72646    , m_iScrollingTokenSize(30)
    73647    , m_fIsScrollingInProgress(false)
     
    84658void UIChooserModel::init()
    85659{
    86     /* Load tree: */
    87     loadTree();
     660    /* Call to base-class: */
     661    UIChooserAbstractModel::init();
    88662
    89663    /* Build tree for main root: */
     
    101675    saveLastSelectedItem();
    102676
    103     /* Currently we are not saving group descriptors
    104      * (which reflecting group toggle-state) on-the-fly,
    105      * so, for now we are additionally save group orders
    106      * when exiting application: */
    107     saveGroupOrders();
    108 
    109     /* Make sure all saving steps complete: */
    110     makeSureGroupDefinitionsSaveIsFinished();
    111     makeSureGroupOrdersSaveIsFinished();
    112 
    113677    /* Unset current items: */
    114678    unsetCurrentItems();
    115679
    116     /* Delete tree: */
    117     delete m_pInvisibleRootNode;
    118     m_pInvisibleRootNode = 0;
     680    /* Call to base-class: */
     681    UIChooserAbstractModel::deinit();
    119682}
    120683
     
    4641027void UIChooserModel::performSearch(const QString &strSearchTerm, int iItemSearchFlags)
    4651028{
    466     if (!m_pInvisibleRootNode)
     1029    if (!invisibleRoot())
    4671030        return;
    4681031
     
    4741037        return;
    4751038
    476     m_pInvisibleRootNode->searchForNodes(strSearchTerm, iItemSearchFlags, m_searchResults);
     1039    invisibleRoot()->searchForNodes(strSearchTerm, iItemSearchFlags, m_searchResults);
    4771040
    4781041    foreach (UIChooserNode* pNode, allNodes)
     
    4901053    QList<UIChooserNode*> allNodes;
    4911054    /* Calling UIChooserNode::searchForNodes with an empty search string returns a list all nodes (of the whole treee) of the required type: */
    492     m_pInvisibleRootNode->searchForNodes(QString(), UIChooserItemSearchFlag_Machine, allNodes);
     1055    invisibleRoot()->searchForNodes(QString(), UIChooserItemSearchFlag_Machine, allNodes);
    4931056
    4941057    /* Reset the disabled flag of the node items first. */
     
    5471110}
    5481111
    549 UIChooserNode *UIChooserModel::invisibleRoot() const
    550 {
    551     return m_pInvisibleRootNode;
    552 }
    553 
    5541112UIChooserItem *UIChooserModel::root() const
    5551113{
     
    5601118{
    5611119    sltEditGroupName();
    562 }
    563 
    564 void UIChooserModel::wipeOutEmptyGroups()
    565 {
    566     wipeOutEmptyGroups(invisibleRoot());
    5671120}
    5681121
     
    5941147{
    5951148    return m_pLookupTimer->isActive();
    596 }
    597 
    598 /* static */
    599 QString UIChooserModel::uniqueGroupName(UIChooserItem *pRoot)
    600 {
    601     /* Enumerate all the group names: */
    602     QStringList groupNames;
    603     foreach (UIChooserItem *pItem, pRoot->items(UIChooserItemType_Group))
    604         groupNames << pItem->name();
    605 
    606     /* Prepare reg-exp: */
    607     const QString strMinimumName = tr("New group");
    608     const QString strShortTemplate = strMinimumName;
    609     const QString strFullTemplate = strShortTemplate + QString(" (\\d+)");
    610     const QRegExp shortRegExp(strShortTemplate);
    611     const QRegExp fullRegExp(strFullTemplate);
    612 
    613     /* Search for the maximum index: */
    614     int iMinimumPossibleNumber = 0;
    615     foreach (const QString &strName, groupNames)
    616     {
    617         if (shortRegExp.exactMatch(strName))
    618             iMinimumPossibleNumber = qMax(iMinimumPossibleNumber, 2);
    619         else if (fullRegExp.exactMatch(strName))
    620             iMinimumPossibleNumber = qMax(iMinimumPossibleNumber, fullRegExp.cap(1).toInt() + 1);
    621     }
    622 
    623     /* Prepare result: */
    624     QString strResult = strMinimumName;
    625     if (iMinimumPossibleNumber)
    626         strResult += " " + QString::number(iMinimumPossibleNumber);
    627     return strResult;
    6281149}
    6291150
     
    6621183        }
    6631184    }
    664 }
    665 
    666 void UIChooserModel::saveGroupSettings()
    667 {
    668     emit sigGroupSavingStarted();
    669 }
    670 
    671 bool UIChooserModel::isGroupSavingInProgress() const
    672 {
    673     return    UIThreadGroupDefinitionSave::instance()
    674            || UIThreadGroupOrderSave::instance();
    6751185}
    6761186
     
    7221232}
    7231233
    724 void UIChooserModel::sltMachineStateChanged(const QUuid &uId, const KMachineState)
    725 {
    726     /* Update machine-nodes with passed id: */
    727     invisibleRoot()->updateAllNodes(uId);
    728 }
    729 
    730 void UIChooserModel::sltMachineDataChanged(const QUuid &uId)
    731 {
    732     /* Update machine-nodes with passed id: */
    733     invisibleRoot()->updateAllNodes(uId);
    734 }
    735 
    7361234void UIChooserModel::sltMachineRegistered(const QUuid &uId, const bool fRegistered)
    7371235{
    738     /* New VM registered? */
    739     if (fRegistered)
    740     {
    741         /* Show machine if we should: */
    742         CMachine comMachine = vboxGlobal().virtualBox().FindMachine(uId.toString());
    743         if (gEDataManager->showMachineInVirtualBoxManagerChooser(uId))
    744         {
    745             /* Add new machine-item: */
    746             addMachineIntoTheTree(comMachine, true /* make it visible */);
    747 
    748             /* Rebuild tree for main root: */
    749             buildTreeForMainRoot();
    750             updateNavigation();
    751             updateLayout();
    752 
    753             /* Choose newly added item: */
    754             setCurrentItem(root()->searchForItem(comMachine.GetName(),
    755                                                  UIChooserItemSearchFlag_Machine |
    756                                                  UIChooserItemSearchFlag_ExactName));
    757         }
    758     }
     1236    /* Call to base-class: */
     1237    UIChooserAbstractModel::sltMachineRegistered(uId, fRegistered);
     1238
    7591239    /* Existing VM unregistered? */
    760     else
    761     {
    762         /* Remove machine-items with passed id: */
    763         invisibleRoot()->removeAllNodes(uId.toString());
    764         /* Wipe out empty groups: */
    765         wipeOutEmptyGroups();
    766 
     1240    if (!fRegistered)
     1241    {
    7671242        /* Rebuild tree for main root: */
    7681243        buildTreeForMainRoot();
     
    7791254        emit sigSelectionChanged();
    7801255    }
    781 }
    782 
    783 void UIChooserModel::sltSessionStateChanged(const QUuid &uId, const KSessionState)
    784 {
    785     /* Update machine-nodes with passed id: */
    786     invisibleRoot()->updateAllNodes(uId);
    787 }
    788 
    789 void UIChooserModel::sltSnapshotChanged(const QUuid &uId, const QUuid &)
    790 {
    791     /* Update machine-nodes with passed id: */
    792     invisibleRoot()->updateAllNodes(uId);
     1256    /* New VM registered? */
     1257    else
     1258    {
     1259        /* Should we show this VM? */
     1260        if (gEDataManager->showMachineInVirtualBoxManagerChooser(uId))
     1261        {
     1262            /* Rebuild tree for main root: */
     1263            buildTreeForMainRoot();
     1264            updateNavigation();
     1265            updateLayout();
     1266
     1267            /* Choose newly added item: */
     1268            CMachine comMachine = vboxGlobal().virtualBox().FindMachine(uId.toString());
     1269            setCurrentItem(root()->searchForItem(comMachine.GetName(),
     1270                                                 UIChooserItemSearchFlag_Machine |
     1271                                                 UIChooserItemSearchFlag_ExactName));
     1272        }
     1273    }
     1274}
     1275
     1276void UIChooserModel::sltReloadMachine(const QUuid &uId)
     1277{
     1278    /* Call to base-class: */
     1279    UIChooserAbstractModel::sltReloadMachine(uId);
     1280
     1281    /* Show machine if we should: */
     1282    if (gEDataManager->showMachineInVirtualBoxManagerChooser(uId))
     1283    {
     1284        /* Rebuild tree for main root: */
     1285        buildTreeForMainRoot();
     1286        updateNavigation();
     1287        updateLayout();
     1288
     1289        /* Choose newly added item: */
     1290        CMachine comMachine = vboxGlobal().virtualBox().FindMachine(uId.toString());
     1291        setCurrentItem(root()->searchForItem(comMachine.GetName(),
     1292                                             UIChooserItemSearchFlag_Machine |
     1293                                             UIChooserItemSearchFlag_ExactName));
     1294    }
     1295    else
     1296    {
     1297        /* Make sure at least one item selected after that: */
     1298        if (!currentItem() && !navigationList().isEmpty())
     1299            setCurrentItem(navigationList().first());
     1300    }
     1301
     1302    /* Notify listeners about selection change: */
     1303    emit sigSelectionChanged();
    7931304}
    7941305
     
    8931404                UIChooserItemGroup *pGroupItem = new UIChooserItemGroup(pParentItem, pGroupNode);
    8941405                if (toBeRenamed.contains(pNode))
    895                     pGroupNode->setName(uniqueGroupName(pParentItem));
     1406                    pGroupNode->setName(uniqueGroupName(pParentNode));
    8961407                copiedItems << pGroupItem;
    8971408                break;
     
    9781489                                                               false /* favorite */,
    9791490                                                               invisibleRoot()->nodes().size() /* position */,
    980                                                                uniqueGroupName(root()),
     1491                                                               uniqueGroupName(invisibleRoot()),
    9811492                                                               true /* opened */);
    9821493    UIChooserItemGroup *pNewGroupItem = new UIChooserItemGroup(root(), pNewGroupNode);
     
    10321543}
    10331544
    1034 void UIChooserModel::sltReloadMachine(const QUuid &uId)
    1035 {
    1036     /* Remove all the nodes first: */
    1037     invisibleRoot()->removeAllNodes(uId);
    1038     /* Wipe out empty groups: */
    1039     wipeOutEmptyGroups();
    1040 
    1041     /* Show machine if we should: */
    1042     CMachine comMachine = vboxGlobal().virtualBox().FindMachine(uId.toString());
    1043     if (gEDataManager->showMachineInVirtualBoxManagerChooser(uId))
    1044     {
    1045         /* Add new machine-item: */
    1046         addMachineIntoTheTree(comMachine);
    1047 
    1048         /* Rebuild tree for main root: */
    1049         buildTreeForMainRoot();
    1050         updateNavigation();
    1051         updateLayout();
    1052 
    1053         /* Choose newly added item: */
    1054         setCurrentItem(root()->searchForItem(comMachine.GetName(),
    1055                                              UIChooserItemSearchFlag_Machine |
    1056                                              UIChooserItemSearchFlag_ExactName));
    1057     }
    1058     else
    1059     {
    1060         /* Make sure at least one item selected after that: */
    1061         if (!currentItem() && !navigationList().isEmpty())
    1062             setCurrentItem(navigationList().first());
    1063     }
    1064 
    1065     /* Notify listeners about selection change: */
    1066     emit sigSelectionChanged();
    1067 }
    1068 
    10691545void UIChooserModel::sltSortParentGroup()
    10701546{
     
    12401716}
    12411717
    1242 void UIChooserModel::sltGroupSavingStart()
    1243 {
    1244     saveGroupDefinitions();
    1245     saveGroupOrders();
    1246 }
    1247 
    1248 void UIChooserModel::sltGroupDefinitionsSaveComplete()
    1249 {
    1250     makeSureGroupDefinitionsSaveIsFinished();
    1251     emit sigGroupSavingStateChanged();
    1252 }
    1253 
    1254 void UIChooserModel::sltGroupOrdersSaveComplete()
    1255 {
    1256     makeSureGroupOrdersSaveIsFinished();
    1257     emit sigGroupSavingStateChanged();
    1258 }
    1259 
    12601718void UIChooserModel::prepare()
    12611719{
    1262     /* Prepare scene: */
    12631720    prepareScene();
    1264 
    1265     /* Prepare lookup: */
    12661721    prepareLookup();
    1267 
    1268     /* Prepare context-menu: */
    12691722    prepareContextMenu();
    1270 
    1271     /* Prepare handlers: */
    12721723    prepareHandlers();
    1273 
    1274     /* Prepare connections: */
    12751724    prepareConnections();
    12761725}
     
    14111860    connect(this, SIGNAL(sigToggleFinished()),
    14121861            parent(), SIGNAL(sigToggleFinished()));
    1413     connect(this, SIGNAL(sigGroupSavingStateChanged()),
    1414             parent(), SIGNAL(sigGroupSavingStateChanged()));
    1415 
    1416     /* Setup global connections: */
    1417     connect(gVBoxEvents, SIGNAL(sigMachineStateChange(QUuid, KMachineState)),
    1418             this, SLOT(sltMachineStateChanged(QUuid, KMachineState)));
    1419     connect(gVBoxEvents, SIGNAL(sigMachineDataChange(QUuid)),
    1420             this, SLOT(sltMachineDataChanged(QUuid)));
    1421     connect(gVBoxEvents, SIGNAL(sigMachineRegistered(QUuid, bool)),
    1422             this, SLOT(sltMachineRegistered(QUuid, bool)));
    1423     connect(gVBoxEvents, SIGNAL(sigSessionStateChange(QUuid, KSessionState)),
    1424             this, SLOT(sltSessionStateChanged(QUuid, KSessionState)));
    1425     connect(gVBoxEvents, SIGNAL(sigSnapshotTake(QUuid, QUuid)),
    1426             this, SLOT(sltSnapshotChanged(QUuid, QUuid)));
    1427     connect(gVBoxEvents, SIGNAL(sigSnapshotDelete(QUuid, QUuid)),
    1428             this, SLOT(sltSnapshotChanged(QUuid, QUuid)));
    1429     connect(gVBoxEvents, SIGNAL(sigSnapshotChange(QUuid, QUuid)),
    1430             this, SLOT(sltSnapshotChanged(QUuid, QUuid)));
    1431     connect(gVBoxEvents, SIGNAL(sigSnapshotRestore(QUuid, QUuid)),
    1432             this, SLOT(sltSnapshotChanged(QUuid, QUuid)));
    14331862
    14341863    /* Setup action connections: */
     
    14571886    connect(actionPool()->action(UIActionIndexST_M_Machine_S_Search), SIGNAL(triggered()),
    14581887            this, SLOT(sltShowHideSearchWidget()));
    1459 
    1460     /* Setup group saving connections: */
    1461     connect(this, &UIChooserModel::sigGroupSavingStarted,
    1462             this, &UIChooserModel::sltGroupSavingStart,
    1463             Qt::QueuedConnection);
    14641888}
    14651889
     
    15101934void UIChooserModel::cleanup()
    15111935{
    1512     /* Cleanup handlers: */
    15131936    cleanupHandlers();
    1514 
    1515     /* Prepare context-menu: */
    15161937    cleanupContextMenu();
    1517 
    1518     /* Cleanup lookup: */
    15191938    cleanupLookup();
    1520 
    1521     /* Cleanup scene: */
    15221939    cleanupScene();
    15231940}
     
    16692086}
    16702087
    1671 void UIChooserModel::loadTree()
    1672 {
    1673     /* Create invisible root group node: */
    1674     m_pInvisibleRootNode = new UIChooserNodeGroup(0 /* parent */,
    1675                                                   false /* favorite */,
    1676                                                   0 /* position */,
    1677                                                   QString() /* name */,
    1678                                                   true /* opened */);
    1679     if (invisibleRoot())
    1680     {
    1681         /* Create global node: */
    1682         new UIChooserNodeGlobal(m_pInvisibleRootNode,
    1683                                 isGlobalNodeFavorite(m_pInvisibleRootNode),
    1684                                 0 /* position */,
    1685                                 QString() /* tip */);
    1686 
    1687         /* Add all the approved machine nodes into the tree: */
    1688         LogRelFlow(("UIChooserModel: Loading VMs...\n"));
    1689         foreach (const CMachine &comMachine, vboxGlobal().virtualBox().GetMachines())
    1690         {
    1691             const QUuid uMachineID = comMachine.GetId();
    1692             if (!uMachineID.isNull() && gEDataManager->showMachineInVirtualBoxManagerChooser(uMachineID))
    1693                 addMachineIntoTheTree(comMachine);
    1694         }
    1695         LogRelFlow(("UIChooserModel: VMs loaded.\n"));
    1696     }
    1697 }
    1698 
    1699 void UIChooserModel::addMachineIntoTheTree(const CMachine &comMachine, bool fMakeItVisible /* = false */)
    1700 {
    1701     /* Make sure passed VM is not NULL: */
    1702     if (comMachine.isNull())
    1703         LogRelFlow(("UIChooserModel: ERROR: Passed VM is NULL!\n"));
    1704     AssertReturnVoid(!comMachine.isNull());
    1705 
    1706     /* Which VM we are loading: */
    1707     LogRelFlow(("UIChooserModel: Loading VM with ID={%s}...\n", toOldStyleUuid(comMachine.GetId()).toUtf8().constData()));
    1708     /* Is that machine accessible? */
    1709     if (comMachine.GetAccessible())
    1710     {
    1711         /* VM is accessible: */
    1712         const QString strName = comMachine.GetName();
    1713         LogRelFlow(("UIChooserModel:  VM {%s} is accessible.\n", strName.toUtf8().constData()));
    1714         /* Which groups passed machine attached to? */
    1715         const QVector<QString> groups = comMachine.GetGroups();
    1716         const QStringList groupList = groups.toList();
    1717         const QString strGroups = groupList.join(", ");
    1718         LogRelFlow(("UIChooserModel:  VM {%s} has groups: {%s}.\n", strName.toUtf8().constData(),
    1719                                                                     strGroups.toUtf8().constData()));
    1720         foreach (QString strGroup, groups)
    1721         {
    1722             /* Remove last '/' if any: */
    1723             if (strGroup.right(1) == "/")
    1724                 strGroup.truncate(strGroup.size() - 1);
    1725             /* Create machine-item with found group-item as parent: */
    1726             LogRelFlow(("UIChooserModel:   Creating item for VM {%s} in group {%s}.\n", strName.toUtf8().constData(),
    1727                                                                                         strGroup.toUtf8().constData()));
    1728             createMachineNode(getGroupNode(strGroup, invisibleRoot(), fMakeItVisible), comMachine);
    1729         }
    1730         /* Update group definitions: */
    1731         m_groups[toOldStyleUuid(comMachine.GetId())] = groupList;
    1732     }
    1733     /* Inaccessible machine: */
    1734     else
    1735     {
    1736         /* VM is accessible: */
    1737         LogRelFlow(("UIChooserModel:  VM {%s} is inaccessible.\n", toOldStyleUuid(comMachine.GetId()).toUtf8().constData()));
    1738         /* Create machine-item with main-root group-item as parent: */
    1739         createMachineNode(invisibleRoot(), comMachine);
    1740     }
    1741 }
    1742 
    1743 UIChooserNode *UIChooserModel::getGroupNode(const QString &strName, UIChooserNode *pParentNode, bool fAllGroupsOpened)
    1744 {
    1745     /* Check passed stuff: */
    1746     if (pParentNode->name() == strName)
    1747         return pParentNode;
    1748 
    1749     /* Prepare variables: */
    1750     const QString strFirstSubName = strName.section('/', 0, 0);
    1751     const QString strFirstSuffix = strName.section('/', 1, -1);
    1752     const QString strSecondSubName = strFirstSuffix.section('/', 0, 0);
    1753     const QString strSecondSuffix = strFirstSuffix.section('/', 1, -1);
    1754 
    1755     /* Passed group name equal to first sub-name: */
    1756     if (pParentNode->name() == strFirstSubName)
    1757     {
    1758         /* Make sure first-suffix is NOT empty: */
    1759         AssertMsg(!strFirstSuffix.isEmpty(), ("Invalid group name!"));
    1760         /* Trying to get group node among our children: */
    1761         foreach (UIChooserNode *pGroupNode, pParentNode->nodes(UIChooserItemType_Group))
    1762         {
    1763             if (pGroupNode->name() == strSecondSubName)
    1764             {
    1765                 UIChooserNode *pFoundNode = getGroupNode(strFirstSuffix, pGroupNode, fAllGroupsOpened);
    1766                 if (UIChooserNodeGroup *pFoundGroupNode = pFoundNode->toGroupNode())
    1767                     if (fAllGroupsOpened && pFoundGroupNode->isClosed())
    1768                         pFoundGroupNode->open();
    1769                 return pFoundNode;
    1770             }
    1771         }
    1772     }
    1773 
    1774     /* Found nothing? Creating: */
    1775     UIChooserNodeGroup *pNewGroupNode =
    1776         new UIChooserNodeGroup(pParentNode,
    1777                                false /* favorite */,
    1778                                getDesiredPosition(pParentNode, UIChooserItemType_Group, strSecondSubName),
    1779                                strSecondSubName,
    1780                                fAllGroupsOpened || shouldBeGroupOpened(pParentNode, strSecondSubName));
    1781     return strSecondSuffix.isEmpty() ? pNewGroupNode : getGroupNode(strFirstSuffix, pNewGroupNode, fAllGroupsOpened);
    1782 }
    1783 
    1784 bool UIChooserModel::shouldBeGroupOpened(UIChooserNode *pParentNode, const QString &strName)
    1785 {
    1786     /* Read group definitions: */
    1787     const QStringList definitions = gEDataManager->selectorWindowGroupsDefinitions(pParentNode->fullName());
    1788     /* Return 'false' if no definitions found: */
    1789     if (definitions.isEmpty())
    1790         return false;
    1791 
    1792     /* Prepare required group definition reg-exp: */
    1793     const QString strDefinitionTemplate = QString("g(\\S)*=%1").arg(strName);
    1794     const QRegExp definitionRegExp(strDefinitionTemplate);
    1795     /* For each the group definition: */
    1796     foreach (const QString &strDefinition, definitions)
    1797     {
    1798         /* Check if this is required definition: */
    1799         if (definitionRegExp.indexIn(strDefinition) == 0)
    1800         {
    1801             /* Get group descriptor: */
    1802             const QString strDescriptor(definitionRegExp.cap(1));
    1803             if (strDescriptor.contains('o'))
    1804                 return true;
    1805         }
    1806     }
    1807 
    1808     /* Return 'false' by default: */
    1809     return false;
    1810 }
    1811 
    1812 void UIChooserModel::wipeOutEmptyGroups(UIChooserNode *pParent)
    1813 {
    1814     /* Cleanup all the group-items recursively first: */
    1815     foreach (UIChooserNode *pNode, pParent->nodes(UIChooserItemType_Group))
    1816         wipeOutEmptyGroups(pNode);
    1817     /* If parent has no nodes: */
    1818     if (!pParent->hasNodes())
    1819     {
    1820         /* If that is non-root item: */
    1821         if (!pParent->isRoot())
    1822         {
    1823             /* Delete parent node and item: */
    1824             delete pParent;
    1825         }
    1826     }
    1827 }
    1828 
    1829 bool UIChooserModel::isGlobalNodeFavorite(UIChooserNode *pParentNode) const
    1830 {
    1831     /* Read group definitions: */
    1832     const QStringList definitions = gEDataManager->selectorWindowGroupsDefinitions(pParentNode->fullName());
    1833     /* Return 'false' if no definitions found: */
    1834     if (definitions.isEmpty())
    1835         return false;
    1836 
    1837     /* Prepare required group definition reg-exp: */
    1838     const QString strDefinitionTemplate = QString("n(\\S)*=GLOBAL");
    1839     const QRegExp definitionRegExp = QRegExp(strDefinitionTemplate);
    1840     /* For each the group definition: */
    1841     foreach (const QString &strDefinition, definitions)
    1842     {
    1843         /* Check if this is required definition: */
    1844         if (definitionRegExp.indexIn(strDefinition) == 0)
    1845         {
    1846             /* Get group descriptor: */
    1847             const QString strDescriptor(definitionRegExp.cap(1));
    1848             if (strDescriptor.contains('f'))
    1849                 return true;
    1850         }
    1851     }
    1852 
    1853     /* Return 'false' by default: */
    1854     return false;
    1855 }
    1856 
    1857 int UIChooserModel::getDesiredPosition(UIChooserNode *pParentNode, UIChooserItemType enmType, const QString &strName)
    1858 {
    1859     /* End of list (by default)? */
    1860     int iNewNodeDesiredPosition = -1;
    1861     /* Which position should be new node placed by definitions: */
    1862     int iNewNodeDefinitionPosition = positionFromDefinitions(pParentNode, enmType, strName);
    1863     /* If some position wanted: */
    1864     if (iNewNodeDefinitionPosition != -1)
    1865     {
    1866         /* Start of list if some definition present: */
    1867         iNewNodeDesiredPosition = 0;
    1868         /* We have to check all the existing node positions: */
    1869         QList<UIChooserNode*> nodes = pParentNode->nodes(enmType);
    1870         for (int i = nodes.size() - 1; i >= 0; --i)
    1871         {
    1872             /* Get current node: */
    1873             UIChooserNode *pNode = nodes[i];
    1874             /* Which position should be current node placed by definitions? */
    1875             QString strDefinitionName = pNode->type() == UIChooserItemType_Group ? pNode->name() :
    1876                                         pNode->type() == UIChooserItemType_Machine ? toOldStyleUuid(pNode->toMachineNode()->id()) :
    1877                                         QString();
    1878             AssertMsg(!strDefinitionName.isEmpty(), ("Wrong definition name!"));
    1879             int iNodeDefinitionPosition = positionFromDefinitions(pParentNode, enmType, strDefinitionName);
    1880             /* If some position wanted: */
    1881             if (iNodeDefinitionPosition != -1)
    1882             {
    1883                 AssertMsg(iNodeDefinitionPosition != iNewNodeDefinitionPosition, ("Incorrect definitions!"));
    1884                 if (iNodeDefinitionPosition < iNewNodeDefinitionPosition)
    1885                 {
    1886                     iNewNodeDesiredPosition = i + 1;
    1887                     break;
    1888                 }
    1889             }
    1890         }
    1891     }
    1892     /* Return desired node position: */
    1893     return iNewNodeDesiredPosition;
    1894 }
    1895 
    1896 int UIChooserModel::positionFromDefinitions(UIChooserNode *pParentNode, UIChooserItemType enmType, const QString &strName)
    1897 {
    1898     /* Read group definitions: */
    1899     const QStringList definitions = gEDataManager->selectorWindowGroupsDefinitions(pParentNode->fullName());
    1900     /* Return 'false' if no definitions found: */
    1901     if (definitions.isEmpty())
    1902         return -1;
    1903 
    1904     /* Prepare definition reg-exp: */
    1905     QString strDefinitionTemplateShort;
    1906     QString strDefinitionTemplateFull;
    1907     switch (enmType)
    1908     {
    1909         case UIChooserItemType_Group:
    1910             strDefinitionTemplateShort = QString("^g(\\S)*=");
    1911             strDefinitionTemplateFull = QString("^g(\\S)*=%1$").arg(strName);
    1912             break;
    1913         case UIChooserItemType_Machine:
    1914             strDefinitionTemplateShort = QString("^m=");
    1915             strDefinitionTemplateFull = QString("^m=%1$").arg(strName);
    1916             break;
    1917         default: return -1;
    1918     }
    1919     QRegExp definitionRegExpShort(strDefinitionTemplateShort);
    1920     QRegExp definitionRegExpFull(strDefinitionTemplateFull);
    1921 
    1922     /* For each the definition: */
    1923     int iDefinitionIndex = -1;
    1924     foreach (const QString &strDefinition, definitions)
    1925     {
    1926         /* Check if this definition is of required type: */
    1927         if (definitionRegExpShort.indexIn(strDefinition) == 0)
    1928         {
    1929             ++iDefinitionIndex;
    1930             /* Check if this definition is exactly what we need: */
    1931             if (definitionRegExpFull.indexIn(strDefinition) == 0)
    1932                 return iDefinitionIndex;
    1933         }
    1934     }
    1935 
    1936     /* Return result: */
    1937     return -1;
    1938 }
    1939 
    1940 void UIChooserModel::createMachineNode(UIChooserNode *pParentNode, const CMachine &comMachine)
    1941 {
    1942     /* Create machine node: */
    1943     new UIChooserNodeMachine(pParentNode,
    1944                              false /* favorite */,
    1945                              getDesiredPosition(pParentNode, UIChooserItemType_Machine, toOldStyleUuid(comMachine.GetId())),
    1946                              comMachine);
    1947 }
    1948 
    19492088void UIChooserModel::buildTreeForMainRoot()
    19502089{
     
    21012240}
    21022241
    2103 void UIChooserModel::saveGroupDefinitions()
    2104 {
    2105     /* Make sure there is no group save activity: */
    2106     if (UIThreadGroupDefinitionSave::instance())
    2107         return;
    2108 
    2109     /* Prepare full group map: */
    2110     QMap<QString, QStringList> groups;
    2111     gatherGroupDefinitions(groups, invisibleRoot());
    2112 
    2113     /* Save information in other thread: */
    2114     UIThreadGroupDefinitionSave::prepare();
    2115     emit sigGroupSavingStateChanged();
    2116     connect(UIThreadGroupDefinitionSave::instance(), SIGNAL(sigReload(QUuid)),
    2117             this, SLOT(sltReloadMachine(QUuid)));
    2118     UIThreadGroupDefinitionSave::instance()->configure(this, m_groups, groups);
    2119     UIThreadGroupDefinitionSave::instance()->start();
    2120     m_groups = groups;
    2121 }
    2122 
    2123 void UIChooserModel::saveGroupOrders()
    2124 {
    2125     /* Make sure there is no group save activity: */
    2126     if (UIThreadGroupOrderSave::instance())
    2127         return;
    2128 
    2129     /* Prepare full group map: */
    2130     QMap<QString, QStringList> groups;
    2131     gatherGroupOrders(groups, invisibleRoot());
    2132 
    2133     /* Save information in other thread: */
    2134     UIThreadGroupOrderSave::prepare();
    2135     emit sigGroupSavingStateChanged();
    2136     UIThreadGroupOrderSave::instance()->configure(this, groups);
    2137     UIThreadGroupOrderSave::instance()->start();
    2138 }
    2139 
    2140 void UIChooserModel::gatherGroupDefinitions(QMap<QString, QStringList> &definitions,
    2141                                             UIChooserNode *pParentGroup)
    2142 {
    2143     /* Iterate over all the machine-nodes: */
    2144     foreach (UIChooserNode *pNode, pParentGroup->nodes(UIChooserItemType_Machine))
    2145         if (UIChooserNodeMachine *pMachineNode = pNode->toMachineNode())
    2146             if (pMachineNode->accessible())
    2147                 definitions[toOldStyleUuid(pMachineNode->id())] << pParentGroup->fullName();
    2148     /* Iterate over all the group-nodes: */
    2149     foreach (UIChooserNode *pNode, pParentGroup->nodes(UIChooserItemType_Group))
    2150         gatherGroupDefinitions(definitions, pNode);
    2151 }
    2152 
    2153 void UIChooserModel::gatherGroupOrders(QMap<QString, QStringList> &orders,
    2154                                        UIChooserNode *pParentItem)
    2155 {
    2156     /* Prepare extra-data key for current group: */
    2157     const QString strExtraDataKey = pParentItem->fullName();
    2158     /* Iterate over all the global-nodes: */
    2159     foreach (UIChooserNode *pNode, pParentItem->nodes(UIChooserItemType_Global))
    2160     {
    2161         const QString strGlobalDescriptor(pNode->isFavorite() ? "nf" : "n");
    2162         orders[strExtraDataKey] << QString("%1=GLOBAL").arg(strGlobalDescriptor);
    2163     }
    2164     /* Iterate over all the group-nodes: */
    2165     foreach (UIChooserNode *pNode, pParentItem->nodes(UIChooserItemType_Group))
    2166     {
    2167         const QString strGroupDescriptor(pNode->toGroupNode()->isOpened() ? "go" : "gc");
    2168         orders[strExtraDataKey] << QString("%1=%2").arg(strGroupDescriptor, pNode->name());
    2169         gatherGroupOrders(orders, pNode);
    2170     }
    2171     /* Iterate over all the machine-nodes: */
    2172     foreach (UIChooserNode *pNode, pParentItem->nodes(UIChooserItemType_Machine))
    2173         orders[strExtraDataKey] << QString("m=%1").arg(toOldStyleUuid(pNode->toMachineNode()->id()));
    2174 }
    2175 
    2176 void UIChooserModel::makeSureGroupDefinitionsSaveIsFinished()
    2177 {
    2178     /* Cleanup if necessary: */
    2179     if (UIThreadGroupDefinitionSave::instance())
    2180         UIThreadGroupDefinitionSave::cleanup();
    2181 }
    2182 
    2183 void UIChooserModel::makeSureGroupOrdersSaveIsFinished()
    2184 {
    2185     /* Cleanup if necessary: */
    2186     if (UIThreadGroupOrderSave::instance())
    2187         UIThreadGroupOrderSave::cleanup();
    2188 }
    2189 
    2190 /* static */
    2191 QString UIChooserModel::toOldStyleUuid(const QUuid &uId)
    2192 {
    2193     return uId.toString().remove(QRegExp("[{}]"));
    2194 }
    2195 
    21962242
    21972243/*********************************************************************************************************************************
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser/UIChooserModel.h

    r77847 r77890  
    5656
    5757
    58 /** QObject extension used as VM Chooser-pane model: */
    59 class UIChooserModel : public QObject
     58/** QObject extension used as VM Chooser-pane abstract model.
     59  * This class is used to load/save a tree of abstract invisible
     60  * nodes representing VMs and their groups from/to extra-data. */
     61class UIChooserAbstractModel : public QObject
     62{
     63    Q_OBJECT;
     64
     65signals:
     66
     67    /** @name Group saving stuff.
     68      * @{ */
     69        /** Notifies about group saving started. */
     70        void sigGroupSavingStarted();
     71        /** Notifies about group saving state changed. */
     72        void sigGroupSavingStateChanged();
     73    /** @} */
     74
     75public:
     76
     77    /** Constructs abstract Chooser-model passing @a pParent to the base-class. */
     78    UIChooserAbstractModel(UIChooser *pParent);
     79
     80    /** @name General stuff.
     81      * @{ */
     82        /** Inits model. */
     83        void init();
     84        /** Deinits model. */
     85        void deinit();
     86    /** @} */
     87
     88    /** @name Children stuff.
     89      * @{ */
     90        /** Returns invisible root node instance. */
     91        UIChooserNode *invisibleRoot() const;
     92
     93        /** Wipes out empty groups. */
     94        void wipeOutEmptyGroups();
     95
     96        /** Generates unique group name traversing recursively starting from @a pRoot. */
     97        static QString uniqueGroupName(UIChooserNode *pRoot);
     98    /** @} */
     99
     100    /** @name Group saving stuff.
     101      * @{ */
     102        /** Commands to save group settings. */
     103        void saveGroupSettings();
     104        /** Returns whether group saving is in progress. */
     105        bool isGroupSavingInProgress() const;
     106    /** @} */
     107
     108protected slots:
     109
     110    /** @name Main event handling stuff.
     111      * @{ */
     112        /** Handles machine @a enmState change for machine with certain @a uId. */
     113        virtual void sltMachineStateChanged(const QUuid &uId, const KMachineState enmState);
     114        /** Handles machine data change for machine with certain @a uId. */
     115        virtual void sltMachineDataChanged(const QUuid &uId);
     116        /** Handles machine registering/unregistering for machine with certain @a uId. */
     117        virtual void sltMachineRegistered(const QUuid &uId, const bool fRegistered);
     118        /** Handles session @a enmState change for machine with certain @a uId. */
     119        virtual void sltSessionStateChanged(const QUuid &uId, const KSessionState enmState);
     120        /** Handles snapshot change for machine/snapshot with certain @a uId / @a uSnapshotId. */
     121        virtual void sltSnapshotChanged(const QUuid &uId, const QUuid &uSnapshotId);
     122    /** @} */
     123
     124    /** @name Children stuff.
     125      * @{ */
     126        /** Handles reload machine with certain @a uId request. */
     127        virtual void sltReloadMachine(const QUuid &uId);
     128    /** @} */
     129
     130private slots:
     131
     132    /** @name Group saving stuff.
     133      * @{ */
     134        /** Handles request to start group saving. */
     135        void sltGroupSavingStart();
     136        /** Handles group definition saving complete. */
     137        void sltGroupDefinitionsSaveComplete();
     138        /** Handles group order saving complete. */
     139        void sltGroupOrdersSaveComplete();
     140    /** @} */
     141
     142private:
     143
     144    /** @name Prepare/Cleanup cascade.
     145      * @{ */
     146        /** Prepares all. */
     147        void prepare();
     148        /** Prepares connections. */
     149        void prepareConnections();
     150    /** @} */
     151
     152    /** @name Children stuff.
     153      * @{ */
     154        /** Loads tree. */
     155        void loadTree();
     156        /** Adds machine item based on certain @a comMachine and optionally @a fMakeItVisible. */
     157        void addMachineIntoTheTree(const CMachine &comMachine, bool fMakeItVisible = false);
     158        /** Acquires group node, creates one if necessary.
     159          * @param  strName           Brings the name of group we looking for.
     160          * @param  pParentNode       Brings the parent we starting to look for a group from.
     161          * @param  fAllGroupsOpened  Brings whether we should open all the groups till the required one. */
     162        UIChooserNode *getGroupNode(const QString &strName, UIChooserNode *pParentNode, bool fAllGroupsOpened);
     163        /** Returns whether group with certain @a strName should be opened, searching starting from the passed @a pParentItem. */
     164        bool shouldBeGroupOpened(UIChooserNode *pParentNode, const QString &strName);
     165
     166        /** Wipes out empty groups starting from @a pParentItem. */
     167        void wipeOutEmptyGroups(UIChooserNode *pParentNode);
     168
     169        /** Returns whether global node within the @a pParentNode is favorite. */
     170        bool isGlobalNodeFavorite(UIChooserNode *pParentNode) const;
     171
     172        /** Acquires desired position for a child of @a pParentNode with specified @a enmType and @a strName. */
     173        int getDesiredPosition(UIChooserNode *pParentNode, UIChooserItemType enmType, const QString &strName);
     174        /** Acquires saved position for a child of @a pParentNode with specified @a enmType and @a strName. */
     175        int positionFromDefinitions(UIChooserNode *pParentNode, UIChooserItemType enmType, const QString &strName);
     176
     177        /** Creates machine node based on certain @a comMachine as a child of specified @a pParentNode. */
     178        void createMachineNode(UIChooserNode *pParentNode, const CMachine &comMachine);
     179    /** @} */
     180
     181    /** @name Group saving stuff.
     182      * @{ */
     183        /** Saves group definitions. */
     184        void saveGroupDefinitions();
     185        /** Saves group orders. */
     186        void saveGroupOrders();
     187
     188        /** Gathers group @a definitions of @a pParentGroup. */
     189        void gatherGroupDefinitions(QMap<QString, QStringList> &definitions, UIChooserNode *pParentGroup);
     190        /** Gathers group @a orders of @a pParentGroup. */
     191        void gatherGroupOrders(QMap<QString, QStringList> &orders, UIChooserNode *pParentItem);
     192
     193        /** Makes sure group definitions saving is finished. */
     194        void makeSureGroupDefinitionsSaveIsFinished();
     195        /** Makes sure group orders saving is finished. */
     196        void makeSureGroupOrdersSaveIsFinished();
     197
     198        /** Returns QString representation for passed @a uId, wiping out {} symbols.
     199          * @note  Required for backward compatibility after QString=>QUuid change. */
     200        static QString toOldStyleUuid(const QUuid &uId);
     201    /** @} */
     202
     203    /** @name Children stuff.
     204      * @{ */
     205        /** Holds the invisible root node instance. */
     206        UIChooserNode *m_pInvisibleRootNode;
     207    /** @} */
     208
     209    /** @name Group saving stuff.
     210      * @{ */
     211        /** Holds the consolidated map of group definitions/orders. */
     212        QMap<QString, QStringList>  m_groups;
     213    /** @} */
     214};
     215
     216
     217/** UIChooserAbstractModel extension used as VM Chooser-pane model.
     218  * This class is used to operate on tree of visible tree items
     219  * representing VMs and their groups. */
     220class UIChooserModel : public UIChooserAbstractModel
    60221{
    61222    Q_OBJECT;
     
    86247        /** Notifies about root item minimum width @a iHint changed. */
    87248        void sigRootItemMinimumWidthHintChanged(int iHint);
    88     /** @} */
    89 
    90     /** @name Group saving stuff.
    91       * @{ */
    92         /** Notifies about group saving started. */
    93         void sigGroupSavingStarted();
    94         /** Notifies about group saving state changed. */
    95         void sigGroupSavingStateChanged();
    96249    /** @} */
    97250
     
    203356    /** @name Children stuff.
    204357      * @{ */
    205         /** Returns invisible root node instance. */
    206         UIChooserNode *invisibleRoot() const;
    207 
    208358        /** Returns the root instance. */
    209359        UIChooserItem *root() const;
     
    211361        /** Starts editing group name. */
    212362        void startEditingGroupItemName();
    213 
    214         /** Wipes out empty groups. */
    215         void wipeOutEmptyGroups();
    216363
    217364        /** Activates machine item. */
     
    225372        /** Returns whether looking is in progress. */
    226373        bool isLookupInProgress() const;
    227 
    228         /** Generates unique group name traversing recursively starting from @a pRoot. */
    229         static QString uniqueGroupName(UIChooserItem *pRoot);
    230374    /** @} */
    231375
     
    239383    /** @} */
    240384
    241     /** @name Group saving stuff.
    242       * @{ */
    243         /** Commands to save group settings. */
    244         void saveGroupSettings();
    245         /** Returns whether group saving is in progress. */
    246         bool isGroupSavingInProgress() const;
    247     /** @} */
    248 
    249385public slots:
    250386
     
    263399    /** @} */
    264400
     401protected slots:
     402
     403    /** @name Main event handling stuff.
     404      * @{ */
     405        /** Handles machine registering/unregistering for machine with certain @a uId. */
     406        virtual void sltMachineRegistered(const QUuid &uId, const bool fRegistered) /* override */;
     407    /** @} */
     408
     409    /** @name Children stuff.
     410      * @{ */
     411        /** Handles reload machine with certain @a uId request. */
     412        virtual void sltReloadMachine(const QUuid &uId) /* override */;
     413    /** @} */
     414
    265415private slots:
    266 
    267     /** @name Main event handling stuff.
    268       * @{ */
    269         /** Handles machine @a enmState change for machine with certain @a uId. */
    270         void sltMachineStateChanged(const QUuid &uId, const KMachineState enmState);
    271         /** Handles machine data change for machine with certain @a uId. */
    272         void sltMachineDataChanged(const QUuid &uId);
    273         /** Handles machine registering/unregistering for machine with certain @a uId. */
    274         void sltMachineRegistered(const QUuid &uId, const bool fRegistered);
    275         /** Handles session @a enmState change for machine with certain @a uId. */
    276         void sltSessionStateChanged(const QUuid &uId, const KSessionState enmState);
    277         /** Handles snapshot change for machine/snapshot with certain @a uId / @a uSnapshotId. */
    278         void sltSnapshotChanged(const QUuid &uId, const QUuid &uSnapshotId);
    279     /** @} */
    280416
    281417    /** @name Selection stuff.
     
    300436        /** Handles group selected machines request. */
    301437        void sltGroupSelectedMachines();
    302         /** Handles reload machine with certain @a uId request. */
    303         void sltReloadMachine(const QUuid &uId);
    304438        /** Handles sort parent group request. */
    305439        void sltSortParentGroup();
     
    316450        /** Handles request to erase lookup timer. */
    317451        void sltEraseLookupTimer();
    318     /** @} */
    319 
    320     /** @name Group saving stuff.
    321       * @{ */
    322         /** Handles request to start group saving. */
    323         void sltGroupSavingStart();
    324         /** Handles group definition saving complete. */
    325         void sltGroupDefinitionsSaveComplete();
    326         /** Handles group order saving complete. */
    327         void sltGroupOrdersSaveComplete();
    328452    /** @} */
    329453
     
    385509    /** @name Children stuff.
    386510      * @{ */
    387         /** Loads tree. */
    388         void loadTree();
    389         /** Adds machine item based on certain @a comMachine and optionally @a fMakeItVisible. */
    390         void addMachineIntoTheTree(const CMachine &comMachine, bool fMakeItVisible = false);
    391         /** Acquires group node, creates one if necessary.
    392           * @param  strName           Brings the name of group we looking for.
    393           * @param  pParentNode       Brings the parent we starting to look for a group from.
    394           * @param  fAllGroupsOpened  Brings whether we should open all the groups till the required one. */
    395         UIChooserNode *getGroupNode(const QString &strName, UIChooserNode *pParentNode, bool fAllGroupsOpened);
    396         /** Returns whether group with certain @a strName should be opened, searching starting from the passed @a pParentItem. */
    397         bool shouldBeGroupOpened(UIChooserNode *pParentNode, const QString &strName);
    398 
    399         /** Wipes out empty groups starting from @a pParentItem. */
    400         void wipeOutEmptyGroups(UIChooserNode *pParentNode);
    401 
    402         /** Returns whether global node within the @a pParentNode is favorite. */
    403         bool isGlobalNodeFavorite(UIChooserNode *pParentNode) const;
    404 
    405         /** Acquires desired position for a child of @a pParentNode with specified @a enmType and @a strName. */
    406         int getDesiredPosition(UIChooserNode *pParentNode, UIChooserItemType enmType, const QString &strName);
    407         /** Acquires saved position for a child of @a pParentNode with specified @a enmType and @a strName. */
    408         int positionFromDefinitions(UIChooserNode *pParentNode, UIChooserItemType enmType, const QString &strName);
    409 
    410         /** Creates machine node based on certain @a comMachine as a child of specified @a pParentNode. */
    411         void createMachineNode(UIChooserNode *pParentNode, const CMachine &comMachine);
    412 
    413511        /** Build tree for main root. */
    414512        void buildTreeForMainRoot();
     
    426524        /** Performs sorting for @a pNode. */
    427525        void sortNodes(UIChooserNode *pNode);
    428     /** @} */
    429 
    430     /** @name Group saving stuff.
    431       * @{ */
    432         /** Saves group definitions. */
    433         void saveGroupDefinitions();
    434         /** Saves group orders. */
    435         void saveGroupOrders();
    436 
    437         /** Gathers group @a definitions of @a pParentGroup. */
    438         void gatherGroupDefinitions(QMap<QString, QStringList> &definitions, UIChooserNode *pParentGroup);
    439         /** Gathers group @a orders of @a pParentGroup. */
    440         void gatherGroupOrders(QMap<QString, QStringList> &orders, UIChooserNode *pParentItem);
    441 
    442         /** Makes sure group definitions saving is finished. */
    443         void makeSureGroupDefinitionsSaveIsFinished();
    444         /** Makes sure group orders saving is finished. */
    445         void makeSureGroupOrdersSaveIsFinished();
    446 
    447         /** Returns QString representation for passed @a uId, wiping out {} symbols.
    448           * @note  Required for backward compatibility after QString=>QUuid change. */
    449         static QString toOldStyleUuid(const QUuid &uId);
    450526    /** @} */
    451527
     
    487563    /** @name Children stuff.
    488564      * @{ */
    489         /** Holds the invisible root node instance. */
    490         UIChooserNode  *m_pInvisibleRootNode;
    491 
    492565        /** Holds the root instance. */
    493566        QPointer<UIChooserItem>  m_pRoot;
     
    509582        QString  m_strLookupString;
    510583    /** @} */
    511 
    512     /** @name Group saving stuff.
    513       * @{ */
    514         /** Holds the consolidated map of group definitions/orders. */
    515         QMap<QString, QStringList>  m_groups;
    516     /** @} */
    517584};
    518585
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