Changeset 86783 in vbox for trunk/src/VBox/Frontends
- Timestamp:
- Nov 2, 2020 4:50:56 PM (4 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 3 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r86774 r86783 1058 1058 src/hostnetwork/UIHostNetworkManager.cpp \ 1059 1059 src/hostnetwork/UIHostNetworkUtils.cpp \ 1060 src/manager/UICloudEntityKey.cpp \ 1060 1061 src/manager/UIErrorPane.cpp \ 1061 1062 src/manager/UITaskCloudGetSettingsForm.cpp \ -
trunk/src/VBox/Frontends/VirtualBox/src/manager/UICloudEntityKey.cpp
r86768 r86783 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UIC hooserAbstractModelclass implementation.3 * VBox Qt GUI - UICloudEntityKey class implementation. 4 4 */ 5 5 … … 16 16 */ 17 17 18 /* Qtincludes: */19 #include <QThread>18 /* GUI includes: */ 19 #include "UICloudEntityKey.h" 20 20 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 QThread49 {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 QThread98 {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 continue222 * with common cleanup in case of failure.223 * We have to simulate a try-catch block. */224 CSession comSession;225 CMachine comMachine;226 do227 {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 *********************************************************************************************************************************/354 21 355 22 UICloudEntityKey::UICloudEntityKey(const QString &strProviderShortName /* = QString() */, … … 392 59 return strResult; 393 60 } 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 descriptors439 // (which reflecting group toggle-state) on-the-fly,440 // so for now we are additionally save group definitions441 // 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 make520 * 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 term550 * 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() const568 {569 return m_searchResults;570 }571 572 void UIChooserAbstractModel::saveGroups()573 {574 emit sigStartGroupSaving();575 }576 577 bool UIChooserAbstractModel::isGroupSavingInProgress() const578 {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) const645 {646 return m_cloudEntityKeysBeingUpdated.contains(key);647 }648 649 bool UIChooserAbstractModel::isCloudProfileUpdateInProgress() const650 {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 else741 {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 else1034 {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 else1214 {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_Local1274 && 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_Provider1323 || 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) const1342 {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) const1372 {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) const1589 {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 else1601 {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) const1621 {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_Local1700 && 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_Local1738 || 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 1 1 /* $Id$ */ 2 2 /** @file 3 * VBox Qt GUI - UIC hooserAbstractModelclass declaration.3 * VBox Qt GUI - UICloudEntityKey class declaration. 4 4 */ 5 5 … … 16 16 */ 17 17 18 #ifndef FEQT_INCLUDED_SRC_manager_ chooser_UIChooserAbstractModel_h19 #define FEQT_INCLUDED_SRC_manager_ chooser_UIChooserAbstractModel_h18 #ifndef FEQT_INCLUDED_SRC_manager_UICloudEntityKey_h 19 #define FEQT_INCLUDED_SRC_manager_UICloudEntityKey_h 20 20 #ifndef RT_WITHOUT_PRAGMA_ONCE 21 21 # pragma once … … 23 23 24 24 /* Qt includes: */ 25 #include <QSet> 25 #include <QHash> 26 #include <QString> 26 27 #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 42 28 43 29 /** Cloud entity key definition. */ … … 73 59 } 74 60 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 346 346 /* COM cleanup: */ 347 347 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) const372 {373 return true374 && m_strProviderShortName == another.m_strProviderShortName375 && m_strProfileName == another.m_strProfileName376 && m_uMachineId == another.m_uMachineId377 ;378 }379 380 QString UICloudEntityKey::toString() const381 {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;393 348 } 394 349 -
trunk/src/VBox/Frontends/VirtualBox/src/manager/chooser/UIChooserAbstractModel.h
r86748 r86783 28 28 /* GUI includes: */ 29 29 #include "UIChooserDefs.h" 30 #include "UICloudEntityKey.h" 30 31 #include "UIManagerDefs.h" 31 32 … … 39 40 class CCloudMachine; 40 41 class CMachine; 41 42 43 /** Cloud entity key definition. */44 struct UICloudEntityKey45 {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 75 42 76 43 /** QObject extension used as VM Chooser-pane abstract model.
Note:
See TracChangeset
for help on using the changeset viewer.