VirtualBox

Changeset 86783 in vbox for trunk/src/VBox/Frontends


Ignore:
Timestamp:
Nov 2, 2020 4:50:56 PM (4 years ago)
Author:
vboxsync
Message:

FE/Qt: bugref:9653: VirtualBox Manager: Moving UICloudEntityKey to separate files for reusing possibilities.

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
3 edited
2 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk

    r86774 r86783  
    10581058        src/hostnetwork/UIHostNetworkManager.cpp \
    10591059        src/hostnetwork/UIHostNetworkUtils.cpp \
     1060        src/manager/UICloudEntityKey.cpp \
    10601061        src/manager/UIErrorPane.cpp \
    10611062        src/manager/UITaskCloudGetSettingsForm.cpp \
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/UICloudEntityKey.cpp

    r86768 r86783  
    11/* $Id$ */
    22/** @file
    3  * VBox Qt GUI - UIChooserAbstractModel class implementation.
     3 * VBox Qt GUI - UICloudEntityKey class implementation.
    44 */
    55
     
    1616 */
    1717
    18 /* Qt includes: */
    19 #include <QThread>
     18/* GUI includes: */
     19#include "UICloudEntityKey.h"
    2020
    21 /* GUI includes: */
    22 #include "UICommon.h"
    23 #include "UIChooser.h"
    24 #include "UIChooserAbstractModel.h"
    25 #include "UIChooserNode.h"
    26 #include "UIChooserNodeGroup.h"
    27 #include "UIChooserNodeGlobal.h"
    28 #include "UIChooserNodeMachine.h"
    29 #include "UICloudNetworkingStuff.h"
    30 #include "UIExtraDataManager.h"
    31 #include "UIMessageCenter.h"
    32 #include "UITaskCloudListMachines.h"
    33 #include "UIThreadPool.h"
    34 #include "UIVirtualBoxEventHandler.h"
    35 #include "UIVirtualMachineItemCloud.h"
    36 
    37 /* COM includes: */
    38 #include "CCloudMachine.h"
    39 #include "CCloudProfile.h"
    40 #include "CCloudProvider.h"
    41 #include "CMachine.h"
    42 
    43 /* Type defs: */
    44 typedef QSet<QString> UIStringSet;
    45 
    46 
    47 /** QThread subclass allowing to save group settings asynchronously. */
    48 class UIThreadGroupSettingsSave : public QThread
    49 {
    50     Q_OBJECT;
    51 
    52 signals:
    53 
    54     /** Notifies about machine with certain @a uMachineId to be reloaded. */
    55     void sigReload(const QUuid &uMachineId);
    56 
    57     /** Notifies about task is complete. */
    58     void sigComplete();
    59 
    60 public:
    61 
    62     /** Returns group settings saving thread instance. */
    63     static UIThreadGroupSettingsSave *instance();
    64     /** Prepares group settings saving thread instance. */
    65     static void prepare();
    66     /** Cleanups group settings saving thread instance. */
    67     static void cleanup();
    68 
    69     /** Configures @a group settings saving thread with corresponding @a pListener.
    70       * @param  oldLists  Brings the old settings list to be compared.
    71       * @param  newLists  Brings the new settings list to be saved. */
    72     void configure(QObject *pParent,
    73                    const QMap<QString, QStringList> &oldLists,
    74                    const QMap<QString, QStringList> &newLists);
    75 
    76 protected:
    77 
    78     /** Constructs group settings saving thread. */
    79     UIThreadGroupSettingsSave();
    80     /** Destructs group settings saving thread. */
    81     virtual ~UIThreadGroupSettingsSave() /* override */;
    82 
    83     /** Contains a thread task to be executed. */
    84     virtual void run() /* override */;
    85 
    86     /** Holds the singleton instance. */
    87     static UIThreadGroupSettingsSave *s_pInstance;
    88 
    89     /** Holds the map of group settings to be compared. */
    90     QMap<QString, QStringList> m_oldLists;
    91     /** Holds the map of group settings to be saved. */
    92     QMap<QString, QStringList> m_newLists;
    93 };
    94 
    95 
    96 /** QThread subclass allowing to save group definitions asynchronously. */
    97 class UIThreadGroupDefinitionsSave : public QThread
    98 {
    99     Q_OBJECT;
    100 
    101 signals:
    102 
    103     /** Notifies about task is complete. */
    104     void sigComplete();
    105 
    106 public:
    107 
    108     /** Returns group definitions saving thread instance. */
    109     static UIThreadGroupDefinitionsSave *instance();
    110     /** Prepares group definitions saving thread instance. */
    111     static void prepare();
    112     /** Cleanups group definitions saving thread instance. */
    113     static void cleanup();
    114 
    115     /** Configures group definitions saving thread with corresponding @a pListener.
    116       * @param  lists  Brings definitions lists to be saved. */
    117     void configure(QObject *pListener,
    118                    const QMap<QString, QStringList> &lists);
    119 
    120 protected:
    121 
    122     /** Constructs group definitions saving thread. */
    123     UIThreadGroupDefinitionsSave();
    124     /** Destructs group definitions saving thread. */
    125     virtual ~UIThreadGroupDefinitionsSave() /* override */;
    126 
    127     /** Contains a thread task to be executed. */
    128     virtual void run() /* override */;
    129 
    130     /** Holds the singleton instance. */
    131     static UIThreadGroupDefinitionsSave *s_pInstance;
    132 
    133     /** Holds the map of group definitions to be saved. */
    134     QMap<QString, QStringList>  m_lists;
    135 };
    136 
    137 
    138 /*********************************************************************************************************************************
    139 *   Class UIThreadGroupSettingsSave implementation.                                                                              *
    140 *********************************************************************************************************************************/
    141 
    142 /* static */
    143 UIThreadGroupSettingsSave *UIThreadGroupSettingsSave::s_pInstance = 0;
    144 
    145 /* static */
    146 UIThreadGroupSettingsSave *UIThreadGroupSettingsSave::instance()
    147 {
    148     return s_pInstance;
    149 }
    150 
    151 /* static */
    152 void UIThreadGroupSettingsSave::prepare()
    153 {
    154     /* Make sure instance is not prepared: */
    155     if (s_pInstance)
    156         return;
    157 
    158     /* Crate instance: */
    159     new UIThreadGroupSettingsSave;
    160 }
    161 
    162 /* static */
    163 void UIThreadGroupSettingsSave::cleanup()
    164 {
    165     /* Make sure instance is prepared: */
    166     if (!s_pInstance)
    167         return;
    168 
    169     /* Delete instance: */
    170     delete s_pInstance;
    171 }
    172 
    173 void UIThreadGroupSettingsSave::configure(QObject *pParent,
    174                                           const QMap<QString, QStringList> &oldLists,
    175                                           const QMap<QString, QStringList> &newLists)
    176 {
    177     m_oldLists = oldLists;
    178     m_newLists = newLists;
    179     UIChooserAbstractModel *pChooserAbstractModel = qobject_cast<UIChooserAbstractModel*>(pParent);
    180     AssertPtrReturnVoid(pChooserAbstractModel);
    181     {
    182         connect(this, &UIThreadGroupSettingsSave::sigComplete,
    183                 pChooserAbstractModel, &UIChooserAbstractModel::sltGroupSettingsSaveComplete);
    184     }
    185 }
    186 
    187 UIThreadGroupSettingsSave::UIThreadGroupSettingsSave()
    188 {
    189     /* Assign instance: */
    190     s_pInstance = this;
    191 }
    192 
    193 UIThreadGroupSettingsSave::~UIThreadGroupSettingsSave()
    194 {
    195     /* Make sure thread work is complete: */
    196     wait();
    197 
    198     /* Erase instance: */
    199     s_pInstance = 0;
    200 }
    201 
    202 void UIThreadGroupSettingsSave::run()
    203 {
    204     /* COM prepare: */
    205     COMBase::InitializeCOM(false);
    206 
    207     /* For every particular machine ID: */
    208     foreach (const QString &strId, m_newLists.keys())
    209     {
    210         /* Get new group list/set: */
    211         const QStringList &newGroupList = m_newLists.value(strId);
    212         const UIStringSet &newGroupSet = UIStringSet::fromList(newGroupList);
    213         /* Get old group list/set: */
    214         const QStringList &oldGroupList = m_oldLists.value(strId);
    215         const UIStringSet &oldGroupSet = UIStringSet::fromList(oldGroupList);
    216         /* Make sure group set changed: */
    217         if (newGroupSet == oldGroupSet)
    218             continue;
    219 
    220         /* The next steps are subsequent.
    221          * Every of them is mandatory in order to continue
    222          * with common cleanup in case of failure.
    223          * We have to simulate a try-catch block. */
    224         CSession comSession;
    225         CMachine comMachine;
    226         do
    227         {
    228             /* 1. Open session: */
    229             comSession = uiCommon().openSession(QUuid(strId));
    230             if (comSession.isNull())
    231                 break;
    232 
    233             /* 2. Get session machine: */
    234             comMachine = comSession.GetMachine();
    235             if (comMachine.isNull())
    236                 break;
    237 
    238             /* 3. Set new groups: */
    239             comMachine.SetGroups(newGroupList.toVector());
    240             if (!comMachine.isOk())
    241             {
    242                 msgCenter().cannotSetGroups(comMachine);
    243                 break;
    244             }
    245 
    246             /* 4. Save settings: */
    247             comMachine.SaveSettings();
    248             if (!comMachine.isOk())
    249             {
    250                 msgCenter().cannotSaveMachineSettings(comMachine);
    251                 break;
    252             }
    253         } while (0);
    254 
    255         /* Cleanup if necessary: */
    256         if (comMachine.isNull() || !comMachine.isOk())
    257             emit sigReload(QUuid(strId));
    258         if (!comSession.isNull())
    259             comSession.UnlockMachine();
    260     }
    261 
    262     /* Notify listeners about completeness: */
    263     emit sigComplete();
    264 
    265     /* COM cleanup: */
    266     COMBase::CleanupCOM();
    267 }
    268 
    269 
    270 /*********************************************************************************************************************************
    271 *   Class UIThreadGroupDefinitionsSave implementation.                                                                           *
    272 *********************************************************************************************************************************/
    273 
    274 /* static */
    275 UIThreadGroupDefinitionsSave *UIThreadGroupDefinitionsSave::s_pInstance = 0;
    276 
    277 /* static */
    278 UIThreadGroupDefinitionsSave *UIThreadGroupDefinitionsSave::instance()
    279 {
    280     return s_pInstance;
    281 }
    282 
    283 /* static */
    284 void UIThreadGroupDefinitionsSave::prepare()
    285 {
    286     /* Make sure instance is not prepared: */
    287     if (s_pInstance)
    288         return;
    289 
    290     /* Crate instance: */
    291     new UIThreadGroupDefinitionsSave;
    292 }
    293 
    294 /* static */
    295 void UIThreadGroupDefinitionsSave::cleanup()
    296 {
    297     /* Make sure instance is prepared: */
    298     if (!s_pInstance)
    299         return;
    300 
    301     /* Delete instance: */
    302     delete s_pInstance;
    303 }
    304 
    305 void UIThreadGroupDefinitionsSave::configure(QObject *pParent,
    306                                              const QMap<QString, QStringList> &groups)
    307 {
    308     m_lists = groups;
    309     UIChooserAbstractModel *pChooserAbstractModel = qobject_cast<UIChooserAbstractModel*>(pParent);
    310     AssertPtrReturnVoid(pChooserAbstractModel);
    311     {
    312         connect(this, &UIThreadGroupDefinitionsSave::sigComplete,
    313                 pChooserAbstractModel, &UIChooserAbstractModel::sltGroupDefinitionsSaveComplete);
    314     }
    315 }
    316 
    317 UIThreadGroupDefinitionsSave::UIThreadGroupDefinitionsSave()
    318 {
    319     /* Assign instance: */
    320     s_pInstance = this;
    321 }
    322 
    323 UIThreadGroupDefinitionsSave::~UIThreadGroupDefinitionsSave()
    324 {
    325     /* Make sure thread work is complete: */
    326     wait();
    327 
    328     /* Erase instance: */
    329     s_pInstance = 0;
    330 }
    331 
    332 void UIThreadGroupDefinitionsSave::run()
    333 {
    334     /* COM prepare: */
    335     COMBase::InitializeCOM(false);
    336 
    337     /* Clear all the extra-data records related to group definitions: */
    338     gEDataManager->clearSelectorWindowGroupsDefinitions();
    339     /* For every particular group definition: */
    340     foreach (const QString &strId, m_lists.keys())
    341         gEDataManager->setSelectorWindowGroupsDefinitions(strId, m_lists.value(strId));
    342 
    343     /* Notify listeners about completeness: */
    344     emit sigComplete();
    345 
    346     /* COM cleanup: */
    347     COMBase::CleanupCOM();
    348 }
    349 
    350 
    351 /*********************************************************************************************************************************
    352 *   Class UICloudEntityKey implementation.                                                                                       *
    353 *********************************************************************************************************************************/
    35421
    35522UICloudEntityKey::UICloudEntityKey(const QString &strProviderShortName /* = QString() */,
     
    39259    return strResult;
    39360}
    394 
    395 
    396 /*********************************************************************************************************************************
    397 *   Class UIChooserAbstractModel implementation.                                                                                 *
    398 *********************************************************************************************************************************/
    399 
    400 UIChooserAbstractModel:: UIChooserAbstractModel(UIChooser *pParent)
    401     : QObject(pParent)
    402     , m_pParent(pParent)
    403     , m_pInvisibleRootNode(0)
    404 {
    405     prepare();
    406 }
    407 
    408 void UIChooserAbstractModel::init()
    409 {
    410     /* Create invisible root group node: */
    411     m_pInvisibleRootNode = new UIChooserNodeGroup(0 /* parent */,
    412                                                   0 /* position */,
    413                                                   QUuid() /* id */,
    414                                                   QString() /* name */,
    415                                                   UIChooserNodeGroupType_Local,
    416                                                   true /* opened */);
    417     if (invisibleRoot())
    418     {
    419         /* Link root to this model: */
    420         invisibleRoot()->setModel(this);
    421 
    422         /* Create global node: */
    423         new UIChooserNodeGlobal(invisibleRoot() /* parent */,
    424                                 0 /* position */,
    425                                 shouldGlobalNodeBeFavorite(invisibleRoot()),
    426                                 QString() /* tip */);
    427 
    428         /* Reload local tree: */
    429         reloadLocalTree();
    430         /* Reload cloud tree: */
    431         reloadCloudTree();
    432     }
    433 }
    434 
    435 void UIChooserAbstractModel::deinit()
    436 {
    437     // WORKAROUND:
    438     // Currently we are not saving group descriptors
    439     // (which reflecting group toggle-state) on-the-fly,
    440     // so for now we are additionally save group definitions
    441     // when exiting application:
    442     saveGroupDefinitions();
    443 
    444     /* Make sure all saving steps complete: */
    445     makeSureGroupSettingsSaveIsFinished();
    446     makeSureGroupDefinitionsSaveIsFinished();
    447 
    448     /* Delete tree: */
    449     delete m_pInvisibleRootNode;
    450     m_pInvisibleRootNode = 0;
    451 }
    452 
    453 void UIChooserAbstractModel::wipeOutEmptyGroups()
    454 {
    455     wipeOutEmptyGroupsStartingFrom(invisibleRoot());
    456 }
    457 
    458 QStringList UIChooserAbstractModel::possibleGroupNodeNamesForMachineNodeToMove(const QUuid &uId)
    459 {
    460     /* Search for all the machine nodes with passed ID: */
    461     QList<UIChooserNode*> machineNodes;
    462     invisibleRoot()->searchForNodes(uId.toString(),
    463                                     UIChooserItemSearchFlag_Machine | UIChooserItemSearchFlag_ExactId,
    464                                     machineNodes);
    465 
    466     /* Return group nodes starting from root one: */
    467     return gatherPossibleGroupNodeNames(invisibleRoot(), machineNodes);
    468 }
    469 
    470 QStringList UIChooserAbstractModel::possibleGroupNodeNamesForGroupNodeToMove(const QString &strFullName)
    471 {
    472     /* Search for all the group nodes with passed full-name: */
    473     QList<UIChooserNode*> groupNodes;
    474     invisibleRoot()->searchForNodes(strFullName,
    475                                     UIChooserItemSearchFlag_LocalGroup | UIChooserItemSearchFlag_FullName,
    476                                     groupNodes);
    477 
    478     /* Return group nodes starting from root one: */
    479     return gatherPossibleGroupNodeNames(invisibleRoot(), groupNodes);
    480 }
    481 
    482 /* static */
    483 QString UIChooserAbstractModel::uniqueGroupName(UIChooserNode *pRoot)
    484 {
    485     /* Enumerate all the group names: */
    486     QStringList groupNames;
    487     foreach (UIChooserNode *pNode, pRoot->nodes(UIChooserNodeType_Group))
    488         groupNames << pNode->name();
    489 
    490     /* Prepare reg-exp: */
    491     const QString strMinimumName = tr("New group");
    492     const QString strShortTemplate = strMinimumName;
    493     const QString strFullTemplate = strShortTemplate + QString(" (\\d+)");
    494     const QRegExp shortRegExp(strShortTemplate);
    495     const QRegExp fullRegExp(strFullTemplate);
    496 
    497     /* Search for the maximum index: */
    498     int iMinimumPossibleNumber = 0;
    499     foreach (const QString &strName, groupNames)
    500     {
    501         if (shortRegExp.exactMatch(strName))
    502             iMinimumPossibleNumber = qMax(iMinimumPossibleNumber, 2);
    503         else if (fullRegExp.exactMatch(strName))
    504             iMinimumPossibleNumber = qMax(iMinimumPossibleNumber, fullRegExp.cap(1).toInt() + 1);
    505     }
    506 
    507     /* Prepare/return result: */
    508     QString strResult = strMinimumName;
    509     if (iMinimumPossibleNumber)
    510         strResult += " " + QString::number(iMinimumPossibleNumber);
    511     return strResult;
    512 }
    513 
    514 void UIChooserAbstractModel::performSearch(const QString &strSearchTerm, int iSearchFlags)
    515 {
    516     /* Make sure invisible root exists: */
    517     AssertPtrReturnVoid(invisibleRoot());
    518 
    519     /* Currently we perform the search only for machines, when this to be changed make
    520      * sure the disabled flags of the other item types are also managed correctly. */
    521 
    522     /* Reset the search first to erase the disabled flag,
    523      * this also returns a full list of all machine nodes: */
    524     const QList<UIChooserNode*> nodes = resetSearch();
    525 
    526     /* Stop here if no search conditions specified: */
    527     if (strSearchTerm.isEmpty())
    528         return;
    529 
    530     /* Search for all the nodes matching required condition: */
    531     invisibleRoot()->searchForNodes(strSearchTerm, iSearchFlags, m_searchResults);
    532 
    533     /* Assign/reset the disabled flag for required nodes: */
    534     foreach (UIChooserNode *pNode, nodes)
    535     {
    536         AssertPtrReturnVoid(pNode);
    537         pNode->setDisabled(!m_searchResults.contains(pNode));
    538     }
    539 }
    540 
    541 QList<UIChooserNode*> UIChooserAbstractModel::resetSearch()
    542 {
    543     /* Prepare resulting nodes: */
    544     QList<UIChooserNode*> nodes;
    545 
    546     /* Make sure invisible root exists: */
    547     AssertPtrReturn(invisibleRoot(), nodes);
    548 
    549     /* Calling UIChooserNode::searchForNodes with an empty search term
    550      * returns a list all nodes (of the whole tree) of the required type: */
    551     invisibleRoot()->searchForNodes(QString(), UIChooserItemSearchFlag_Machine, nodes);
    552 
    553     /* Reset the disabled flag of the nodes first: */
    554     foreach (UIChooserNode *pNode, nodes)
    555     {
    556         AssertPtrReturn(pNode, nodes);
    557         pNode->setDisabled(false);
    558     }
    559 
    560     /* Reset the search result related data: */
    561     m_searchResults.clear();
    562 
    563     /* Return nodes: */
    564     return nodes;
    565 }
    566 
    567 QList<UIChooserNode*> UIChooserAbstractModel::searchResult() const
    568 {
    569     return m_searchResults;
    570 }
    571 
    572 void UIChooserAbstractModel::saveGroups()
    573 {
    574     emit sigStartGroupSaving();
    575 }
    576 
    577 bool UIChooserAbstractModel::isGroupSavingInProgress() const
    578 {
    579     return    UIThreadGroupSettingsSave::instance()
    580            || UIThreadGroupDefinitionsSave::instance();
    581 }
    582 
    583 /* static */
    584 QString UIChooserAbstractModel::toOldStyleUuid(const QUuid &uId)
    585 {
    586     return uId.toString().remove(QRegExp("[{}]"));
    587 }
    588 
    589 /* static */
    590 QString UIChooserAbstractModel::prefixToString(UIChooserNodeDataPrefixType enmType)
    591 {
    592     switch (enmType)
    593     {
    594         /* Global nodes: */
    595         case UIChooserNodeDataPrefixType_Global:   return "n";
    596         /* Machine nodes: */
    597         case UIChooserNodeDataPrefixType_Machine:  return "m";
    598         /* Group nodes: */
    599         case UIChooserNodeDataPrefixType_Local:    return "g";
    600         case UIChooserNodeDataPrefixType_Provider: return "p";
    601         case UIChooserNodeDataPrefixType_Profile:  return "a";
    602     }
    603     return QString();
    604 }
    605 
    606 /* static */
    607 QString UIChooserAbstractModel::optionToString(UIChooserNodeDataOptionType enmType)
    608 {
    609     switch (enmType)
    610     {
    611         /* Global nodes: */
    612         case UIChooserNodeDataOptionType_GlobalFavorite: return "f";
    613         /* Group nodes: */
    614         case UIChooserNodeDataOptionType_GroupOpened:    return "o";
    615     }
    616     return QString();
    617 }
    618 
    619 /* static */
    620 QString UIChooserAbstractModel::valueToString(UIChooserNodeDataValueType enmType)
    621 {
    622     switch (enmType)
    623     {
    624         /* Global nodes: */
    625         case UIChooserNodeDataValueType_GlobalDefault: return "GLOBAL";
    626     }
    627     return QString();
    628 }
    629 
    630 void UIChooserAbstractModel::insertCloudEntityKey(const UICloudEntityKey &key)
    631 {
    632 //    printf("Cloud entity with key %s being updated..\n", key.toString().toUtf8().constData());
    633     m_cloudEntityKeysBeingUpdated.insert(key);
    634     emit sigCloudUpdateStateChanged();
    635 }
    636 
    637 void UIChooserAbstractModel::removeCloudEntityKey(const UICloudEntityKey &key)
    638 {
    639 //    printf("Cloud entity with key %s is updated!\n", key.toString().toUtf8().constData());
    640     m_cloudEntityKeysBeingUpdated.remove(key);
    641     emit sigCloudUpdateStateChanged();
    642 }
    643 
    644 bool UIChooserAbstractModel::containsCloudEntityKey(const UICloudEntityKey &key) const
    645 {
    646     return m_cloudEntityKeysBeingUpdated.contains(key);
    647 }
    648 
    649 bool UIChooserAbstractModel::isCloudProfileUpdateInProgress() const
    650 {
    651     /* Compose RE for profile: */
    652     QRegExp re("^/[^/]+/[^/]+$");
    653     /* Check whether keys match profile RE: */
    654     foreach (const UICloudEntityKey &key, m_cloudEntityKeysBeingUpdated)
    655     {
    656         const int iIndex = re.indexIn(key.toString());
    657         if (iIndex != -1)
    658             return true;
    659     }
    660     /* False by default: */
    661     return false;
    662 }
    663 
    664 void UIChooserAbstractModel::sltHandleCloudMachineRefreshStarted()
    665 {
    666     /* Acquire sender: */
    667     UIVirtualMachineItem *pCache = qobject_cast<UIVirtualMachineItem*>(sender());
    668     AssertPtrReturnVoid(pCache);
    669 
    670     /* Acquire sender's ID: */
    671     const QUuid uId = pCache->id();
    672 
    673     /* Search for a first machine node with passed ID: */
    674     UIChooserNode *pMachineNode = searchMachineNode(invisibleRoot(), uId);
    675 
    676     /* Insert cloud entity key into a list of keys currently being updated: */
    677     const UICloudEntityKey cloudEntityKey = UICloudEntityKey(pMachineNode->parentNode()->parentNode()->name(),
    678                                                              pMachineNode->parentNode()->name(),
    679                                                              pMachineNode->toMachineNode()->id());
    680     insertCloudEntityKey(cloudEntityKey);
    681 }
    682 
    683 void UIChooserAbstractModel::sltHandleCloudMachineRefreshFinished()
    684 {
    685     /* Acquire sender: */
    686     UIVirtualMachineItem *pCache = qobject_cast<UIVirtualMachineItem*>(sender());
    687     AssertPtrReturnVoid(pCache);
    688 
    689     /* Acquire sender's ID: */
    690     const QUuid uId = pCache->id();
    691 
    692     /* Search for a first machine node with passed ID: */
    693     UIChooserNode *pMachineNode = searchMachineNode(invisibleRoot(), uId);
    694 
    695     /* Remove cloud entity key from the list of keys currently being updated: */
    696     const UICloudEntityKey cloudEntityKey = UICloudEntityKey(pMachineNode->parentNode()->parentNode()->name(),
    697                                                              pMachineNode->parentNode()->name(),
    698                                                              pMachineNode->toMachineNode()->id());
    699     removeCloudEntityKey(cloudEntityKey);
    700 
    701     /* Notify listeners: */
    702     emit sigCloudMachineStateChange(uId);
    703 }
    704 
    705 void UIChooserAbstractModel::sltGroupSettingsSaveComplete()
    706 {
    707     makeSureGroupSettingsSaveIsFinished();
    708     emit sigGroupSavingStateChanged();
    709 }
    710 
    711 void UIChooserAbstractModel::sltGroupDefinitionsSaveComplete()
    712 {
    713     makeSureGroupDefinitionsSaveIsFinished();
    714     emit sigGroupSavingStateChanged();
    715 }
    716 
    717 void UIChooserAbstractModel::sltLocalMachineStateChanged(const QUuid &uMachineId, const KMachineState)
    718 {
    719     /* Update machine-nodes with passed id: */
    720     invisibleRoot()->updateAllNodes(uMachineId);
    721 }
    722 
    723 void UIChooserAbstractModel::sltLocalMachineDataChanged(const QUuid &uMachineId)
    724 {
    725     /* Update machine-nodes with passed id: */
    726     invisibleRoot()->updateAllNodes(uMachineId);
    727 }
    728 
    729 void UIChooserAbstractModel::sltLocalMachineRegistrationChanged(const QUuid &uMachineId, const bool fRegistered)
    730 {
    731     /* Existing VM unregistered? */
    732     if (!fRegistered)
    733     {
    734         /* Remove machine-items with passed id: */
    735         invisibleRoot()->removeAllNodes(uMachineId);
    736         /* Wipe out empty groups: */
    737         wipeOutEmptyGroups();
    738     }
    739     /* New VM registered? */
    740     else
    741     {
    742         /* Should we show this VM? */
    743         if (gEDataManager->showMachineInVirtualBoxManagerChooser(uMachineId))
    744         {
    745             /* Add new machine-item: */
    746             const CMachine comMachine = uiCommon().virtualBox().FindMachine(uMachineId.toString());
    747             addLocalMachineIntoTheTree(comMachine, true /* make it visible */);
    748         }
    749     }
    750 }
    751 
    752 void UIChooserAbstractModel::sltSessionStateChanged(const QUuid &uMachineId, const KSessionState)
    753 {
    754     /* Update machine-nodes with passed id: */
    755     invisibleRoot()->updateAllNodes(uMachineId);
    756 }
    757 
    758 void UIChooserAbstractModel::sltSnapshotChanged(const QUuid &uMachineId, const QUuid &)
    759 {
    760     /* Update machine-nodes with passed id: */
    761     invisibleRoot()->updateAllNodes(uMachineId);
    762 }
    763 
    764 void UIChooserAbstractModel::sltHandleCloudProviderUninstall(const QUuid &uProviderId)
    765 {
    766     /* We should stop cloud machine updates currently being performed: */
    767     foreach (const UICloudEntityKey &key, m_cloudEntityKeysBeingUpdated)
    768     {
    769         /* Skip unrelated keys: */
    770         if (key.m_uMachineId.isNull())
    771             continue;
    772 
    773         /* Search machine node: */
    774         UIChooserNode *pNode = searchMachineNode(key.m_strProviderShortName, key.m_strProfileName, key.m_uMachineId);
    775         AssertPtrReturnVoid(pNode);
    776         /* Acquire cloud machine item: */
    777         UIVirtualMachineItemCloud *pCloudMachineItem = pNode->toMachineNode()->cache()->toCloud();
    778         AssertPtrReturnVoid(pCloudMachineItem);
    779 
    780         /* Wait for cloud machine refresh task to complete: */
    781         pCloudMachineItem->waitForAsyncInfoUpdateFinished();
    782     }
    783 
    784     /* Search and delete corresponding cloud provider node if present: */
    785     delete searchProviderNode(uProviderId);
    786 }
    787 
    788 void UIChooserAbstractModel::sltReloadMachine(const QUuid &uMachineId)
    789 {
    790     /* Remove machine-items with passed id: */
    791     invisibleRoot()->removeAllNodes(uMachineId);
    792     /* Wipe out empty groups: */
    793     wipeOutEmptyGroups();
    794 
    795     /* Should we show this VM? */
    796     if (gEDataManager->showMachineInVirtualBoxManagerChooser(uMachineId))
    797     {
    798         /* Add new machine-item: */
    799         const CMachine comMachine = uiCommon().virtualBox().FindMachine(uMachineId.toString());
    800         addLocalMachineIntoTheTree(comMachine, true /* make it visible */);
    801     }
    802 }
    803 
    804 void UIChooserAbstractModel::sltStartGroupSaving()
    805 {
    806     saveGroupSettings();
    807     saveGroupDefinitions();
    808 }
    809 
    810 void UIChooserAbstractModel::sltCloudMachineUnregistered(const QString &strProviderShortName,
    811                                                          const QString &strProfileName,
    812                                                          const QUuid &uId)
    813 {
    814     /* Search for profile node: */
    815     UIChooserNode *pProfileNode = searchProfileNode(strProviderShortName, strProfileName);
    816     if (!pProfileNode)
    817         return;
    818 
    819     /* Remove machine-item with passed uId: */
    820     pProfileNode->removeAllNodes(uId);
    821 
    822     /* If there are no items left => add fake cloud VM node: */
    823     if (pProfileNode->nodes(UIChooserNodeType_Machine).isEmpty())
    824         createCloudMachineNode(pProfileNode, UIFakeCloudVirtualMachineItemState_Done);
    825 }
    826 
    827 void UIChooserAbstractModel::sltCloudMachinesUnregistered(const QString &strProviderShortName,
    828                                                           const QString &strProfileName,
    829                                                           const QList<QUuid> &ids)
    830 {
    831     /* Search for profile node: */
    832     UIChooserNode *pProfileNode = searchProfileNode(strProviderShortName, strProfileName);
    833     if (!pProfileNode)
    834         return;
    835 
    836     /* Remove machine-items with passed id: */
    837     foreach (const QUuid &uId, ids)
    838         pProfileNode->removeAllNodes(uId);
    839 
    840     /* If there are no items left => add fake cloud VM node: */
    841     if (pProfileNode->nodes(UIChooserNodeType_Machine).isEmpty())
    842         createCloudMachineNode(pProfileNode, UIFakeCloudVirtualMachineItemState_Done);
    843 }
    844 
    845 void UIChooserAbstractModel::sltCloudMachineRegistered(const QString &strProviderShortName,
    846                                                        const QString &strProfileName,
    847                                                        const CCloudMachine &comMachine)
    848 {
    849     /* Search for profile node: */
    850     UIChooserNode *pProfileNode = searchProfileNode(strProviderShortName, strProfileName);
    851     if (!pProfileNode)
    852         return;
    853 
    854     /* Compose corresponding group path: */
    855     const QString strGroup = QString("/%1/%2").arg(strProviderShortName, strProfileName);
    856     /* Make sure there is no VM with such ID already: */
    857     QUuid uId;
    858     if (!cloudMachineId(comMachine, uId))
    859         return;
    860     if (checkIfNodeContainChildWithId(pProfileNode, uId))
    861         return;
    862     /* Add new machine-item: */
    863     addCloudMachineIntoTheTree(strGroup, comMachine, true /* make it visible? */);
    864 
    865     /* Delete fake node if present: */
    866     delete searchFakeNode(pProfileNode);
    867 }
    868 
    869 void UIChooserAbstractModel::sltCloudMachinesRegistered(const QString &strProviderShortName,
    870                                                         const QString &strProfileName,
    871                                                         const QVector<CCloudMachine> &machines)
    872 {
    873     /* Search for profile node: */
    874     UIChooserNode *pProfileNode = searchProfileNode(strProviderShortName, strProfileName);
    875     if (!pProfileNode)
    876         return;
    877 
    878     /* Compose corresponding group path: */
    879     const QString strGroup = QString("/%1/%2").arg(strProviderShortName, strProfileName);
    880     foreach (const CCloudMachine &comMachine, machines)
    881     {
    882         /* Make sure there is no VM with such ID already: */
    883         QUuid uId;
    884         if (!cloudMachineId(comMachine, uId))
    885             continue;
    886         if (checkIfNodeContainChildWithId(pProfileNode, uId))
    887             continue;
    888         /* Add new machine-item: */
    889         addCloudMachineIntoTheTree(strGroup, comMachine, false /* make it visible? */);
    890     }
    891 
    892     /* Delete fake node if present: */
    893     delete searchFakeNode(pProfileNode);
    894 }
    895 
    896 void UIChooserAbstractModel::sltHandleCloudListMachinesTaskComplete(UITask *pTask)
    897 {
    898     /* Skip unrelated tasks: */
    899     AssertPtrReturnVoid(pTask);
    900     if (pTask->type() != UITask::Type_CloudListMachines)
    901         return;
    902     UITaskCloudListMachines *pAcquiringTask = qobject_cast<UITaskCloudListMachines*>(pTask);
    903     AssertPtrReturnVoid(pAcquiringTask);
    904     const QString strProviderShortName = pAcquiringTask->providerShortName();
    905     const QString strProfileName = pAcquiringTask->profileName();
    906 
    907     /* Search for profile node: */
    908     UIChooserNode *pProfileNode = searchProfileNode(strProviderShortName, strProfileName);
    909     if (!pProfileNode)
    910         return;
    911 
    912     /* Compose old set of machine IDs: */
    913     QSet<QUuid> oldIDs;
    914     foreach (UIChooserNode *pNode, pProfileNode->nodes(UIChooserNodeType_Machine))
    915     {
    916         AssertPtrReturnVoid(pNode);
    917         UIChooserNodeMachine *pNodeMachine = pNode->toMachineNode();
    918         AssertPtrReturnVoid(pNodeMachine);
    919         if (pNodeMachine->cacheType() != UIVirtualMachineItemType_CloudReal)
    920             continue;
    921         oldIDs << pNodeMachine->id();
    922     }
    923     /* Compose new set of machine IDs and map of machines: */
    924     QSet<QUuid> newIDs;
    925     QMap<QUuid, CCloudMachine> newMachines;
    926     foreach (const CCloudMachine &comMachine, pAcquiringTask->result())
    927     {
    928         QUuid uId;
    929         AssertReturnVoid(cloudMachineId(comMachine, uId));
    930         newMachines[uId] = comMachine;
    931         newIDs << uId;
    932     }
    933 
    934     /* Calculate set of unregistered/registered IDs: */
    935     const QSet<QUuid> unregisteredIDs = oldIDs - newIDs;
    936     const QSet<QUuid> registeredIDs = newIDs - oldIDs;
    937     QVector<CCloudMachine> registeredMachines;
    938     foreach (const QUuid &uId, registeredIDs)
    939         registeredMachines << newMachines.value(uId);
    940 
    941     /* Remove unregistered cloud VM nodes: */
    942     if (!unregisteredIDs.isEmpty())
    943         sltCloudMachinesUnregistered(strProviderShortName, strProfileName, unregisteredIDs.toList());
    944     /* Add registered cloud VM nodes: */
    945     if (!registeredMachines.isEmpty())
    946         sltCloudMachinesRegistered(strProviderShortName, strProfileName, registeredMachines);
    947     /* If we changed nothing and have nothing currently: */
    948     if (unregisteredIDs.isEmpty() && newIDs.isEmpty())
    949     {
    950         /* We should update at least fake cloud machine node: */
    951         UIChooserNode *pFakeNode = searchFakeNode(pProfileNode);
    952         AssertPtrReturnVoid(pFakeNode);
    953         pFakeNode->toMachineNode()->cache()->toCloud()->setFakeCloudItemState(UIFakeCloudVirtualMachineItemState_Done);
    954         pFakeNode->item()->updateItem();
    955     }
    956 
    957     /* Remove cloud entity key from the list of keys currently being updated: */
    958     const UICloudEntityKey cloudEntityKey = UICloudEntityKey(strProviderShortName, strProfileName);
    959     removeCloudEntityKey(cloudEntityKey);
    960 }
    961 
    962 void UIChooserAbstractModel::sltHandleCloudProfileManagerCumulativeChange()
    963 {
    964     /* Reload cloud tree: */
    965     reloadCloudTree();
    966 }
    967 
    968 void UIChooserAbstractModel::prepare()
    969 {
    970     prepareConnections();
    971 }
    972 
    973 void UIChooserAbstractModel::prepareConnections()
    974 {
    975     /* Cloud thread-pool connections: */
    976     connect(uiCommon().threadPoolCloud(), &UIThreadPool::sigTaskComplete,
    977             this, &UIChooserAbstractModel::sltHandleCloudListMachinesTaskComplete);
    978 
    979     /* Cloud VM registration connections: */
    980     connect(&uiCommon(), &UICommon::sigCloudMachineUnregistered,
    981             this, &UIChooserAbstractModel::sltCloudMachineUnregistered);
    982     connect(&uiCommon(), &UICommon::sigCloudMachineRegistered,
    983             this, &UIChooserAbstractModel::sltCloudMachineRegistered);
    984 
    985     /* Setup global connections: */
    986     connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigMachineStateChange,
    987             this, &UIChooserAbstractModel::sltLocalMachineStateChanged);
    988     connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigMachineDataChange,
    989             this, &UIChooserAbstractModel::sltLocalMachineDataChanged);
    990     connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigMachineRegistered,
    991             this, &UIChooserAbstractModel::sltLocalMachineRegistrationChanged);
    992     connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigSessionStateChange,
    993             this, &UIChooserAbstractModel::sltSessionStateChanged);
    994     connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigSnapshotTake,
    995             this, &UIChooserAbstractModel::sltSnapshotChanged);
    996     connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigSnapshotDelete,
    997             this, &UIChooserAbstractModel::sltSnapshotChanged);
    998     connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigSnapshotChange,
    999             this, &UIChooserAbstractModel::sltSnapshotChanged);
    1000     connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigSnapshotRestore,
    1001             this, &UIChooserAbstractModel::sltSnapshotChanged);
    1002     connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigCloudProviderListChanged,
    1003             this, &UIChooserAbstractModel::sltHandleCloudProfileManagerCumulativeChange);
    1004     connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigCloudProfileRegistered,
    1005             this, &UIChooserAbstractModel::sltHandleCloudProfileManagerCumulativeChange);
    1006     connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigCloudProfileChanged,
    1007             this, &UIChooserAbstractModel::sltHandleCloudProfileManagerCumulativeChange);
    1008     connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigCloudProviderUninstall,
    1009             this, &UIChooserAbstractModel::sltHandleCloudProviderUninstall);
    1010 
    1011     /* Setup group saving connections: */
    1012     connect(this, &UIChooserAbstractModel::sigStartGroupSaving,
    1013             this, &UIChooserAbstractModel::sltStartGroupSaving,
    1014             Qt::QueuedConnection);
    1015 
    1016     /* Setup extra-data connections: */
    1017     connect(gEDataManager, &UIExtraDataManager::sigCloudProfileManagerRestrictionChange,
    1018             this, &UIChooserAbstractModel::sltHandleCloudProfileManagerCumulativeChange);
    1019 }
    1020 
    1021 void UIChooserAbstractModel::reloadLocalTree()
    1022 {
    1023     LogRelFlow(("UIChooserAbstractModel: Loading local VMs...\n"));
    1024 
    1025     /* Acquire VBox: */
    1026     const CVirtualBox comVBox = uiCommon().virtualBox();
    1027 
    1028     /* Acquire existing local machines: */
    1029     const QVector<CMachine> machines = comVBox.GetMachines();
    1030     /* Show error message if necessary: */
    1031     if (!comVBox.isOk())
    1032         msgCenter().cannotAcquireVirtualBoxParameter(comVBox);
    1033     else
    1034     {
    1035         /* Iterate through existing machines: */
    1036         foreach (const CMachine &comMachine, machines)
    1037         {
    1038             /* Skip if we have nothing to populate (wtf happened?): */
    1039             if (comMachine.isNull())
    1040                 continue;
    1041 
    1042             /* Get machine ID: */
    1043             const QUuid uMachineID = comMachine.GetId();
    1044             /* Show error message if necessary: */
    1045             if (!comMachine.isOk())
    1046             {
    1047                 msgCenter().cannotAcquireMachineParameter(comMachine);
    1048                 continue;
    1049             }
    1050 
    1051             /* Skip if we have nothing to show (wtf happened?): */
    1052             if (uMachineID.isNull())
    1053                 continue;
    1054 
    1055             /* Skip if machine is restricted from being shown: */
    1056             if (!gEDataManager->showMachineInVirtualBoxManagerChooser(uMachineID))
    1057                 continue;
    1058 
    1059             /* Add machine into tree: */
    1060             addLocalMachineIntoTheTree(comMachine);
    1061         }
    1062     }
    1063 
    1064     LogRelFlow(("UIChooserAbstractModel: Local VMs loaded.\n"));
    1065 }
    1066 
    1067 void UIChooserAbstractModel::reloadCloudTree()
    1068 {
    1069     LogRelFlow(("UIChooserAbstractModel: Loading cloud providers/profiles...\n"));
    1070 
    1071     /* Wipe out existing cloud providers first.
    1072      * This is quite rude, in future we need to reimplement it more wise.. */
    1073     foreach (UIChooserNode *pNode, invisibleRoot()->nodes(UIChooserNodeType_Group))
    1074     {
    1075         AssertPtrReturnVoid(pNode);
    1076         UIChooserNodeGroup *pGroupNode = pNode->toGroupNode();
    1077         AssertPtrReturnVoid(pGroupNode);
    1078         if (pGroupNode->groupType() == UIChooserNodeGroupType_Provider)
    1079             delete pNode;
    1080     }
    1081 
    1082     /* Acquire Cloud Profile Manager restrictions: */
    1083     const QStringList restrictions = gEDataManager->cloudProfileManagerRestrictions();
    1084 
    1085     /* Iterate through existing providers: */
    1086     foreach (CCloudProvider comCloudProvider, listCloudProviders())
    1087     {
    1088         /* Skip if we have nothing to populate: */
    1089         if (comCloudProvider.isNull())
    1090             continue;
    1091 
    1092         /* Acquire provider id: */
    1093         QUuid uProviderId;
    1094         if (!cloudProviderId(comCloudProvider, uProviderId))
    1095             continue;
    1096 
    1097         /* Acquire provider short name: */
    1098         QString strProviderShortName;
    1099         if (!cloudProviderShortName(comCloudProvider, strProviderShortName))
    1100             continue;
    1101 
    1102         /* Make sure this provider isn't restricted: */
    1103         const QString strProviderPath = QString("/%1").arg(strProviderShortName);
    1104         if (restrictions.contains(strProviderPath))
    1105             continue;
    1106 
    1107         /* Acquire list of profiles: */
    1108         const QVector<CCloudProfile> profiles = listCloudProfiles(comCloudProvider);
    1109         if (profiles.isEmpty())
    1110             continue;
    1111 
    1112         /* Add provider group node: */
    1113         UIChooserNodeGroup *pProviderNode =
    1114             new UIChooserNodeGroup(invisibleRoot() /* parent */,
    1115                                    getDesiredNodePosition(invisibleRoot(),
    1116                                                           UIChooserNodeDataPrefixType_Provider,
    1117                                                           strProviderShortName),
    1118                                    uProviderId,
    1119                                    strProviderShortName,
    1120                                    UIChooserNodeGroupType_Provider,
    1121                                    shouldGroupNodeBeOpened(invisibleRoot(),
    1122                                                            UIChooserNodeDataPrefixType_Provider,
    1123                                                            strProviderShortName));
    1124 
    1125         /* Iterate through provider's profiles: */
    1126         foreach (CCloudProfile comCloudProfile, profiles)
    1127         {
    1128             /* Skip if we have nothing to populate: */
    1129             if (comCloudProfile.isNull())
    1130                 continue;
    1131 
    1132             /* Acquire profile name: */
    1133             QString strProfileName;
    1134             if (!cloudProfileName(comCloudProfile, strProfileName))
    1135                 continue;
    1136 
    1137             /* Make sure this profile isn't restricted: */
    1138             const QString strProfilePath = QString("/%1/%2").arg(strProviderShortName, strProfileName);
    1139             if (restrictions.contains(strProfilePath))
    1140                 continue;
    1141 
    1142             /* Add profile sub-group node: */
    1143             UIChooserNodeGroup *pProfileNode =
    1144                 new UIChooserNodeGroup(pProviderNode /* parent */,
    1145                                        getDesiredNodePosition(pProviderNode,
    1146                                                               UIChooserNodeDataPrefixType_Profile,
    1147                                                               strProfileName),
    1148                                        QUuid() /* id */,
    1149                                        strProfileName,
    1150                                        UIChooserNodeGroupType_Profile,
    1151                                        shouldGroupNodeBeOpened(pProviderNode,
    1152                                                                UIChooserNodeDataPrefixType_Profile,
    1153                                                                strProfileName));
    1154 
    1155             /* Add fake cloud VM item: */
    1156             createCloudMachineNode(pProfileNode, UIFakeCloudVirtualMachineItemState_Loading);
    1157 
    1158             /* Insert cloud entity key into a list of keys currently being updated: */
    1159             const UICloudEntityKey cloudEntityKey = UICloudEntityKey(strProviderShortName, strProfileName);
    1160             insertCloudEntityKey(cloudEntityKey);
    1161 
    1162             /* Create list cloud machines task: */
    1163             UITaskCloudListMachines *pTask = new UITaskCloudListMachines(strProviderShortName,
    1164                                                                          strProfileName,
    1165                                                                          true /* with refresh? */);
    1166             AssertPtrReturnVoid(pTask);
    1167             uiCommon().threadPoolCloud()->enqueueTask(pTask);
    1168         }
    1169     }
    1170 
    1171     LogRelFlow(("UIChooserAbstractModel: Cloud providers/profiles loaded.\n"));
    1172 }
    1173 
    1174 void UIChooserAbstractModel::addLocalMachineIntoTheTree(const CMachine &comMachine,
    1175                                                         bool fMakeItVisible /* = false */)
    1176 {
    1177     /* Make sure passed VM is not NULL: */
    1178     if (comMachine.isNull())
    1179         LogRelFlow(("UIChooserModel: ERROR: Passed local VM is NULL!\n"));
    1180     AssertReturnVoid(!comMachine.isNull());
    1181 
    1182     /* Which VM we are loading: */
    1183     const QUuid uId = comMachine.GetId();
    1184     LogRelFlow(("UIChooserModel: Loading local VM with ID={%s}...\n",
    1185                 toOldStyleUuid(uId).toUtf8().constData()));
    1186 
    1187     /* Is that machine accessible? */
    1188     if (comMachine.GetAccessible())
    1189     {
    1190         /* Acquire VM name: */
    1191         const QString strName = comMachine.GetName();
    1192         LogRelFlow(("UIChooserModel:  Local VM {%s} is accessible.\n", strName.toUtf8().constData()));
    1193         /* Which groups passed machine attached to? */
    1194         const QVector<QString> groups = comMachine.GetGroups();
    1195         const QStringList groupList = groups.toList();
    1196         const QString strGroups = groupList.join(", ");
    1197         LogRelFlow(("UIChooserModel:  Local VM {%s} has groups: {%s}.\n",
    1198                     strName.toUtf8().constData(), strGroups.toUtf8().constData()));
    1199         foreach (QString strGroup, groups)
    1200         {
    1201             /* Remove last '/' if any: */
    1202             if (strGroup.right(1) == "/")
    1203                 strGroup.truncate(strGroup.size() - 1);
    1204             /* Create machine-item with found group-item as parent: */
    1205             LogRelFlow(("UIChooserModel:   Creating node for local VM {%s} in group {%s}.\n",
    1206                         strName.toUtf8().constData(), strGroup.toUtf8().constData()));
    1207             createLocalMachineNode(getLocalGroupNode(strGroup, invisibleRoot(), fMakeItVisible), comMachine);
    1208         }
    1209         /* Update group settings: */
    1210         m_groups[toOldStyleUuid(uId)] = groupList;
    1211     }
    1212     /* Inaccessible machine: */
    1213     else
    1214     {
    1215         /* VM is accessible: */
    1216         LogRelFlow(("UIChooserModel:  Local VM {%s} is inaccessible.\n",
    1217                     toOldStyleUuid(uId).toUtf8().constData()));
    1218         /* Create machine-item with main-root group-item as parent: */
    1219         createLocalMachineNode(invisibleRoot(), comMachine);
    1220     }
    1221 }
    1222 
    1223 void UIChooserAbstractModel::addCloudMachineIntoTheTree(const QString &strGroup,
    1224                                                         const CCloudMachine &comMachine,
    1225                                                         bool fMakeItVisible /* = false */)
    1226 {
    1227     /* Make sure passed VM is not NULL: */
    1228     if (comMachine.isNull())
    1229         LogRelFlow(("UIChooserModel: ERROR: Passed cloud VM is NULL!\n"));
    1230     AssertReturnVoid(!comMachine.isNull());
    1231 
    1232     /* Which VM we are loading: */
    1233     const QUuid uId = comMachine.GetId();
    1234     LogRelFlow(("UIChooserModel: Loading cloud VM with ID={%s}...\n",
    1235                 toOldStyleUuid(uId).toUtf8().constData()));
    1236 
    1237     /* Acquire VM name: */
    1238     QString strName = comMachine.GetName();
    1239     if (strName.isEmpty())
    1240         strName = uId.toString();
    1241     LogRelFlow(("UIChooserModel:  Creating node for cloud VM {%s} in group {%s}.\n",
    1242                 strName.toUtf8().constData(), strGroup.toUtf8().constData()));
    1243     /* Create machine-item with found group-item as parent: */
    1244     createCloudMachineNode(getCloudGroupNode(strGroup, invisibleRoot(), fMakeItVisible), comMachine);
    1245     /* Update group settings: */
    1246     const QStringList groupList(strGroup);
    1247     m_groups[toOldStyleUuid(uId)] = groupList;
    1248 }
    1249 
    1250 UIChooserNode *UIChooserAbstractModel::getLocalGroupNode(const QString &strName, UIChooserNode *pParentNode, bool fAllGroupsOpened)
    1251 {
    1252     /* Check passed stuff: */
    1253     if (pParentNode->name() == strName)
    1254         return pParentNode;
    1255 
    1256     /* Prepare variables: */
    1257     const QString strFirstSubName = strName.section('/', 0, 0);
    1258     const QString strFirstSuffix = strName.section('/', 1, -1);
    1259     const QString strSecondSubName = strFirstSuffix.section('/', 0, 0);
    1260     const QString strSecondSuffix = strFirstSuffix.section('/', 1, -1);
    1261 
    1262     /* Passed group name equal to first sub-name: */
    1263     if (pParentNode->name() == strFirstSubName)
    1264     {
    1265         /* Make sure first-suffix is NOT empty: */
    1266         AssertMsg(!strFirstSuffix.isEmpty(), ("Invalid group name!"));
    1267         /* Trying to get group node among our children: */
    1268         foreach (UIChooserNode *pNode, pParentNode->nodes(UIChooserNodeType_Group))
    1269         {
    1270             AssertPtrReturn(pNode, 0);
    1271             UIChooserNodeGroup *pGroupNode = pNode->toGroupNode();
    1272             AssertPtrReturn(pGroupNode, 0);
    1273             if (   pGroupNode->groupType() == UIChooserNodeGroupType_Local
    1274                 && pNode->name() == strSecondSubName)
    1275             {
    1276                 UIChooserNode *pFoundNode = getLocalGroupNode(strFirstSuffix, pNode, fAllGroupsOpened);
    1277                 if (UIChooserNodeGroup *pFoundGroupNode = pFoundNode->toGroupNode())
    1278                     if (fAllGroupsOpened && pFoundGroupNode->isClosed())
    1279                         pFoundGroupNode->open();
    1280                 return pFoundNode;
    1281             }
    1282         }
    1283     }
    1284 
    1285     /* Found nothing? Creating: */
    1286     UIChooserNodeGroup *pNewGroupNode =
    1287         new UIChooserNodeGroup(pParentNode,
    1288                                getDesiredNodePosition(pParentNode,
    1289                                                       UIChooserNodeDataPrefixType_Local,
    1290                                                       strSecondSubName),
    1291                                QUuid() /* id */,
    1292                                strSecondSubName,
    1293                                UIChooserNodeGroupType_Local,
    1294                                fAllGroupsOpened || shouldGroupNodeBeOpened(pParentNode,
    1295                                                                            UIChooserNodeDataPrefixType_Local,
    1296                                                                            strSecondSubName));
    1297     return strSecondSuffix.isEmpty() ? pNewGroupNode : getLocalGroupNode(strFirstSuffix, pNewGroupNode, fAllGroupsOpened);
    1298 }
    1299 
    1300 UIChooserNode *UIChooserAbstractModel::getCloudGroupNode(const QString &strName, UIChooserNode *pParentNode, bool fAllGroupsOpened)
    1301 {
    1302     /* Check passed stuff: */
    1303     if (pParentNode->name() == strName)
    1304         return pParentNode;
    1305 
    1306     /* Prepare variables: */
    1307     const QString strFirstSubName = strName.section('/', 0, 0);
    1308     const QString strFirstSuffix = strName.section('/', 1, -1);
    1309     const QString strSecondSubName = strFirstSuffix.section('/', 0, 0);
    1310 
    1311     /* Passed group name equal to first sub-name: */
    1312     if (pParentNode->name() == strFirstSubName)
    1313     {
    1314         /* Make sure first-suffix is NOT empty: */
    1315         AssertMsg(!strFirstSuffix.isEmpty(), ("Invalid group name!"));
    1316         /* Trying to get group node among our children: */
    1317         foreach (UIChooserNode *pNode, pParentNode->nodes(UIChooserNodeType_Group))
    1318         {
    1319             AssertPtrReturn(pNode, 0);
    1320             UIChooserNodeGroup *pGroupNode = pNode->toGroupNode();
    1321             AssertPtrReturn(pGroupNode, 0);
    1322             if (   (   pGroupNode->groupType() == UIChooserNodeGroupType_Provider
    1323                     || pGroupNode->groupType() == UIChooserNodeGroupType_Profile)
    1324                 && pNode->name() == strSecondSubName)
    1325             {
    1326                 UIChooserNode *pFoundNode = getCloudGroupNode(strFirstSuffix, pNode, fAllGroupsOpened);
    1327                 if (UIChooserNodeGroup *pFoundGroupNode = pFoundNode->toGroupNode())
    1328                     if (fAllGroupsOpened && pFoundGroupNode->isClosed())
    1329                         pFoundGroupNode->open();
    1330                 return pFoundNode;
    1331             }
    1332         }
    1333     }
    1334 
    1335     /* Found nothing? Returning parent: */
    1336     AssertFailedReturn(pParentNode);
    1337 }
    1338 
    1339 bool UIChooserAbstractModel::shouldGroupNodeBeOpened(UIChooserNode *pParentNode,
    1340                                                      UIChooserNodeDataPrefixType enmDataType,
    1341                                                      const QString &strName) const
    1342 {
    1343     /* Read group definitions: */
    1344     const QStringList definitions = gEDataManager->selectorWindowGroupsDefinitions(pParentNode->fullName());
    1345     /* Return 'false' if no definitions found: */
    1346     if (definitions.isEmpty())
    1347         return false;
    1348 
    1349     /* Prepare required group definition reg-exp: */
    1350     const QString strNodePrefix = prefixToString(enmDataType);
    1351     const QString strNodeOptionOpened = optionToString(UIChooserNodeDataOptionType_GroupOpened);
    1352     const QString strDefinitionTemplate = QString("%1(\\S)*=%2").arg(strNodePrefix, strName);
    1353     const QRegExp definitionRegExp(strDefinitionTemplate);
    1354     /* For each the group definition: */
    1355     foreach (const QString &strDefinition, definitions)
    1356     {
    1357         /* Check if this is required definition: */
    1358         if (definitionRegExp.indexIn(strDefinition) == 0)
    1359         {
    1360             /* Get group descriptor: */
    1361             const QString strDescriptor(definitionRegExp.cap(1));
    1362             if (strDescriptor.contains(strNodeOptionOpened))
    1363                 return true;
    1364         }
    1365     }
    1366 
    1367     /* Return 'false' by default: */
    1368     return false;
    1369 }
    1370 
    1371 bool UIChooserAbstractModel::shouldGlobalNodeBeFavorite(UIChooserNode *pParentNode) const
    1372 {
    1373     /* Read group definitions: */
    1374     const QStringList definitions = gEDataManager->selectorWindowGroupsDefinitions(pParentNode->fullName());
    1375     /* Return 'false' if no definitions found: */
    1376     if (definitions.isEmpty())
    1377         return false;
    1378 
    1379     /* Prepare required group definition reg-exp: */
    1380     const QString strNodePrefix = prefixToString(UIChooserNodeDataPrefixType_Global);
    1381     const QString strNodeOptionFavorite = optionToString(UIChooserNodeDataOptionType_GlobalFavorite);
    1382     const QString strNodeValueDefault = valueToString(UIChooserNodeDataValueType_GlobalDefault);
    1383     const QString strDefinitionTemplate = QString("%1(\\S)*=%2").arg(strNodePrefix, strNodeValueDefault);
    1384     const QRegExp definitionRegExp(strDefinitionTemplate);
    1385     /* For each the group definition: */
    1386     foreach (const QString &strDefinition, definitions)
    1387     {
    1388         /* Check if this is required definition: */
    1389         if (definitionRegExp.indexIn(strDefinition) == 0)
    1390         {
    1391             /* Get group descriptor: */
    1392             const QString strDescriptor(definitionRegExp.cap(1));
    1393             if (strDescriptor.contains(strNodeOptionFavorite))
    1394                 return true;
    1395         }
    1396     }
    1397 
    1398     /* Return 'false' by default: */
    1399     return false;
    1400 }
    1401 
    1402 void UIChooserAbstractModel::wipeOutEmptyGroupsStartingFrom(UIChooserNode *pParent)
    1403 {
    1404     /* Cleanup all the group children recursively first: */
    1405     foreach (UIChooserNode *pNode, pParent->nodes(UIChooserNodeType_Group))
    1406         wipeOutEmptyGroupsStartingFrom(pNode);
    1407     /* If parent isn't root and has no nodes: */
    1408     if (!pParent->isRoot() && !pParent->hasNodes())
    1409     {
    1410         /* Delete parent node and item: */
    1411         delete pParent;
    1412     }
    1413 }
    1414 
    1415 int UIChooserAbstractModel::getDesiredNodePosition(UIChooserNode *pParentNode,
    1416                                                    UIChooserNodeDataPrefixType enmDataType,
    1417                                                    const QString &strName)
    1418 {
    1419     /* End of list (by default)? */
    1420     int iNewNodeDesiredPosition = -1;
    1421     /* Which position should be new node placed by definitions: */
    1422     const int iNewNodeDefinitionPosition = getDefinedNodePosition(pParentNode, enmDataType, strName);
    1423 
    1424     /* If some position defined: */
    1425     if (iNewNodeDefinitionPosition != -1)
    1426     {
    1427         /* Start of list if some definition present: */
    1428         iNewNodeDesiredPosition = 0;
    1429         /* We have to check all the existing node positions: */
    1430         UIChooserNodeType enmType = UIChooserNodeType_Any;
    1431         switch (enmDataType)
    1432         {
    1433             case UIChooserNodeDataPrefixType_Global:   enmType = UIChooserNodeType_Global; break;
    1434             case UIChooserNodeDataPrefixType_Machine:  enmType = UIChooserNodeType_Machine; break;
    1435             case UIChooserNodeDataPrefixType_Local:
    1436             case UIChooserNodeDataPrefixType_Provider:
    1437             case UIChooserNodeDataPrefixType_Profile:  enmType = UIChooserNodeType_Group; break;
    1438         }
    1439         const QList<UIChooserNode*> nodes = pParentNode->nodes(enmType);
    1440         for (int i = nodes.size() - 1; i >= 0; --i)
    1441         {
    1442             /* Get current node: */
    1443             UIChooserNode *pNode = nodes.at(i);
    1444             AssertPtrReturn(pNode, iNewNodeDesiredPosition);
    1445             /* Which position should be current node placed by definitions? */
    1446             UIChooserNodeDataPrefixType enmNodeDataType = UIChooserNodeDataPrefixType_Global;
    1447             QString strDefinitionName;
    1448             switch (pNode->type())
    1449             {
    1450                 case UIChooserNodeType_Machine:
    1451                 {
    1452                     enmNodeDataType = UIChooserNodeDataPrefixType_Machine;
    1453                     strDefinitionName = toOldStyleUuid(pNode->toMachineNode()->id());
    1454                     break;
    1455                 }
    1456                 case UIChooserNodeType_Group:
    1457                 {
    1458                     /* Cast to group node: */
    1459                     UIChooserNodeGroup *pGroupNode = pNode->toGroupNode();
    1460                     AssertPtrReturn(pGroupNode, iNewNodeDesiredPosition);
    1461                     switch (pGroupNode->groupType())
    1462                     {
    1463                         case UIChooserNodeGroupType_Local:    enmNodeDataType = UIChooserNodeDataPrefixType_Local; break;
    1464                         case UIChooserNodeGroupType_Provider: enmNodeDataType = UIChooserNodeDataPrefixType_Provider; break;
    1465                         case UIChooserNodeGroupType_Profile:  enmNodeDataType = UIChooserNodeDataPrefixType_Profile; break;
    1466                         default: break;
    1467                     }
    1468                     strDefinitionName = pNode->name();
    1469                     break;
    1470                 }
    1471                 default:
    1472                     break;
    1473             }
    1474             /* If some position defined: */
    1475             const int iNodeDefinitionPosition = getDefinedNodePosition(pParentNode, enmNodeDataType, strDefinitionName);
    1476             if (iNodeDefinitionPosition != -1)
    1477             {
    1478                 AssertReturn(iNodeDefinitionPosition != iNewNodeDefinitionPosition, iNewNodeDesiredPosition);
    1479                 if (iNodeDefinitionPosition < iNewNodeDefinitionPosition)
    1480                 {
    1481                     iNewNodeDesiredPosition = i + 1;
    1482                     break;
    1483                 }
    1484             }
    1485         }
    1486     }
    1487 
    1488     /* Return desired node position: */
    1489     return iNewNodeDesiredPosition;
    1490 }
    1491 
    1492 int UIChooserAbstractModel::getDefinedNodePosition(UIChooserNode *pParentNode, UIChooserNodeDataPrefixType enmDataType, const QString &strName)
    1493 {
    1494     /* Read group definitions: */
    1495     const QStringList definitions = gEDataManager->selectorWindowGroupsDefinitions(pParentNode->fullName());
    1496     /* Return 'false' if no definitions found: */
    1497     if (definitions.isEmpty())
    1498         return -1;
    1499 
    1500     /* Prepare definition reg-exp: */
    1501     QString strDefinitionTemplateShort;
    1502     QString strDefinitionTemplateFull;
    1503     const QString strNodePrefixLocal = prefixToString(UIChooserNodeDataPrefixType_Local);
    1504     const QString strNodePrefixProvider = prefixToString(UIChooserNodeDataPrefixType_Provider);
    1505     const QString strNodePrefixProfile = prefixToString(UIChooserNodeDataPrefixType_Profile);
    1506     const QString strNodePrefixMachine = prefixToString(UIChooserNodeDataPrefixType_Machine);
    1507     switch (enmDataType)
    1508     {
    1509         case UIChooserNodeDataPrefixType_Local:
    1510         {
    1511             strDefinitionTemplateShort = QString("^[%1%2%3](\\S)*=").arg(strNodePrefixLocal, strNodePrefixProvider, strNodePrefixProfile);
    1512             strDefinitionTemplateFull = QString("^%1(\\S)*=%2$").arg(strNodePrefixLocal, strName);
    1513             break;
    1514         }
    1515         case UIChooserNodeDataPrefixType_Provider:
    1516         {
    1517             strDefinitionTemplateShort = QString("^[%1%2%3](\\S)*=").arg(strNodePrefixLocal, strNodePrefixProvider, strNodePrefixProfile);
    1518             strDefinitionTemplateFull = QString("^%1(\\S)*=%2$").arg(strNodePrefixProvider, strName);
    1519             break;
    1520         }
    1521         case UIChooserNodeDataPrefixType_Profile:
    1522         {
    1523             strDefinitionTemplateShort = QString("^[%1%2%3](\\S)*=").arg(strNodePrefixLocal, strNodePrefixProvider, strNodePrefixProfile);
    1524             strDefinitionTemplateFull = QString("^%1(\\S)*=%2$").arg(strNodePrefixProfile, strName);
    1525             break;
    1526         }
    1527         case UIChooserNodeDataPrefixType_Machine:
    1528         {
    1529             strDefinitionTemplateShort = QString("^%1=").arg(strNodePrefixMachine);
    1530             strDefinitionTemplateFull = QString("^%1=%2$").arg(strNodePrefixMachine, strName);
    1531             break;
    1532         }
    1533         default:
    1534             return -1;
    1535     }
    1536     QRegExp definitionRegExpShort(strDefinitionTemplateShort);
    1537     QRegExp definitionRegExpFull(strDefinitionTemplateFull);
    1538 
    1539     /* For each the definition: */
    1540     int iDefinitionIndex = -1;
    1541     foreach (const QString &strDefinition, definitions)
    1542     {
    1543         /* Check if this definition is of required type: */
    1544         if (definitionRegExpShort.indexIn(strDefinition) == 0)
    1545         {
    1546             ++iDefinitionIndex;
    1547             /* Check if this definition is exactly what we need: */
    1548             if (definitionRegExpFull.indexIn(strDefinition) == 0)
    1549                 return iDefinitionIndex;
    1550         }
    1551     }
    1552 
    1553     /* Return result: */
    1554     return -1;
    1555 }
    1556 
    1557 void UIChooserAbstractModel::createLocalMachineNode(UIChooserNode *pParentNode, const CMachine &comMachine)
    1558 {
    1559     new UIChooserNodeMachine(pParentNode,
    1560                              getDesiredNodePosition(pParentNode,
    1561                                                     UIChooserNodeDataPrefixType_Machine,
    1562                                                     toOldStyleUuid(comMachine.GetId())),
    1563                              comMachine);
    1564 }
    1565 
    1566 void UIChooserAbstractModel::createCloudMachineNode(UIChooserNode *pParentNode, UIFakeCloudVirtualMachineItemState enmState)
    1567 {
    1568     new UIChooserNodeMachine(pParentNode,
    1569                              0 /* position */,
    1570                              enmState);
    1571 }
    1572 
    1573 void UIChooserAbstractModel::createCloudMachineNode(UIChooserNode *pParentNode, const CCloudMachine &comMachine)
    1574 {
    1575     UIChooserNodeMachine *pNode = new UIChooserNodeMachine(pParentNode,
    1576                                                            getDesiredNodePosition(pParentNode,
    1577                                                                                   UIChooserNodeDataPrefixType_Machine,
    1578                                                                                   toOldStyleUuid(comMachine.GetId())),
    1579                                                            comMachine);
    1580     /* Request for async node update if necessary: */
    1581     if (!comMachine.GetAccessible())
    1582     {
    1583         AssertReturnVoid(pNode && pNode->cacheType() == UIVirtualMachineItemType_CloudReal);
    1584         pNode->cache()->toCloud()->updateInfoAsync(false /* delayed? */);
    1585     }
    1586 }
    1587 
    1588 QStringList UIChooserAbstractModel::gatherPossibleGroupNodeNames(UIChooserNode *pCurrentNode, QList<UIChooserNode*> exceptions) const
    1589 {
    1590     /* Prepare result: */
    1591     QStringList result;
    1592 
    1593     /* Walk through all the children and make sure there are no exceptions: */
    1594     bool fAddCurrent = true;
    1595     foreach (UIChooserNode *pChild, pCurrentNode->nodes(UIChooserNodeType_Any))
    1596     {
    1597         AssertPtrReturn(pChild, result);
    1598         if (exceptions.contains(pChild))
    1599             fAddCurrent = false;
    1600         else
    1601         {
    1602             if (pChild->type() == UIChooserNodeType_Group)
    1603             {
    1604                 UIChooserNodeGroup *pChildGroup = pChild->toGroupNode();
    1605                 AssertPtrReturn(pChildGroup, result);
    1606                 if (pChildGroup->groupType() == UIChooserNodeGroupType_Local)
    1607                     result << gatherPossibleGroupNodeNames(pChild, exceptions);
    1608             }
    1609         }
    1610     }
    1611 
    1612     /* Add current item if not overridden: */
    1613     if (fAddCurrent)
    1614         result.prepend(pCurrentNode->fullName());
    1615 
    1616     /* Return result: */
    1617     return result;
    1618 }
    1619 
    1620 bool UIChooserAbstractModel::checkIfNodeContainChildWithId(UIChooserNode *pParentNode, const QUuid &uId) const
    1621 {
    1622     /* Check parent-node type: */
    1623     AssertPtrReturn(pParentNode, false);
    1624     switch (pParentNode->type())
    1625     {
    1626         case UIChooserNodeType_Machine:
    1627         {
    1628             /* Check if pParentNode has the passed uId itself: */
    1629             UIChooserNodeMachine *pMachineNode = pParentNode->toMachineNode();
    1630             AssertPtrReturn(pMachineNode, false);
    1631             if (pMachineNode->id() == uId)
    1632                 return true;
    1633             break;
    1634         }
    1635         case UIChooserNodeType_Group:
    1636         {
    1637             /* Recursively iterate through children: */
    1638             foreach (UIChooserNode *pChildNode, pParentNode->nodes())
    1639                 if (checkIfNodeContainChildWithId(pChildNode, uId))
    1640                     return true;
    1641             break;
    1642         }
    1643         default:
    1644             break;
    1645     }
    1646 
    1647     /* False by default: */
    1648     return false;
    1649 }
    1650 
    1651 void UIChooserAbstractModel::saveGroupSettings()
    1652 {
    1653     /* Make sure there is no group settings saving activity: */
    1654     if (UIThreadGroupSettingsSave::instance())
    1655         return;
    1656 
    1657     /* Prepare full group map: */
    1658     QMap<QString, QStringList> groups;
    1659     gatherGroupSettings(groups, invisibleRoot());
    1660 
    1661     /* Save information in other thread: */
    1662     UIThreadGroupSettingsSave::prepare();
    1663     emit sigGroupSavingStateChanged();
    1664     connect(UIThreadGroupSettingsSave::instance(), &UIThreadGroupSettingsSave::sigReload,
    1665             this, &UIChooserAbstractModel::sltReloadMachine);
    1666     UIThreadGroupSettingsSave::instance()->configure(this, m_groups, groups);
    1667     UIThreadGroupSettingsSave::instance()->start();
    1668     m_groups = groups;
    1669 }
    1670 
    1671 void UIChooserAbstractModel::saveGroupDefinitions()
    1672 {
    1673     /* Make sure there is no group definitions save activity: */
    1674     if (UIThreadGroupDefinitionsSave::instance())
    1675         return;
    1676 
    1677     /* Prepare full group map: */
    1678     QMap<QString, QStringList> groups;
    1679     gatherGroupDefinitions(groups, invisibleRoot());
    1680 
    1681     /* Save information in other thread: */
    1682     UIThreadGroupDefinitionsSave::prepare();
    1683     emit sigGroupSavingStateChanged();
    1684     UIThreadGroupDefinitionsSave::instance()->configure(this, groups);
    1685     UIThreadGroupDefinitionsSave::instance()->start();
    1686 }
    1687 
    1688 void UIChooserAbstractModel::gatherGroupSettings(QMap<QString, QStringList> &settings,
    1689                                                  UIChooserNode *pParentGroup)
    1690 {
    1691     /* Iterate over all the machine-nodes: */
    1692     foreach (UIChooserNode *pNode, pParentGroup->nodes(UIChooserNodeType_Machine))
    1693     {
    1694         /* Make sure it's really machine node: */
    1695         AssertPtrReturnVoid(pNode);
    1696         UIChooserNodeMachine *pMachineNode = pNode->toMachineNode();
    1697         AssertPtrReturnVoid(pMachineNode);
    1698         /* Make sure it's local machine node exactly and it's accessible: */
    1699         if (   pMachineNode->cacheType() == UIVirtualMachineItemType_Local
    1700             && pMachineNode->accessible())
    1701             settings[toOldStyleUuid(pMachineNode->id())] << pParentGroup->fullName();
    1702     }
    1703     /* Iterate over all the group-nodes: */
    1704     foreach (UIChooserNode *pNode, pParentGroup->nodes(UIChooserNodeType_Group))
    1705         gatherGroupSettings(settings, pNode);
    1706 }
    1707 
    1708 void UIChooserAbstractModel::gatherGroupDefinitions(QMap<QString, QStringList> &definitions,
    1709                                                     UIChooserNode *pParentGroup)
    1710 {
    1711     /* Prepare extra-data key for current group: */
    1712     const QString strExtraDataKey = pParentGroup->fullName();
    1713     /* Iterate over all the global-nodes: */
    1714     foreach (UIChooserNode *pNode, pParentGroup->nodes(UIChooserNodeType_Global))
    1715     {
    1716         /* Append node definition: */
    1717         AssertPtrReturnVoid(pNode);
    1718         definitions[strExtraDataKey] << pNode->definition(true /* full */);
    1719     }
    1720     /* Iterate over all the group-nodes: */
    1721     foreach (UIChooserNode *pNode, pParentGroup->nodes(UIChooserNodeType_Group))
    1722     {
    1723         /* Append node definition: */
    1724         AssertPtrReturnVoid(pNode);
    1725         definitions[strExtraDataKey] << pNode->definition(true /* full */);
    1726         /* Go recursively through children: */
    1727         gatherGroupDefinitions(definitions, pNode);
    1728     }
    1729     /* Iterate over all the machine-nodes: */
    1730     foreach (UIChooserNode *pNode, pParentGroup->nodes(UIChooserNodeType_Machine))
    1731     {
    1732         /* Make sure it's really machine node: */
    1733         AssertPtrReturnVoid(pNode);
    1734         UIChooserNodeMachine *pMachineNode = pNode->toMachineNode();
    1735         AssertPtrReturnVoid(pMachineNode);
    1736         /* Append node definition, make sure it's local or real cloud machine node only: */
    1737         if (   pMachineNode->cacheType() == UIVirtualMachineItemType_Local
    1738             || pMachineNode->cacheType() == UIVirtualMachineItemType_CloudReal)
    1739             definitions[strExtraDataKey] << pNode->definition(true /* full */);
    1740     }
    1741 }
    1742 
    1743 void UIChooserAbstractModel::makeSureGroupSettingsSaveIsFinished()
    1744 {
    1745     /* Cleanup if necessary: */
    1746     if (UIThreadGroupSettingsSave::instance())
    1747         UIThreadGroupSettingsSave::cleanup();
    1748 }
    1749 
    1750 void UIChooserAbstractModel::makeSureGroupDefinitionsSaveIsFinished()
    1751 {
    1752     /* Cleanup if necessary: */
    1753     if (UIThreadGroupDefinitionsSave::instance())
    1754         UIThreadGroupDefinitionsSave::cleanup();
    1755 }
    1756 
    1757 UIChooserNode *UIChooserAbstractModel::searchProviderNode(const QUuid &uProviderId)
    1758 {
    1759     /* Search for a list of nodes matching passed name: */
    1760     QList<UIChooserNode*> providerNodes;
    1761     invisibleRoot()->searchForNodes(uProviderId.toString(),
    1762                                     UIChooserItemSearchFlag_CloudProvider | UIChooserItemSearchFlag_ExactId,
    1763                                     providerNodes);
    1764 
    1765     /* Return 1st node if any: */
    1766     return providerNodes.value(0);
    1767 }
    1768 
    1769 UIChooserNode *UIChooserAbstractModel::searchProviderNode(const QString &strProviderShortName)
    1770 {
    1771     /* Search for a list of nodes matching passed name: */
    1772     QList<UIChooserNode*> providerNodes;
    1773     invisibleRoot()->searchForNodes(strProviderShortName,
    1774                                     UIChooserItemSearchFlag_CloudProvider | UIChooserItemSearchFlag_ExactName,
    1775                                     providerNodes);
    1776 
    1777     /* Return 1st node if any: */
    1778     return providerNodes.value(0);
    1779 }
    1780 
    1781 UIChooserNode *UIChooserAbstractModel::searchProfileNode(UIChooserNode *pProviderNode, const QString &strProfileName)
    1782 {
    1783     AssertPtrReturn(pProviderNode, 0);
    1784 
    1785     /* Search for a list of nodes matching passed name: */
    1786     QList<UIChooserNode*> profileNodes;
    1787     pProviderNode->searchForNodes(strProfileName,
    1788                                   UIChooserItemSearchFlag_CloudProfile | UIChooserItemSearchFlag_ExactName,
    1789                                   profileNodes);
    1790 
    1791     /* Return 1st node if any: */
    1792     return profileNodes.value(0);
    1793 }
    1794 
    1795 UIChooserNode *UIChooserAbstractModel::searchProfileNode(const QString &strProviderShortName, const QString &strProfileName)
    1796 {
    1797     /* Wrap method above: */
    1798     return searchProfileNode(searchProviderNode(strProviderShortName), strProfileName);
    1799 }
    1800 
    1801 UIChooserNode *UIChooserAbstractModel::searchMachineNode(UIChooserNode *pProfileNode, const QUuid &uMachineId)
    1802 {
    1803     AssertPtrReturn(pProfileNode, 0);
    1804 
    1805     /* Search for a list of nodes matching passed ID: */
    1806     QList<UIChooserNode*> machineNodes;
    1807     pProfileNode->searchForNodes(uMachineId.toString(),
    1808                                  UIChooserItemSearchFlag_Machine | UIChooserItemSearchFlag_ExactId,
    1809                                  machineNodes);
    1810 
    1811     /* Return 1st node if any: */
    1812     return machineNodes.value(0);
    1813 }
    1814 
    1815 UIChooserNode *UIChooserAbstractModel::searchMachineNode(const QString &strProviderShortName, const QString &strProfileName, const QUuid &uMachineId)
    1816 {
    1817     /* Wrap method above: */
    1818     return searchMachineNode(searchProfileNode(strProviderShortName, strProfileName), uMachineId);
    1819 }
    1820 
    1821 UIChooserNode *UIChooserAbstractModel::searchFakeNode(UIChooserNode *pProfileNode)
    1822 {
    1823     /* Wrap method above: */
    1824     return searchMachineNode(pProfileNode, QUuid());
    1825 }
    1826 
    1827 UIChooserNode *UIChooserAbstractModel::searchFakeNode(const QString &strProviderShortName, const QString &strProfileName)
    1828 {
    1829     /* Wrap method above: */
    1830     return searchMachineNode(strProviderShortName, strProfileName, QUuid());
    1831 }
    1832 
    1833 
    1834 #include "UIChooserAbstractModel.moc"
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/UICloudEntityKey.h

    r86768 r86783  
    11/* $Id$ */
    22/** @file
    3  * VBox Qt GUI - UIChooserAbstractModel class declaration.
     3 * VBox Qt GUI - UICloudEntityKey class declaration.
    44 */
    55
     
    1616 */
    1717
    18 #ifndef FEQT_INCLUDED_SRC_manager_chooser_UIChooserAbstractModel_h
    19 #define FEQT_INCLUDED_SRC_manager_chooser_UIChooserAbstractModel_h
     18#ifndef FEQT_INCLUDED_SRC_manager_UICloudEntityKey_h
     19#define FEQT_INCLUDED_SRC_manager_UICloudEntityKey_h
    2020#ifndef RT_WITHOUT_PRAGMA_ONCE
    2121# pragma once
     
    2323
    2424/* Qt includes: */
    25 #include <QSet>
     25#include <QHash>
     26#include <QString>
    2627#include <QUuid>
    27 
    28 /* GUI includes: */
    29 #include "UIChooserDefs.h"
    30 #include "UIManagerDefs.h"
    31 
    32 /* COM includes: */
    33 #include "COMEnums.h"
    34 
    35 /* Forward declaration: */
    36 class UIChooser;
    37 class UIChooserNode;
    38 class UITask;
    39 class CCloudMachine;
    40 class CMachine;
    41 
    4228
    4329/** Cloud entity key definition. */
     
    7359}
    7460
    75 
    76 /** QObject extension used as VM Chooser-pane abstract model.
    77   * This class is used to load/save a tree of abstract invisible
    78   * nodes representing VMs and their groups from/to extra-data. */
    79 class UIChooserAbstractModel : public QObject
    80 {
    81     Q_OBJECT;
    82 
    83 signals:
    84 
    85     /** @name Cloud machine stuff.
    86       * @{ */
    87         /** Notifies listeners about state change for cloud machine with certain @a uId. */
    88         void sigCloudMachineStateChange(const QUuid &uId);
    89     /** @} */
    90 
    91     /** @name Group saving stuff.
    92       * @{ */
    93         /** Commands to start group saving. */
    94         void sigStartGroupSaving();
    95         /** Notifies listeners about group saving state changed. */
    96         void sigGroupSavingStateChanged();
    97     /** @} */
    98 
    99     /** @name Cloud update stuff.
    100       * @{ */
    101         /** Notifies listeners about cloud update state changed. */
    102         void sigCloudUpdateStateChanged();
    103     /** @} */
    104 
    105 public:
    106 
    107     /** Constructs abstract Chooser-model passing @a pParent to the base-class. */
    108     UIChooserAbstractModel(UIChooser *pParent);
    109 
    110     /** @name General stuff.
    111       * @{ */
    112         /** Inits model. */
    113         virtual void init();
    114         /** Deinits model. */
    115         virtual void deinit();
    116     /** @} */
    117 
    118     /** @name Children stuff.
    119       * @{ */
    120         /** Returns invisible root node instance. */
    121         UIChooserNode *invisibleRoot() const { return m_pInvisibleRootNode; }
    122 
    123         /** Wipes out empty groups. */
    124         void wipeOutEmptyGroups();
    125 
    126         /** Returns possible group node names for machine node with passed @a uId to move to. */
    127         QStringList possibleGroupNodeNamesForMachineNodeToMove(const QUuid &uId);
    128         /** Returns possible group node names for group node with passed @a strFullName to move to. */
    129         QStringList possibleGroupNodeNamesForGroupNodeToMove(const QString &strFullName);
    130 
    131         /** Generates unique group name traversing recursively starting from @a pRoot. */
    132         static QString uniqueGroupName(UIChooserNode *pRoot);
    133     /** @} */
    134 
    135     /** @name Search stuff.
    136       * @{ */
    137         /** Performs a search using @a strSearchTerm and @a iSearchFlags specified. */
    138         virtual void performSearch(const QString &strSearchTerm, int iSearchFlags);
    139         /** Resets the search result data members and disables item's visual effects.
    140           * Also returns a list of all nodes which may be utilized by the calling code. */
    141         virtual QList<UIChooserNode*> resetSearch();
    142         /** Returns search result. */
    143         QList<UIChooserNode*> searchResult() const;
    144     /** @} */
    145 
    146     /** @name Group saving stuff.
    147       * @{ */
    148         /** Commands to save groups. */
    149         void saveGroups();
    150         /** Returns whether group saving is in progress. */
    151         bool isGroupSavingInProgress() const;
    152 
    153         /** Returns QString representation for passed @a uId, wiping out {} symbols.
    154           * @note  Required for backward compatibility after QString=>QUuid change. */
    155         static QString toOldStyleUuid(const QUuid &uId);
    156 
    157         /** Returns node extra-data prefix of certain @a enmType. */
    158         static QString prefixToString(UIChooserNodeDataPrefixType enmType);
    159         /** Returns node extra-data option of certain @a enmType. */
    160         static QString optionToString(UIChooserNodeDataOptionType enmType);
    161         /** Returns node extra-data value of certain @a enmType. */
    162         static QString valueToString(UIChooserNodeDataValueType enmType);
    163     /** @} */
    164 
    165     /** @name Cloud update stuff.
    166       * @{ */
    167         /** Inserts cloud entity @a key into a set of keys currently being updated. */
    168         void insertCloudEntityKey(const UICloudEntityKey &key);
    169         /** Removes cloud entity @a key from a set of keys currently being updated. */
    170         void removeCloudEntityKey(const UICloudEntityKey &key);
    171         /** Returns whether cloud entity @a key is a part of key set currently being updated. */
    172         bool containsCloudEntityKey(const UICloudEntityKey &key) const;
    173 
    174         /** Returns whether at least one cloud profile currently being updated. */
    175         bool isCloudProfileUpdateInProgress() const;
    176     /** @} */
    177 
    178 public slots:
    179 
    180     /** @name Cloud machine stuff.
    181       * @{ */
    182         /** Handles cloud machine refresh started. */
    183         void sltHandleCloudMachineRefreshStarted();
    184         /** Handles cloud machine refresh finished. */
    185         void sltHandleCloudMachineRefreshFinished();
    186     /** @} */
    187 
    188     /** @name Group saving stuff.
    189       * @{ */
    190         /** Handles group settings saving complete. */
    191         void sltGroupSettingsSaveComplete();
    192         /** Handles group definitions saving complete. */
    193         void sltGroupDefinitionsSaveComplete();
    194     /** @} */
    195 
    196 protected slots:
    197 
    198     /** @name Main event handling stuff.
    199       * @{ */
    200         /** Handles local machine @a enmState change for machine with certain @a uMachineId. */
    201         virtual void sltLocalMachineStateChanged(const QUuid &uMachineId, const KMachineState enmState);
    202         /** Handles local machine data change for machine with certain @a uMachineId. */
    203         virtual void sltLocalMachineDataChanged(const QUuid &uMachineId);
    204         /** Handles local machine registering/unregistering for machine with certain @a uMachineId. */
    205         virtual void sltLocalMachineRegistrationChanged(const QUuid &uMachineId, const bool fRegistered);
    206 
    207         /** Handles session @a enmState change for machine with certain @a uMachineId. */
    208         virtual void sltSessionStateChanged(const QUuid &uMachineId, const KSessionState enmState);
    209 
    210         /** Handles snapshot change for machine/snapshot with certain @a uMachineId / @a uSnapshotId. */
    211         virtual void sltSnapshotChanged(const QUuid &uMachineId, const QUuid &uSnapshotId);
    212 
    213         /** Handles event about cloud provider with @a uProviderId being uninstalled. */
    214         virtual void sltHandleCloudProviderUninstall(const QUuid &uProviderId);
    215     /** @} */
    216 
    217     /** @name Children stuff.
    218       * @{ */
    219         /** Handles reload machine with certain @a uMachineId request. */
    220         virtual void sltReloadMachine(const QUuid &uMachineId);
    221     /** @} */
    222 
    223     /** @name Cloud stuff.
    224       * @{ */
    225         /** Handles cloud machine unregistering for @a uId.
    226           * @param  strProviderShortName  Brings provider short name.
    227           * @param  strProfileName        Brings profile name. */
    228         virtual void sltCloudMachineUnregistered(const QString &strProviderShortName,
    229                                                  const QString &strProfileName,
    230                                                  const QUuid &uId);
    231         /** Handles cloud machine unregistering for a list of @a ids.
    232           * @param  strProviderShortName  Brings provider short name.
    233           * @param  strProfileName        Brings profile name. */
    234         virtual void sltCloudMachinesUnregistered(const QString &strProviderShortName,
    235                                                   const QString &strProfileName,
    236                                                   const QList<QUuid> &ids);
    237         /** Handles cloud machine registering for @a comMachine.
    238           * @param  strProviderShortName  Brings provider short name.
    239           * @param  strProfileName        Brings profile name. */
    240         virtual void sltCloudMachineRegistered(const QString &strProviderShortName,
    241                                                const QString &strProfileName,
    242                                                const CCloudMachine &comMachine);
    243         /** Handles cloud machine registering for a list of @a machines.
    244           * @param  strProviderShortName  Brings provider short name.
    245           * @param  strProfileName        Brings profile name. */
    246         virtual void sltCloudMachinesRegistered(const QString &strProviderShortName,
    247                                                 const QString &strProfileName,
    248                                                 const QVector<CCloudMachine> &machines);
    249 
    250         /** Handles list cloud machines task complete signal. */
    251         virtual void sltHandleCloudListMachinesTaskComplete(UITask *pTask);
    252 
    253         /** Handles Cloud Profile Manager cumulative change. */
    254         virtual void sltHandleCloudProfileManagerCumulativeChange();
    255     /** @} */
    256 
    257 private slots:
    258 
    259     /** @name Group saving stuff.
    260       * @{ */
    261         /** Handles request to start group saving. */
    262         void sltStartGroupSaving();
    263     /** @} */
    264 
    265 private:
    266 
    267     /** @name Prepare/Cleanup cascade.
    268       * @{ */
    269         /** Prepares all. */
    270         void prepare();
    271         /** Prepares connections. */
    272         void prepareConnections();
    273     /** @} */
    274 
    275     /** @name Children stuff.
    276       * @{ */
    277         /** Reloads local tree. */
    278         void reloadLocalTree();
    279         /** Reloads cloud tree. */
    280         void reloadCloudTree();
    281 
    282         /** Adds local machine item based on certain @a comMachine and optionally @a fMakeItVisible. */
    283         void addLocalMachineIntoTheTree(const CMachine &comMachine, bool fMakeItVisible = false);
    284         /** Adds cloud machine item based on certain @a comMachine and optionally @a fMakeItVisible, into @a strGroup. */
    285         void addCloudMachineIntoTheTree(const QString &strGroup, const CCloudMachine &comMachine, bool fMakeItVisible = false);
    286 
    287         /** Acquires local group node, creates one if necessary.
    288           * @param  strName           Brings the name of group we looking for.
    289           * @param  pParentNode       Brings the parent we starting to look for a group from.
    290           * @param  fAllGroupsOpened  Brings whether we should open all the groups till the required one. */
    291         UIChooserNode *getLocalGroupNode(const QString &strName, UIChooserNode *pParentNode, bool fAllGroupsOpened);
    292         /** Acquires cloud group node, never create new, returns root if nothing found.
    293           * @param  strName           Brings the name of group we looking for.
    294           * @param  pParentNode       Brings the parent we starting to look for a group from.
    295           * @param  fAllGroupsOpened  Brings whether we should open all the groups till the required one. */
    296         UIChooserNode *getCloudGroupNode(const QString &strName, UIChooserNode *pParentNode, bool fAllGroupsOpened);
    297 
    298         /** Returns whether group node * with specified @a enmDataType and @a strName should be opened,
    299           * searching starting from the passed @a pParentNode. */
    300         bool shouldGroupNodeBeOpened(UIChooserNode *pParentNode,
    301                                      UIChooserNodeDataPrefixType enmDataType,
    302                                      const QString &strName) const;
    303         /** Returns whether global node should be favorite,
    304           * searching starting from the passed @a pParentNode. */
    305         bool shouldGlobalNodeBeFavorite(UIChooserNode *pParentNode) const;
    306 
    307         /** Wipes out empty groups starting from @a pParentItem. */
    308         void wipeOutEmptyGroupsStartingFrom(UIChooserNode *pParentNode);
    309 
    310         /** Acquires desired position for a child of @a pParentNode with specified @a enmDataType and @a strName. */
    311         int getDesiredNodePosition(UIChooserNode *pParentNode, UIChooserNodeDataPrefixType enmDataType, const QString &strName);
    312         /** Acquires defined position for a child of @a pParentNode with specified @a enmDataType and @a strName. */
    313         int getDefinedNodePosition(UIChooserNode *pParentNode, UIChooserNodeDataPrefixType enmDataType, const QString &strName);
    314 
    315         /** Creates local machine node based on certain @a comMachine as a child of specified @a pParentNode. */
    316         void createLocalMachineNode(UIChooserNode *pParentNode, const CMachine &comMachine);
    317         /** Creates fake cloud machine node in passed @a enmState as a child of specified @a pParentNode. */
    318         void createCloudMachineNode(UIChooserNode *pParentNode, UIFakeCloudVirtualMachineItemState enmState);
    319         /** Creates real cloud machine node based on certain @a comMachine as a child of specified @a pParentNode. */
    320         void createCloudMachineNode(UIChooserNode *pParentNode, const CCloudMachine &comMachine);
    321 
    322         /** Gathers a list of possible group node names for machine nodes listed in @a exceptions, starting from @a pCurrentNode. */
    323         QStringList gatherPossibleGroupNodeNames(UIChooserNode *pCurrentNode, QList<UIChooserNode*> exceptions) const;
    324 
    325         /** Returns whether passed @a pParentNode contains child node with passed @a uId. */
    326         bool checkIfNodeContainChildWithId(UIChooserNode *pParentNode, const QUuid &uId) const;
    327     /** @} */
    328 
    329     /** @name Group saving stuff.
    330       * @{ */
    331         /** Saves group settings. */
    332         void saveGroupSettings();
    333         /** Saves group definitions. */
    334         void saveGroupDefinitions();
    335 
    336         /** Gathers group @a settings of @a pParentGroup. */
    337         void gatherGroupSettings(QMap<QString, QStringList> &settings, UIChooserNode *pParentGroup);
    338         /** Gathers group @a definitions of @a pParentGroup. */
    339         void gatherGroupDefinitions(QMap<QString, QStringList> &definitions, UIChooserNode *pParentGroup);
    340 
    341         /** Makes sure group settings saving is finished. */
    342         void makeSureGroupSettingsSaveIsFinished();
    343         /** Makes sure group definitions saving is finished. */
    344         void makeSureGroupDefinitionsSaveIsFinished();
    345     /** @} */
    346 
    347     /** @name Cloud stuff.
    348       * @{ */
    349         /** Searches for provider node with passed @a uProviderId. */
    350         UIChooserNode *searchProviderNode(const QUuid &uProviderId);
    351         /** Searches for provider node with passed @a strProviderShortName. */
    352         UIChooserNode *searchProviderNode(const QString &strProviderShortName);
    353 
    354         /** Searches for profile node with passed @a strProfileName under passed @a pProviderNode. */
    355         UIChooserNode *searchProfileNode(UIChooserNode *pProviderNode, const QString &strProfileName);
    356         /** Searches for profile node with passed @a strProviderShortName and @a strProfileName. */
    357         UIChooserNode *searchProfileNode(const QString &strProviderShortName, const QString &strProfileName);
    358 
    359         /** Searches for machine node with passed @a uMachineId under passed @a pProfileNode. */
    360         UIChooserNode *searchMachineNode(UIChooserNode *pProfileNode, const QUuid &uMachineId);
    361         /** Searches for machine with passed @a strProviderShortName, @a strProfileName and @a uMachineId. */
    362         UIChooserNode *searchMachineNode(const QString &strProviderShortName, const QString &strProfileName, const QUuid &uMachineId);
    363 
    364         /** Searches for fake node under passed @a pProfileNode. */
    365         UIChooserNode *searchFakeNode(UIChooserNode *pProfileNode);
    366         /** Searches for fake with passed @a strProviderShortName and @a strProfileName. */
    367         UIChooserNode *searchFakeNode(const QString &strProviderShortName, const QString &strProfileName);
    368     /** @} */
    369 
    370     /** @name General stuff.
    371       * @{ */
    372         /** Holds the parent widget reference. */
    373         UIChooser *m_pParent;
    374     /** @} */
    375 
    376     /** @name Children stuff.
    377       * @{ */
    378         /** Holds the invisible root node instance. */
    379         UIChooserNode *m_pInvisibleRootNode;
    380     /** @} */
    381 
    382     /** @name Search stuff.
    383       * @{ */
    384         /** Stores the results of the current search. */
    385         QList<UIChooserNode*>  m_searchResults;
    386     /** @} */
    387 
    388     /** @name Group saving stuff.
    389       * @{ */
    390         /** Holds the consolidated map of group settings/definitions. */
    391         QMap<QString, QStringList>  m_groups;
    392     /** @} */
    393 
    394     /** @name Cloud update stuff.
    395       * @{ */
    396         /** Holds the set of cloud entity keys currently being updated. */
    397         QSet<UICloudEntityKey>  m_cloudEntityKeysBeingUpdated;
    398     /** @} */
    399 };
    400 
    401 #endif /* !FEQT_INCLUDED_SRC_manager_chooser_UIChooserAbstractModel_h */
     61#endif /* !FEQT_INCLUDED_SRC_manager_UICloudEntityKey_h */
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser/UIChooserAbstractModel.cpp

    r86756 r86783  
    346346    /* COM cleanup: */
    347347    COMBase::CleanupCOM();
    348 }
    349 
    350 
    351 /*********************************************************************************************************************************
    352 *   Class UICloudEntityKey implementation.                                                                                       *
    353 *********************************************************************************************************************************/
    354 
    355 UICloudEntityKey::UICloudEntityKey(const QString &strProviderShortName /* = QString() */,
    356                                    const QString &strProfileName /* = QString() */,
    357                                    const QUuid &uMachineId /* = QUuid() */)
    358     : m_strProviderShortName(strProviderShortName)
    359     , m_strProfileName(strProfileName)
    360     , m_uMachineId(uMachineId)
    361 {
    362 }
    363 
    364 UICloudEntityKey::UICloudEntityKey(const UICloudEntityKey &another)
    365     : m_strProviderShortName(another.m_strProviderShortName)
    366     , m_strProfileName(another.m_strProfileName)
    367     , m_uMachineId(another.m_uMachineId)
    368 {
    369 }
    370 
    371 bool UICloudEntityKey::operator==(const UICloudEntityKey &another) const
    372 {
    373     return    true
    374            && m_strProviderShortName == another.m_strProviderShortName
    375            && m_strProfileName == another.m_strProfileName
    376            && m_uMachineId == another.m_uMachineId
    377               ;
    378 }
    379 
    380 QString UICloudEntityKey::toString() const
    381 {
    382     QString strResult;
    383     if (m_strProviderShortName.isEmpty())
    384         return strResult;
    385     strResult += QString("/%1").arg(m_strProviderShortName);
    386     if (m_strProfileName.isEmpty())
    387         return strResult;
    388     strResult += QString("/%1").arg(m_strProfileName);
    389     if (m_uMachineId.isNull())
    390         return strResult;
    391     strResult += QString("/%1").arg(m_uMachineId.toString());
    392     return strResult;
    393348}
    394349
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser/UIChooserAbstractModel.h

    r86748 r86783  
    2828/* GUI includes: */
    2929#include "UIChooserDefs.h"
     30#include "UICloudEntityKey.h"
    3031#include "UIManagerDefs.h"
    3132
     
    3940class CCloudMachine;
    4041class CMachine;
    41 
    42 
    43 /** Cloud entity key definition. */
    44 struct UICloudEntityKey
    45 {
    46     /** Constructs cloud entity key on the basis of passed parameters.
    47       * @param  strProviderShortName  Brings provider short name.
    48       * @param  strProfileName        Brings profile name.
    49       * @param  uMachineId            Brings machine id. */
    50     UICloudEntityKey(const QString &strProviderShortName = QString(),
    51                      const QString &strProfileName = QString(),
    52                      const QUuid &uMachineId = QUuid());
    53     /** Constructs cloud entity key on the basis of @a another one. */
    54     UICloudEntityKey(const UICloudEntityKey &another);
    55 
    56     /** Returns whether this one key equals to @a another one. */
    57     bool operator==(const UICloudEntityKey &another) const;
    58 
    59     /** Returns string key representation. */
    60     QString toString() const;
    61 
    62     /** Holds provider short name. */
    63     QString m_strProviderShortName;
    64     /** Holds profile name. */
    65     QString m_strProfileName;
    66     /** Holds machine id. */
    67     QUuid m_uMachineId;
    68 };
    69 
    70 inline uint qHash(const UICloudEntityKey &key, uint uSeed)
    71 {
    72     return qHash(key.toString(), uSeed);
    73 }
    74 
    7542
    7643/** QObject extension used as VM Chooser-pane abstract model.
Note: See TracChangeset for help on using the changeset viewer.

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