Index: trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk	(revision 83949)
+++ trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk	(revision 83950)
@@ -288,5 +288,5 @@
 VBOX_GUI_INC_DIRS = \
 	./src \
-	./src/cloud \
+	./src/cloud/profilemanager \
 	./src/converter \
 	./src/extensions \
@@ -614,6 +614,6 @@
 #
 VirtualBox_QT_MOCHDRS = \
-	src/cloud/UICloudProfileDetailsWidget.h \
-	src/cloud/UICloudProfileManager.h \
+	src/cloud/profilemanager/UICloudProfileDetailsWidget.h \
+	src/cloud/profilemanager/UICloudProfileManager.h \
 	src/globals/UIStarter.h \
 	src/hostnetwork/UIHostNetworkDetailsWidget.h \
@@ -1065,6 +1065,6 @@
 VirtualBox_SOURCES = \
 	src/main.cpp \
-	src/cloud/UICloudProfileDetailsWidget.cpp \
-	src/cloud/UICloudProfileManager.cpp \
+	src/cloud/profilemanager/UICloudProfileDetailsWidget.cpp \
+	src/cloud/profilemanager/UICloudProfileManager.cpp \
 	src/globals/UIStarter.cpp \
 	src/hostnetwork/UIHostNetworkDetailsWidget.cpp \
Index: trunk/src/VBox/Frontends/VirtualBox/src/cloud/UICloudProfileDetailsWidget.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/cloud/UICloudProfileDetailsWidget.cpp	(revision 83949)
+++ 	(revision )
@@ -1,409 +1,0 @@
-/* $Id$ */
-/** @file
- * VBox Qt GUI - UICloudProfileDetailsWidget class implementation.
- */
-
-/*
- * Copyright (C) 2009-2020 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-/* Qt includes: */
-#include <QGridLayout>
-#include <QHeaderView>
-#include <QLabel>
-#include <QLineEdit>
-#include <QPushButton>
-#include <QTableWidget>
-#include <QVBoxLayout>
-
-/* GUI includes: */
-#include "QIDialogButtonBox.h"
-#include "UICloudProfileDetailsWidget.h"
-
-/* Other VBox includes: */
-#include "iprt/assert.h"
-
-
-UICloudProfileDetailsWidget::UICloudProfileDetailsWidget(EmbedTo enmEmbedding, QWidget *pParent /* = 0 */)
-    : QIWithRetranslateUI<QWidget>(pParent)
-    , m_enmEmbedding(enmEmbedding)
-    , m_pTableWidget(0)
-    , m_pButtonBox(0)
-{
-    /* Prepare: */
-    prepare();
-}
-
-void UICloudProfileDetailsWidget::setData(const UIDataCloudProfile &data)
-{
-    /* Cache old/new data: */
-    m_oldData = data;
-    m_newData = m_oldData;
-
-    /* Load data: */
-    loadData();
-
-    /* Translate linked widgets: */
-    retranslateEditor();
-    retranslateButtons();
-}
-
-void UICloudProfileDetailsWidget::retranslateUi()
-{
-    /// @todo add description tool-tips
-
-    /* Translate name-editor label: */
-    m_pLabelName->setText(tr("Name:"));
-    /* Translate name-editor: */
-    retranslateEditor();
-
-    /* Translate table-widget label: */
-    m_pLabelTableWidget->setText(tr("Properties:"));
-    /* Translate table-widget: */
-    m_pTableWidget->setToolTip(tr("Contains cloud profile settings"));
-
-    /* Translate buttons: */
-    retranslateButtons();
-
-    /* Retranslate validation: */
-    retranslateValidation();
-
-    /* Update table tool-tips: */
-    updateTableToolTips();
-}
-
-void UICloudProfileDetailsWidget::retranslateEditor()
-{
-    /* Translate placeholders: */
-    m_pEditorName->setPlaceholderText(  m_oldData.m_strName.isNull()
-                                      ? tr("Enter a name for the new profile...")
-                                      : tr("Enter a name for this profile..."));
-}
-
-void UICloudProfileDetailsWidget::retranslateButtons()
-{
-    /* Translate button-box: */
-    if (m_pButtonBox)
-    {
-        /* Common: 'Reset' button: */
-        m_pButtonBox->button(QDialogButtonBox::Cancel)->setText(tr("Reset"));
-        m_pButtonBox->button(QDialogButtonBox::Cancel)->setStatusTip(tr("Reset changes in current profile details"));
-        m_pButtonBox->button(QDialogButtonBox::Cancel)->setShortcut(Qt::Key_Escape);
-        m_pButtonBox->button(QDialogButtonBox::Cancel)->
-            setToolTip(tr("Reset Changes (%1)").arg(m_pButtonBox->button(QDialogButtonBox::Cancel)->shortcut().toString()));
-
-        if (m_oldData.m_strName.isNull())
-        {
-            /* Provider: 'Add' button: */
-            m_pButtonBox->button(QDialogButtonBox::Ok)->setText(tr("Add"));
-            m_pButtonBox->button(QDialogButtonBox::Ok)->setStatusTip(tr("Add a new profile with following name"));
-            m_pButtonBox->button(QDialogButtonBox::Ok)->setShortcut(QString("Ctrl+Return"));
-            m_pButtonBox->button(QDialogButtonBox::Ok)->
-                setToolTip(tr("Add Profile (%1)").arg(m_pButtonBox->button(QDialogButtonBox::Ok)->shortcut().toString()));
-        }
-        else
-        {
-            /* Profile: 'Apply' button: */
-            m_pButtonBox->button(QDialogButtonBox::Ok)->setText(tr("Apply"));
-            m_pButtonBox->button(QDialogButtonBox::Ok)->setStatusTip(tr("Apply changes in current profile details"));
-            m_pButtonBox->button(QDialogButtonBox::Ok)->setShortcut(QString("Ctrl+Return"));
-            m_pButtonBox->button(QDialogButtonBox::Ok)->
-                setToolTip(tr("Apply Changes (%1)").arg(m_pButtonBox->button(QDialogButtonBox::Ok)->shortcut().toString()));
-        }
-    }
-}
-
-void UICloudProfileDetailsWidget::sltNameChanged(const QString &strName)
-{
-    /* Push changes back: */
-    m_newData.m_strName = strName;
-
-    /* Revalidate: */
-    revalidate(m_pEditorName);
-    /* Update button states: */
-    updateButtonStates();
-}
-
-void UICloudProfileDetailsWidget::sltTableChanged(QTableWidgetItem *pItem)
-{
-    /* Make sure item is valid: */
-    AssertPtrReturnVoid(pItem);
-    const int iRow = pItem->row();
-    AssertReturnVoid(iRow >= 0);
-
-    /* Skip if one of items isn't yet created.
-     * This can happen when 1st is already while 2nd isn't yet. */
-    QTableWidgetItem *pItemK = m_pTableWidget->item(iRow, 0);
-    QTableWidgetItem *pItemV = m_pTableWidget->item(iRow, 1);
-    if (!pItemK || !pItemV)
-        return;
-
-    /* Push changes back: */
-    const QString strKey = pItemK->text();
-    const QString strValue = pItemV->text();
-    m_newData.m_data[strKey] = qMakePair(strValue, m_newData.m_data.value(strKey).second);
-
-    /* Revalidate: */
-    revalidate(m_pTableWidget);
-    /* Update button states: */
-    updateButtonStates();
-}
-
-void UICloudProfileDetailsWidget::sltHandleButtonBoxClick(QAbstractButton *pButton)
-{
-    /* Make sure button-box exists: */
-    AssertPtrReturnVoid(m_pButtonBox);
-
-    /* Disable buttons first of all: */
-    m_pButtonBox->button(QDialogButtonBox::Cancel)->setEnabled(false);
-    m_pButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
-
-    /* Compare with known buttons: */
-    if (pButton == m_pButtonBox->button(QDialogButtonBox::Cancel))
-        emit sigDataChangeRejected();
-    else
-    if (pButton == m_pButtonBox->button(QDialogButtonBox::Ok))
-        emit sigDataChangeAccepted();
-}
-
-void UICloudProfileDetailsWidget::prepare()
-{
-    /* Prepare widgets: */
-    prepareWidgets();
-
-    /* Apply language settings: */
-    retranslateUi();
-
-    /* Update button states finally: */
-    updateButtonStates();
-}
-
-void UICloudProfileDetailsWidget::prepareWidgets()
-{
-    /* Create layout: */
-    QGridLayout *pLayout = new QGridLayout(this);
-    if (pLayout)
-    {
-        if (m_enmEmbedding == EmbedTo_Dialog)
-        {
-            pLayout->setContentsMargins(0, 0, 0, 0);
-#ifdef VBOX_WS_MAC
-            pLayout->setSpacing(10);
-#else
-            pLayout->setSpacing(qApp->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing) / 2);
-#endif
-        }
-        else
-        {
-#ifdef VBOX_WS_MAC
-            pLayout->setContentsMargins(13, 0, 13, 13);
-            pLayout->setSpacing(10);
-#else
-            const int iL = qApp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin) * 1.5;
-            const int iT = qApp->style()->pixelMetric(QStyle::PM_LayoutTopMargin) * 1.5;
-            const int iR = qApp->style()->pixelMetric(QStyle::PM_LayoutRightMargin) * 1.5;
-            const int iB = qApp->style()->pixelMetric(QStyle::PM_LayoutBottomMargin) * 1.5;
-            pLayout->setContentsMargins(iL, iT, iR, iB);
-#endif
-        }
-
-        /* Create name editor: */
-        m_pEditorName = new QLineEdit;
-        if (m_pEditorName)
-        {
-            connect(m_pEditorName, &QLineEdit::textChanged, this, &UICloudProfileDetailsWidget::sltNameChanged);
-
-            /* Add into layout: */
-            pLayout->addWidget(m_pEditorName, 0, 1);
-        }
-        /* Create name label: */
-        m_pLabelName = new QLabel;
-        if (m_pLabelName)
-        {
-            m_pLabelName->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
-            m_pLabelName->setBuddy(m_pEditorName);
-
-            /* Add into layout: */
-            pLayout->addWidget(m_pLabelName, 0, 0);
-        }
-
-        /* Create tab-widget: */
-        m_pTableWidget = new QTableWidget;
-        if (m_pTableWidget)
-        {
-            m_pTableWidget->setAlternatingRowColors(true);
-            m_pTableWidget->horizontalHeader()->setVisible(false);
-            m_pTableWidget->verticalHeader()->setVisible(false);
-            m_pTableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
-            connect(m_pTableWidget, &QTableWidget::itemChanged, this, &UICloudProfileDetailsWidget::sltTableChanged);
-
-            /* Add into layout: */
-            pLayout->addWidget(m_pTableWidget, 1, 1);
-        }
-        /* Create tab-widget label: */
-        m_pLabelTableWidget = new QLabel;
-        if (m_pLabelTableWidget)
-        {
-            m_pLabelTableWidget->setAlignment(Qt::AlignRight | Qt::AlignTop);
-            m_pLabelTableWidget->setBuddy(m_pTableWidget);
-
-            /* Add into layout: */
-            pLayout->addWidget(m_pLabelTableWidget, 1, 0);
-        }
-
-        /* If parent embedded into stack: */
-        if (m_enmEmbedding == EmbedTo_Stack)
-        {
-            /* Create button-box: */
-            m_pButtonBox = new QIDialogButtonBox;
-            if  (m_pButtonBox)
-            {
-                m_pButtonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
-                connect(m_pButtonBox, &QIDialogButtonBox::clicked, this, &UICloudProfileDetailsWidget::sltHandleButtonBoxClick);
-
-                /* Add into layout: */
-                pLayout->addWidget(m_pButtonBox, 2, 0, 1, 2);
-            }
-        }
-    }
-}
-
-void UICloudProfileDetailsWidget::loadData()
-{
-    /* Clear table initially: */
-    m_pTableWidget->clear();
-
-    /* Fill name editor: */
-    m_pEditorName->setText(m_oldData.m_strName);
-
-    /* Configure table: */
-    m_pTableWidget->setRowCount(m_oldData.m_data.keys().size());
-    m_pTableWidget->setColumnCount(2);
-
-    /* Push acquired keys/values to data fields: */
-    for (int i = 0; i < m_pTableWidget->rowCount(); ++i)
-    {
-        /* Gather values: */
-        const QString strKey = m_oldData.m_data.keys().at(i);
-        const QString strValue = m_oldData.m_data.value(strKey).first;
-        const QString strToolTip = m_oldData.m_data.value(strKey).second;
-
-        /* Create key item: */
-        QTableWidgetItem *pItemK = new QTableWidgetItem(strKey);
-        if (pItemK)
-        {
-            /* Non-editable for sure, but non-selectable? */
-            pItemK->setFlags(pItemK->flags() & ~Qt::ItemIsEditable);
-            /* Use non-translated description as tool-tip: */
-            pItemK->setData(Qt::UserRole, strToolTip);
-
-            /* Insert into table: */
-            m_pTableWidget->setItem(i, 0, pItemK);
-        }
-
-        /* Create value item: */
-        QTableWidgetItem *pItemV = new QTableWidgetItem(strValue);
-        if (pItemV)
-        {
-            /* Use the value as tool-tip, there can be quite long values: */
-            pItemV->setToolTip(strValue);
-
-            /* Insert into table: */
-            m_pTableWidget->setItem(i, 1, pItemV);
-        }
-    }
-
-    /* Update table tooltips: */
-    updateTableToolTips();
-    /* Adjust table contents: */
-    adjustTableContents();
-}
-
-void UICloudProfileDetailsWidget::revalidate(QWidget *pWidget /* = 0 */)
-{
-    /// @todo validate profile settings table!
-
-    /* Retranslate validation: */
-    retranslateValidation(pWidget);
-}
-
-void UICloudProfileDetailsWidget::retranslateValidation(QWidget *pWidget /* = 0 */)
-{
-    Q_UNUSED(pWidget);
-
-    /// @todo translate vaidation errors!
-}
-
-void UICloudProfileDetailsWidget::updateTableToolTips()
-{
-    /* Iterate through all the key items: */
-    for (int i = 0; i < m_pTableWidget->rowCount(); ++i)
-    {
-        /* Acquire current key item: */
-        QTableWidgetItem *pItemK = m_pTableWidget->item(i, 0);
-        if (pItemK)
-        {
-            const QString strToolTip = pItemK->data(Qt::UserRole).toString();
-            pItemK->setToolTip(tr(strToolTip.toUtf8().constData()));
-        }
-    }
-}
-
-void UICloudProfileDetailsWidget::adjustTableContents()
-{
-    /* Disable last column stretching temporary: */
-    m_pTableWidget->horizontalHeader()->setStretchLastSection(false);
-
-    /* Resize both columns to contents: */
-    m_pTableWidget->resizeColumnsToContents();
-    /* Then acquire full available width: */
-    const int iFullWidth = m_pTableWidget->viewport()->width();
-    /* First column should not be less than it's minimum size, last gets the rest: */
-    const int iMinimumWidth0 = qMin(m_pTableWidget->horizontalHeader()->sectionSize(0), iFullWidth / 2);
-    m_pTableWidget->horizontalHeader()->resizeSection(0, iMinimumWidth0);
-
-    /* Enable last column stretching again: */
-    m_pTableWidget->horizontalHeader()->setStretchLastSection(true);
-}
-
-void UICloudProfileDetailsWidget::updateButtonStates()
-{
-#if 0
-    if (m_oldData != m_newData)
-    {
-        printf("Old data:\n");
-        foreach (const QString &strKey, m_oldData.m_data.keys())
-        {
-            const QString strValue = m_oldData.m_data.value(strKey).first;
-            const QString strDecription = m_oldData.m_data.value(strKey).second;
-            printf(" %s: %s, %s\n", strKey.toUtf8().constData(), strValue.toUtf8().constData(), strDecription.toUtf8().constData());
-        }
-        printf("New data:\n");
-        foreach (const QString &strKey, m_newData.m_data.keys())
-        {
-            const QString strValue = m_newData.m_data.value(strKey).first;
-            const QString strDecription = m_newData.m_data.value(strKey).second;
-            printf(" %s: %s, %s\n", strKey.toUtf8().constData(), strValue.toUtf8().constData(), strDecription.toUtf8().constData());
-        }
-        printf("\n");
-    }
-#endif
-
-    /* Update 'Apply' / 'Reset' button states: */
-    if (m_pButtonBox)
-    {
-        m_pButtonBox->button(QDialogButtonBox::Cancel)->setEnabled(m_oldData != m_newData);
-        m_pButtonBox->button(QDialogButtonBox::Ok)->setEnabled(m_oldData != m_newData);
-    }
-
-    /* Notify listeners as well: */
-    emit sigDataChanged(m_oldData != m_newData);
-}
Index: trunk/src/VBox/Frontends/VirtualBox/src/cloud/UICloudProfileDetailsWidget.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/cloud/UICloudProfileDetailsWidget.h	(revision 83949)
+++ 	(revision )
@@ -1,213 +1,0 @@
-/* $Id$ */
-/** @file
- * VBox Qt GUI - UICloudProfileDetailsWidget class declaration.
- */
-
-/*
- * Copyright (C) 2009-2020 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#ifndef FEQT_INCLUDED_SRC_cloud_UICloudProfileDetailsWidget_h
-#define FEQT_INCLUDED_SRC_cloud_UICloudProfileDetailsWidget_h
-#ifndef RT_WITHOUT_PRAGMA_ONCE
-# pragma once
-#endif
-
-/* Qt includes: */
-#include <QMap>
-#include <QUuid>
-#include <QWidget>
-
-/* GUI includes: */
-#include "QIManagerDialog.h"
-#include "QIWithRetranslateUI.h"
-
-/* Forward declarations: */
-class QAbstractButton;
-class QLabel;
-class QLineEdit;
-class QTableWidget;
-class QTableWidgetItem;
-class QIDialogButtonBox;
-
-
-/** Cloud Provider data structure. */
-struct UIDataCloudProvider
-{
-    /** Constructs data. */
-    UIDataCloudProvider()
-        : m_strName(QString())
-    {}
-
-    /** Returns whether the @a other passed data is equal to this one. */
-    bool equal(const UIDataCloudProvider &other) const
-    {
-        return true
-               && (m_uuid == other.m_uuid)
-               && (m_strName == other.m_strName)
-               ;
-    }
-
-    /** Returns whether the @a other passed data is equal to this one. */
-    bool operator==(const UIDataCloudProvider &other) const { return equal(other); }
-    /** Returns whether the @a other passed data is different from this one. */
-    bool operator!=(const UIDataCloudProvider &other) const { return !equal(other); }
-
-    /** Holds the provider ID. */
-    QUuid    m_uuid;
-    /** Holds the provider name. */
-    QString  m_strName;
-
-    /** Holds the profile supported property descriptions. */
-    QMap<QString, QString>  m_propertyDescriptions;
-};
-
-/** Cloud Profile data structure. */
-struct UIDataCloudProfile
-{
-    /** Constructs data. */
-    UIDataCloudProfile()
-        : m_strName(QString())
-    {}
-
-    /** Returns whether the @a other passed data is equal to this one. */
-    bool equal(const UIDataCloudProfile &other) const
-    {
-        return true
-               && (m_strName == other.m_strName)
-               && (m_data == other.m_data)
-               ;
-    }
-
-    /** Returns whether the @a other passed data is equal to this one. */
-    bool operator==(const UIDataCloudProfile &other) const { return equal(other); }
-    /** Returns whether the @a other passed data is different from this one. */
-    bool operator!=(const UIDataCloudProfile &other) const { return !equal(other); }
-
-    /** Holds the profile name. */
-    QString  m_strName;
-
-    /** Holds the profile data. */
-    QMap<QString, QPair<QString, QString> >  m_data;
-};
-
-
-/** Cloud Profile details widget. */
-class UICloudProfileDetailsWidget : public QIWithRetranslateUI<QWidget>
-{
-    Q_OBJECT;
-
-signals:
-
-    /** Notifies listeners about data changed and whether it @a fDiffers. */
-    void sigDataChanged(bool fDiffers);
-
-    /** Notifies listeners about data change rejected and should be reseted. */
-    void sigDataChangeRejected();
-    /** Notifies listeners about data change accepted and should be applied. */
-    void sigDataChangeAccepted();
-
-public:
-
-    /** Constructs cloud profile details widget passing @a pParent to the base-class.
-      * @param  enmEmbedding  Brings embedding type. */
-    UICloudProfileDetailsWidget(EmbedTo enmEmbedding, QWidget *pParent = 0);
-
-    /** Returns the cloud profile data. */
-    const UIDataCloudProfile &data() const { return m_newData; }
-    /** Defines the cloud profile @a data. */
-    void setData(const UIDataCloudProfile &data);
-
-protected:
-
-    /** Handles translation event. */
-    virtual void retranslateUi() /* override */;
-    /** Handles editor translation. */
-    void retranslateEditor();
-    /** Handles buttons translation. */
-    void retranslateButtons();
-
-private slots:
-
-    /** @name Change handling stuff.
-      * @{ */
-        /** Handles name change. */
-        void sltNameChanged(const QString &strName);
-        /** Handles table change. */
-        void sltTableChanged(QTableWidgetItem *pItem);
-
-        /** Handles button-box button click. */
-        void sltHandleButtonBoxClick(QAbstractButton *pButton);
-    /** @} */
-
-private:
-
-    /** @name Prepare/cleanup cascade.
-      * @{ */
-        /** Prepares all. */
-        void prepare();
-        /** Prepares widgets. */
-        void prepareWidgets();
-    /** @} */
-
-    /** @name Loading stuff.
-      * @{ */
-        /** Loads data. */
-        void loadData();
-    /** @} */
-
-    /** @name Change handling stuff.
-      * @{ */
-        /** Revalidates changes for passed @a pWidget. */
-        void revalidate(QWidget *pWidget = 0);
-
-        /** Retranslates validation for passed @a pWidget. */
-        void retranslateValidation(QWidget *pWidget = 0);
-
-        /** Updates table tooltips. */
-        void updateTableToolTips();
-        /** Adjusts table contents. */
-        void adjustTableContents();
-
-        /** Updates button states. */
-        void updateButtonStates();
-    /** @} */
-
-    /** @name General variables.
-      * @{ */
-        /** Holds the parent widget embedding type. */
-        const EmbedTo  m_enmEmbedding;
-
-        /** Holds the old data copy. */
-        UIDataCloudProfile  m_oldData;
-        /** Holds the new data copy. */
-        UIDataCloudProfile  m_newData;
-    /** @} */
-
-    /** @name Widget variables.
-      * @{ */
-        /** Holds the name label instance. */
-        QLabel    *m_pLabelName;
-        /** Holds the name editor instance. */
-        QLineEdit *m_pEditorName;
-
-        /** Holds the table-widget label instance. */
-        QLabel       *m_pLabelTableWidget;
-        /** Holds the table-widget instance. */
-        QTableWidget *m_pTableWidget;
-
-        /** Holds the server button-box instance. */
-        QIDialogButtonBox *m_pButtonBox;
-    /** @} */
-};
-
-
-#endif /* !FEQT_INCLUDED_SRC_cloud_UICloudProfileDetailsWidget_h */
Index: trunk/src/VBox/Frontends/VirtualBox/src/cloud/UICloudProfileManager.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/cloud/UICloudProfileManager.cpp	(revision 83949)
+++ 	(revision )
@@ -1,978 +1,0 @@
-/* $Id$ */
-/** @file
- * VBox Qt GUI - UICloudProfileManager class implementation.
- */
-
-/*
- * Copyright (C) 2009-2020 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-/* Qt includes: */
-#include <QHeaderView>
-#include <QPushButton>
-#include <QVBoxLayout>
-
-/* GUI includes: */
-#include "QIDialogButtonBox.h"
-#include "QIInputDialog.h"
-#include "QITreeWidget.h"
-#include "UICommon.h"
-#include "UIActionPoolManager.h"
-#include "UIExtraDataManager.h"
-#include "UIIconPool.h"
-#include "UICloudProfileDetailsWidget.h"
-#include "UICloudProfileManager.h"
-#include "UIMessageCenter.h"
-#include "UIToolBar.h"
-#ifdef VBOX_WS_MAC
-# include "UIWindowMenuManager.h"
-#endif
-
-/* COM includes: */
-#include "CCloudProfile.h"
-#include "CCloudProvider.h"
-#include "CCloudProviderManager.h"
-
-
-/** Tree-widget item types. */
-enum CloudItemType
-{
-    CloudItemType_Provider = QTreeWidgetItem::UserType + 1,
-    CloudItemType_Profile  = QTreeWidgetItem::UserType + 2
-};
-Q_DECLARE_METATYPE(CloudItemType);
-
-/** Tree-widget data types. */
-enum
-{
-    Data_ItemType   = Qt::UserRole + 1,
-    Data_ProviderID = Qt::UserRole + 2,
-};
-
-/** Tree-widget column types. */
-enum
-{
-    Column_Name,
-    Column_Max
-};
-
-
-/** Cloud Profile Manager provider's tree-widget item. */
-class UIItemCloudProvider : public QITreeWidgetItem, public UIDataCloudProvider
-{
-public:
-
-    /** Constructs item. */
-    UIItemCloudProvider();
-
-    /** Updates item fields from base-class data. */
-    void updateFields();
-
-    /** Returns item name. */
-    QString name() const { return m_strName; }
-};
-
-/** Cloud Profile Manager profile's tree-widget item. */
-class UIItemCloudProfile : public QITreeWidgetItem, public UIDataCloudProfile
-{
-public:
-
-    /** Constructs item. */
-    UIItemCloudProfile();
-
-    /** Updates item fields from base-class data. */
-    void updateFields();
-
-    /** Returns item name. */
-    QString name() const { return m_strName; }
-};
-
-
-/*********************************************************************************************************************************
-*   Class UIItemCloudProvider implementation.                                                                                    *
-*********************************************************************************************************************************/
-
-UIItemCloudProvider::UIItemCloudProvider()
-{
-    /* Assign icon: */
-    setIcon(Column_Name, UIIconPool::iconSet(":/provider_oracle_16px.png"));
-    /* Assign item type: */
-    setData(Column_Name, Data_ItemType, QVariant::fromValue(CloudItemType_Provider));
-}
-
-void UIItemCloudProvider::updateFields()
-{
-    /* Update item fields: */
-    setText(Column_Name, m_strName);
-    setData(Column_Name, Data_ProviderID, m_uuid);
-}
-
-
-/*********************************************************************************************************************************
-*   Class UIItemCloudProfile implementation.                                                                                     *
-*********************************************************************************************************************************/
-
-UIItemCloudProfile::UIItemCloudProfile()
-{
-    /* Assign icon: */
-    setIcon(Column_Name, UIIconPool::iconSet(":/profile_16px.png"));
-    /* Assign item type: */
-    setData(Column_Name, Data_ItemType, QVariant::fromValue(CloudItemType_Profile));
-}
-
-void UIItemCloudProfile::updateFields()
-{
-    /* Update item fields: */
-    setText(Column_Name, m_strName);
-}
-
-
-/*********************************************************************************************************************************
-*   Class UICloudProfileManagerWidget implementation.                                                                            *
-*********************************************************************************************************************************/
-
-UICloudProfileManagerWidget::UICloudProfileManagerWidget(EmbedTo enmEmbedding, UIActionPool *pActionPool,
-                                                         bool fShowToolbar /* = true */, QWidget *pParent /* = 0 */)
-    : QIWithRetranslateUI<QWidget>(pParent)
-    , m_enmEmbedding(enmEmbedding)
-    , m_pActionPool(pActionPool)
-    , m_fShowToolbar(fShowToolbar)
-    , m_pToolBar(0)
-    , m_pTreeWidget(0)
-    , m_pDetailsWidget(0)
-{
-    /* Prepare: */
-    prepare();
-}
-
-QMenu *UICloudProfileManagerWidget::menu() const
-{
-    return m_pActionPool->action(UIActionIndexST_M_CloudWindow)->menu();
-}
-
-void UICloudProfileManagerWidget::retranslateUi()
-{
-    /* Adjust toolbar: */
-#ifdef VBOX_WS_MAC
-    // WORKAROUND:
-    // There is a bug in Qt Cocoa which result in showing a "more arrow" when
-    // the necessary size of the toolbar is increased. Also for some languages
-    // the with doesn't match if the text increase. So manually adjust the size
-    // after changing the text.
-    if (m_pToolBar)
-        m_pToolBar->updateLayout();
-#endif
-}
-
-void UICloudProfileManagerWidget::sltResetCloudProfileDetailsChanges()
-{
-    /* Just push the current item data there again: */
-    sltHandleCurrentItemChange();
-}
-
-void UICloudProfileManagerWidget::sltApplyCloudProfileDetailsChanges()
-{
-    /* Is can be that there is provider item, not profile item currently selected.
-     * In such case we are not applying parameters, we are creating new one profile. */
-    QTreeWidgetItem *pItem = m_pTreeWidget->currentItem();
-    UIItemCloudProvider *pMaybeProviderItem = pItem && pItem->data(0, Data_ItemType).value<CloudItemType>() == CloudItemType_Provider
-                                            ? static_cast<UIItemCloudProvider*>(pItem) : 0;
-    if (pMaybeProviderItem)
-        return sltAddCloudProfile();
-
-    /* Get profile item: */
-    UIItemCloudProfile *pProfileItem = static_cast<UIItemCloudProfile*>(m_pTreeWidget->currentItem());
-    AssertMsgReturnVoid(pProfileItem, ("Current item must not be null!\n"));
-
-    /* Get item data: */
-    UIDataCloudProfile oldData = *pProfileItem;
-    UIDataCloudProfile newData = m_pDetailsWidget->data();
-
-    /* Get VirtualBox for further activities: */
-    const CVirtualBox comVBox = uiCommon().virtualBox();
-
-    /* Get CloudProviderManager for further activities: */
-    CCloudProviderManager comCloudProviderManager = comVBox.GetCloudProviderManager();
-    /* Show error message if necessary: */
-    if (!comVBox.isOk())
-        msgCenter().cannotAcquireCloudProviderManager(comVBox, this);
-    else
-    {
-        /* Get provider item: */
-        UIItemCloudProvider *pProviderItem = static_cast<UIItemCloudProvider*>(pProfileItem->parentItem());
-        /* Acquire provider ID: */
-        const QUuid uId = pProviderItem->data(Column_Name, Data_ProviderID).toUuid();
-
-        /* Look for corresponding provider: */
-        CCloudProvider comCloudProvider = comCloudProviderManager.GetProviderById(uId);
-        /* Show error message if necessary: */
-        if (!comCloudProviderManager.isOk())
-            msgCenter().cannotFindCloudProvider(comCloudProviderManager, uId, this);
-        else
-        {
-            /* Look for corresponding profile: */
-            CCloudProfile comCloudProfile = comCloudProvider.GetProfileByName(oldData.m_strName);
-            /* Show error message if necessary: */
-            if (!comCloudProvider.isOk())
-                msgCenter().cannotFindCloudProfile(comCloudProvider, oldData.m_strName, this);
-            else
-            {
-                /* Set profile name, if necessary: */
-                if (newData.m_strName != oldData.m_strName)
-                    comCloudProfile.SetName(newData.m_strName);
-                /* Show error message if necessary: */
-                if (!comCloudProfile.isOk())
-                    msgCenter().cannotAssignCloudProfileParameter(comCloudProfile, this);
-                else
-                {
-                    /* Iterate through old/new data: */
-                    foreach (const QString &strKey, oldData.m_data.keys())
-                    {
-                        /* Get values: */
-                        const QString strOldValue = oldData.m_data.value(strKey).first;
-                        const QString strNewValue = newData.m_data.value(strKey).first;
-                        if (strNewValue != strOldValue)
-                        {
-                            /* Apply property: */
-                            comCloudProfile.SetProperty(strKey, strNewValue);
-                            /* Show error message if necessary: */
-                            if (!comCloudProfile.isOk())
-                            {
-                                msgCenter().cannotAssignCloudProfileParameter(comCloudProfile, this);
-                                break;
-                            }
-                        }
-                    }
-                }
-
-                /* If profile is Ok finally: */
-                if (comCloudProfile.isOk())
-                {
-                    /* Update profile in the tree: */
-                    UIDataCloudProfile data;
-                    loadCloudProfile(comCloudProfile, *pProviderItem, data);
-                    updateItemForCloudProfile(data, true, pProfileItem);
-
-                    /* Make sure current item fetched: */
-                    sltHandleCurrentItemChange();
-
-                    /* Save profile changes: */
-                    comCloudProvider.SaveProfiles();
-                    /* Show error message if necessary: */
-                    if (!comCloudProvider.isOk())
-                        msgCenter().cannotSaveCloudProfiles(comCloudProvider, this);
-                }
-            }
-        }
-    }
-
-    /* Notify listeners: */
-    emit sigChange();
-}
-
-void UICloudProfileManagerWidget::sltAddCloudProfile()
-{
-    /* Get provider item: */
-    UIItemCloudProvider *pProviderItem = static_cast<UIItemCloudProvider*>(m_pTreeWidget->currentItem());
-    AssertMsgReturnVoid(pProviderItem, ("Current item must not be null!\n"));
-
-    /* Acquire profile name if not proposed by details widget: */
-    QString strProfileName = m_pDetailsWidget->data().m_strName;
-    if (strProfileName.isEmpty())
-    {
-        bool fCancelled = true;
-        QISafePointerInputDialog pDialog = new QIInputDialog(this);
-        if (pDialog)
-        {
-            pDialog->setWindowIcon(UIIconPool::iconSet(":/cloud_profile_add_16px.png"));
-            pDialog->setWindowTitle(UICloudProfileManager::tr("Add Profile"));
-            if (pDialog->exec() == QDialog::Accepted)
-            {
-                strProfileName = pDialog->textValue();
-                fCancelled = false;
-            }
-            delete pDialog;
-        }
-        if (fCancelled)
-            return;
-    }
-
-    /* Get VirtualBox for further activities: */
-    const CVirtualBox comVBox = uiCommon().virtualBox();
-
-    /* Get CloudProviderManager for further activities: */
-    CCloudProviderManager comCloudProviderManager = comVBox.GetCloudProviderManager();
-    /* Show error message if necessary: */
-    if (!comVBox.isOk())
-        msgCenter().cannotAcquireCloudProviderManager(comVBox, this);
-    else
-    {
-        /* Acquire provider ID: */
-        const QUuid uId = pProviderItem->data(Column_Name, Data_ProviderID).toUuid();
-
-        /* Look for corresponding provider: */
-        CCloudProvider comCloudProvider = comCloudProviderManager.GetProviderById(uId);
-        /* Show error message if necessary: */
-        if (!comCloudProviderManager.isOk())
-            msgCenter().cannotFindCloudProvider(comCloudProviderManager, uId, this);
-        else
-        {
-            /* Create new profile: */
-            const QVector<QString> keys = pProviderItem->m_propertyDescriptions.keys().toVector();
-            const QVector<QString> values(keys.size());
-            comCloudProvider.CreateProfile(strProfileName, keys, values);
-
-            /* Show error message if necessary: */
-            if (!comCloudProvider.isOk())
-                msgCenter().cannotCreateCloudProfle(comCloudProvider, this);
-            else
-            {
-                /* Look for corresponding profile: */
-                CCloudProfile comCloudProfile = comCloudProvider.GetProfileByName(strProfileName);
-                /* Show error message if necessary: */
-                if (!comCloudProvider.isOk())
-                    msgCenter().cannotFindCloudProfile(comCloudProvider, strProfileName, this);
-                else
-                {
-                    /* Add profile to the tree: */
-                    UIDataCloudProfile data;
-                    loadCloudProfile(comCloudProfile, *pProviderItem, data);
-                    createItemForCloudProfile(pProviderItem, data, true);
-
-                    /* Save profile changes: */
-                    comCloudProvider.SaveProfiles();
-                    /* Show error message if necessary: */
-                    if (!comCloudProvider.isOk())
-                        msgCenter().cannotSaveCloudProfiles(comCloudProvider, this);
-                }
-            }
-        }
-    }
-
-    /* Notify listeners: */
-    emit sigChange();
-}
-
-void UICloudProfileManagerWidget::sltImportCloudProfiles()
-{
-    /* Get provider item: */
-    UIItemCloudProvider *pProviderItem = static_cast<UIItemCloudProvider*>(m_pTreeWidget->currentItem());
-    AssertMsgReturnVoid(pProviderItem, ("Current item must not be null!\n"));
-
-    /* If there are profiles exist => confirm cloud profile import. */
-    if (   pProviderItem->childCount() != 0
-        && !msgCenter().confirmCloudProfilesImport(this))
-        return;
-
-    /* Get VirtualBox for further activities: */
-    const CVirtualBox comVBox = uiCommon().virtualBox();
-
-    /* Get CloudProviderManager for further activities: */
-    CCloudProviderManager comCloudProviderManager = comVBox.GetCloudProviderManager();
-    /* Show error message if necessary: */
-    if (!comVBox.isOk())
-        msgCenter().cannotAcquireCloudProviderManager(comVBox, this);
-    else
-    {
-        /* Acquire provider ID: */
-        const QUuid uId = pProviderItem->data(Column_Name, Data_ProviderID).toUuid();
-
-        /* Look for corresponding provider: */
-        CCloudProvider comCloudProvider = comCloudProviderManager.GetProviderById(uId);
-        /* Show error message if necessary: */
-        if (!comCloudProviderManager.isOk())
-            msgCenter().cannotFindCloudProvider(comCloudProviderManager, uId, this);
-        else
-        {
-            /* Import profiles: */
-            comCloudProvider.ImportProfiles();
-
-            /* Show error message if necessary: */
-            if (!comCloudProvider.isOk())
-                msgCenter().cannotImportCloudProfiles(comCloudProvider, this);
-            else
-                loadCloudStuff();
-        }
-    }
-
-    /* Notify listeners: */
-    emit sigChange();
-}
-
-void UICloudProfileManagerWidget::sltRemoveCloudProfile()
-{
-    /* Get profile item: */
-    UIItemCloudProfile *pProfileItem = static_cast<UIItemCloudProfile*>(m_pTreeWidget->currentItem());
-    AssertMsgReturnVoid(pProfileItem, ("Current item must not be null!\n"));
-
-    /* Get profile name: */
-    const QString strProfileName(pProfileItem->name());
-
-    /* Confirm cloud profile removal: */
-    if (!msgCenter().confirmCloudProfileRemoval(strProfileName, this))
-        return;
-
-    /* Get VirtualBox for further activities: */
-    const CVirtualBox comVBox = uiCommon().virtualBox();
-
-    /* Get CloudProviderManager for further activities: */
-    CCloudProviderManager comCloudProviderManager = comVBox.GetCloudProviderManager();
-    /* Show error message if necessary: */
-    if (!comVBox.isOk())
-        msgCenter().cannotAcquireCloudProviderManager(comVBox, this);
-    else
-    {
-        /* Get provider item: */
-        UIItemCloudProvider *pProviderItem = static_cast<UIItemCloudProvider*>(pProfileItem->parentItem());
-        /* Acquire provider ID: */
-        const QUuid uId = pProviderItem->data(Column_Name, Data_ProviderID).toUuid();
-
-        /* Look for corresponding provider: */
-        CCloudProvider comCloudProvider = comCloudProviderManager.GetProviderById(uId);
-        /* Show error message if necessary: */
-        if (!comCloudProviderManager.isOk())
-            msgCenter().cannotFindCloudProvider(comCloudProviderManager, uId, this);
-        else
-        {
-            /* Look for corresponding profile: */
-            CCloudProfile comCloudProfile = comCloudProvider.GetProfileByName(strProfileName);
-            /* Show error message if necessary: */
-            if (!comCloudProvider.isOk())
-                msgCenter().cannotFindCloudProfile(comCloudProvider, strProfileName, this);
-            else
-            {
-                /* Remove current profile: */
-                comCloudProfile.Remove();
-                /// @todo how do we check that?
-
-                /* Remove interface from the tree: */
-                delete pProfileItem;
-
-                /* Save profile changes: */
-                comCloudProvider.SaveProfiles();
-                /* Show error message if necessary: */
-                if (!comCloudProvider.isOk())
-                    msgCenter().cannotSaveCloudProfiles(comCloudProvider, this);
-            }
-        }
-    }
-
-    /* Notify listeners: */
-    emit sigChange();
-}
-
-void UICloudProfileManagerWidget::sltToggleCloudProfileDetailsVisibility(bool fVisible)
-{
-    /* Save the setting: */
-    gEDataManager->setCloudProfileManagerDetailsExpanded(fVisible);
-    /* Show/hide details area and Apply button: */
-    m_pDetailsWidget->setVisible(fVisible);
-    /* Notify external lsiteners: */
-    emit sigCloudProfileDetailsVisibilityChanged(fVisible);
-}
-
-void UICloudProfileManagerWidget::sltShowCloudProfileTryPage()
-{
-    uiCommon().openURL("https://myservices.us.oraclecloud.com/mycloud/signup");
-}
-
-void UICloudProfileManagerWidget::sltShowCloudProfileHelp()
-{
-    uiCommon().openURL("https://docs.cloud.oracle.com/iaas/Content/API/Concepts/sdkconfig.htm");
-}
-
-void UICloudProfileManagerWidget::sltHandleCurrentItemChange()
-{
-    /* Get items: */
-    QTreeWidgetItem *pItem = m_pTreeWidget->currentItem();
-    UIItemCloudProvider *pItemProvider = pItem && pItem->data(0, Data_ItemType).value<CloudItemType>() == CloudItemType_Provider
-                                       ? static_cast<UIItemCloudProvider*>(pItem)
-                                       : 0;
-    UIItemCloudProfile  *pItemProfile  = pItem && pItem->data(0, Data_ItemType).value<CloudItemType>() == CloudItemType_Profile
-                                       ? static_cast<UIItemCloudProfile*>(pItem)
-                                       : 0;
-
-    /* Update actions availability: */
-    m_pActionPool->action(UIActionIndexST_M_Cloud_S_Add)->setEnabled(!pItem || pItemProvider);
-    m_pActionPool->action(UIActionIndexST_M_Cloud_S_Import)->setEnabled(!pItem || pItemProvider);
-    m_pActionPool->action(UIActionIndexST_M_Cloud_S_Remove)->setEnabled(pItemProfile);
-    m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details)->setEnabled(pItemProfile || pItemProvider);
-
-    /* If there is an item => update details data: */
-    if (pItemProfile)
-        m_pDetailsWidget->setData(*pItemProfile);
-    /* Otherwise => clear details data: */
-    else
-        m_pDetailsWidget->setData(UIDataCloudProfile());
-
-    /* Update details area visibility: */
-    sltToggleCloudProfileDetailsVisibility(pItem && m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details)->isChecked());
-}
-
-void UICloudProfileManagerWidget::sltHandleContextMenuRequest(const QPoint &position)
-{
-    /* Get items: */
-    QTreeWidgetItem *pItem = m_pTreeWidget->itemAt(position);
-    UIItemCloudProvider *pItemProvider = pItem && pItem->data(0, Data_ItemType).value<CloudItemType>() == CloudItemType_Provider
-                                       ? static_cast<UIItemCloudProvider*>(pItem)
-                                       : 0;
-    UIItemCloudProfile  *pItemProfile  = pItem && pItem->data(0, Data_ItemType).value<CloudItemType>() == CloudItemType_Profile
-                                       ? static_cast<UIItemCloudProfile*>(pItem)
-                                       : 0;
-
-    /* Compose temporary context-menu: */
-    QMenu menu;
-    if (pItemProfile)
-    {
-        menu.addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Remove));
-        menu.addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details));
-    }
-    else if (pItemProvider)
-    {
-        menu.addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Add));
-        menu.addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Import));
-        menu.addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details));
-    }
-
-    /* And show it: */
-    menu.exec(m_pTreeWidget->mapToGlobal(position));
-}
-
-void UICloudProfileManagerWidget::prepare()
-{
-    /* Prepare actions: */
-    prepareActions();
-    /* Prepare widgets: */
-    prepareWidgets();
-
-    /* Load settings: */
-    loadSettings();
-
-    /* Apply language settings: */
-    retranslateUi();
-
-    /* Load cloud stuff: */
-    loadCloudStuff();
-}
-
-void UICloudProfileManagerWidget::prepareActions()
-{
-    /* First of all, add actions which has smaller shortcut scope: */
-    addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Add));
-    addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Import));
-    addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Remove));
-    addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details));
-    addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_TryPage));
-    addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Help));
-
-    /* Connect actions: */
-    connect(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Add), &QAction::triggered,
-            this, &UICloudProfileManagerWidget::sltAddCloudProfile);
-    connect(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Import), &QAction::triggered,
-            this, &UICloudProfileManagerWidget::sltImportCloudProfiles);
-    connect(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Remove), &QAction::triggered,
-            this, &UICloudProfileManagerWidget::sltRemoveCloudProfile);
-    connect(m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details), &QAction::toggled,
-            this, &UICloudProfileManagerWidget::sltToggleCloudProfileDetailsVisibility);
-    connect(m_pActionPool->action(UIActionIndexST_M_Cloud_S_TryPage), &QAction::triggered,
-            this, &UICloudProfileManagerWidget::sltShowCloudProfileTryPage);
-    connect(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Help), &QAction::triggered,
-            this, &UICloudProfileManagerWidget::sltShowCloudProfileHelp);
-}
-
-void UICloudProfileManagerWidget::prepareWidgets()
-{
-    /* Create main-layout: */
-    new QVBoxLayout(this);
-    if (layout())
-    {
-        /* Configure layout: */
-        layout()->setContentsMargins(0, 0, 0, 0);
-#ifdef VBOX_WS_MAC
-        layout()->setSpacing(10);
-#else
-        layout()->setSpacing(qApp->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing) / 2);
-#endif
-
-        /* Prepare toolbar, if requested: */
-        if (m_fShowToolbar)
-            prepareToolBar();
-        /* Prepare tree-widget: */
-        prepareTreeWidget();
-        /* Prepare details-widget: */
-        prepareDetailsWidget();
-    }
-}
-
-void UICloudProfileManagerWidget::prepareToolBar()
-{
-    /* Create toolbar: */
-    m_pToolBar = new UIToolBar(parentWidget());
-    if (m_pToolBar)
-    {
-        /* Configure toolbar: */
-        const int iIconMetric = (int)(QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize));
-        m_pToolBar->setIconSize(QSize(iIconMetric, iIconMetric));
-        m_pToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
-
-        /* Add toolbar actions: */
-        m_pToolBar->addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Add));
-        m_pToolBar->addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Import));
-        m_pToolBar->addSeparator();
-        m_pToolBar->addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Remove));
-        m_pToolBar->addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details));
-        m_pToolBar->addSeparator();
-        m_pToolBar->addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_TryPage));
-        m_pToolBar->addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Help));
-
-#ifdef VBOX_WS_MAC
-        /* Check whether we are embedded into a stack: */
-        if (m_enmEmbedding == EmbedTo_Stack)
-        {
-            /* Add into layout: */
-            layout()->addWidget(m_pToolBar);
-        }
-#else
-        /* Add into layout: */
-        layout()->addWidget(m_pToolBar);
-#endif
-    }
-}
-
-void UICloudProfileManagerWidget::prepareTreeWidget()
-{
-    /* Create tree-widget: */
-    m_pTreeWidget = new QITreeWidget;
-    if (m_pTreeWidget)
-    {
-        /* Configure tree-widget: */
-        m_pTreeWidget->header()->hide();
-        m_pTreeWidget->setRootIsDecorated(false);
-        m_pTreeWidget->setAlternatingRowColors(true);
-        m_pTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
-        m_pTreeWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
-        m_pTreeWidget->setColumnCount(Column_Max);
-        m_pTreeWidget->setSortingEnabled(true);
-        m_pTreeWidget->sortByColumn(Column_Name, Qt::AscendingOrder);
-        m_pTreeWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
-        connect(m_pTreeWidget, &QITreeWidget::currentItemChanged,
-                this, &UICloudProfileManagerWidget::sltHandleCurrentItemChange);
-        connect(m_pTreeWidget, &QITreeWidget::customContextMenuRequested,
-                this, &UICloudProfileManagerWidget::sltHandleContextMenuRequest);
-        connect(m_pTreeWidget, &QITreeWidget::itemDoubleClicked,
-                m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details), &QAction::setChecked);
-
-        /* Add into layout: */
-        layout()->addWidget(m_pTreeWidget);
-    }
-}
-
-void UICloudProfileManagerWidget::prepareDetailsWidget()
-{
-    /* Create details-widget: */
-    m_pDetailsWidget = new UICloudProfileDetailsWidget(m_enmEmbedding);
-    if (m_pDetailsWidget)
-    {
-        /* Configure details-widget: */
-        m_pDetailsWidget->setVisible(false);
-        m_pDetailsWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
-        connect(m_pDetailsWidget, &UICloudProfileDetailsWidget::sigDataChanged,
-                this, &UICloudProfileManagerWidget::sigCloudProfileDetailsDataChanged);
-        connect(m_pDetailsWidget, &UICloudProfileDetailsWidget::sigDataChangeRejected,
-                this, &UICloudProfileManagerWidget::sltResetCloudProfileDetailsChanges);
-        connect(m_pDetailsWidget, &UICloudProfileDetailsWidget::sigDataChangeAccepted,
-                this, &UICloudProfileManagerWidget::sltApplyCloudProfileDetailsChanges);
-
-        /* Add into layout: */
-        layout()->addWidget(m_pDetailsWidget);
-    }
-}
-
-void UICloudProfileManagerWidget::loadSettings()
-{
-    /* Details action/widget: */
-    m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details)->setChecked(gEDataManager->cloudProfileManagerDetailsExpanded());
-    sltToggleCloudProfileDetailsVisibility(m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details)->isChecked());
-}
-
-void UICloudProfileManagerWidget::loadCloudStuff()
-{
-    /* Clear tree first of all: */
-    m_pTreeWidget->clear();
-
-    /* Get VirtualBox for further activities: */
-    const CVirtualBox comVBox = uiCommon().virtualBox();
-
-    /* Get CloudProviderManager for further activities: */
-    const CCloudProviderManager comCloudProviderManager = comVBox.GetCloudProviderManager();
-    /* Show error message if necessary: */
-    if (!comVBox.isOk())
-        msgCenter().cannotAcquireCloudProviderManager(comVBox, this);
-    else
-    {
-        /* Iterate through existing providers: */
-        foreach (const CCloudProvider &comCloudProvider, comCloudProviderManager.GetProviders())
-        {
-            /* Skip if we have nothing to populate (file missing?): */
-            if (comCloudProvider.isNull())
-                continue;
-
-            /* Load provider data: */
-            UIDataCloudProvider providerData;
-            loadCloudProvider(comCloudProvider, providerData);
-            createItemForCloudProvider(providerData, false);
-
-            /* Make sure provider item is properly inserted: */
-            UIItemCloudProvider *pItem = searchItem(providerData.m_uuid);
-
-            /* Iterate through existing profiles: */
-            foreach (const CCloudProfile &comCloudProfile, comCloudProvider.GetProfiles())
-            {
-                /* Load profile data: */
-                UIDataCloudProfile profileData;
-                loadCloudProfile(comCloudProfile, providerData, profileData);
-                createItemForCloudProfile(pItem, profileData, false);
-            }
-
-            /* Expand provider item finally: */
-            pItem->setExpanded(true);
-        }
-
-        /* Choose the 1st item as current initially: */
-        m_pTreeWidget->setCurrentItem(m_pTreeWidget->topLevelItem(0));
-        sltHandleCurrentItemChange();
-    }
-}
-
-void UICloudProfileManagerWidget::loadCloudProvider(const CCloudProvider &comProvider, UIDataCloudProvider &data)
-{
-    /* Gather provider settings: */
-    if (comProvider.isOk())
-        data.m_uuid = comProvider.GetId();
-    if (comProvider.isOk())
-        data.m_strName = comProvider.GetName();
-    foreach (const QString &strSupportedPropertyName, comProvider.GetSupportedPropertyNames())
-        data.m_propertyDescriptions[strSupportedPropertyName] = comProvider.GetPropertyDescription(strSupportedPropertyName);
-
-    /* Show error message if necessary: */
-    if (!comProvider.isOk())
-        msgCenter().cannotAcquireCloudProviderParameter(comProvider, this);
-}
-
-void UICloudProfileManagerWidget::loadCloudProfile(const CCloudProfile &comProfile, const UIDataCloudProvider &providerData, UIDataCloudProfile &profileData)
-{
-    /* Gather profile settings: */
-    if (comProfile.isOk())
-        profileData.m_strName = comProfile.GetName();
-
-    if (comProfile.isOk())
-    {
-        /* Acquire properties: */
-        QVector<QString> keys;
-        QVector<QString> values;
-        QVector<QString> descriptions;
-        values = comProfile.GetProperties(QString(), keys);
-
-        /* Sync sizes: */
-        values.resize(keys.size());
-        descriptions.resize(keys.size());
-
-        if (comProfile.isOk())
-        {
-            /* Enumerate all the keys: */
-            for (int i = 0; i < keys.size(); ++i)
-                profileData.m_data[keys.at(i)] = qMakePair(values.at(i), providerData.m_propertyDescriptions.value(keys.at(i)));
-        }
-    }
-
-    /* Show error message if necessary: */
-    if (!comProfile.isOk())
-        msgCenter().cannotAcquireCloudProfileParameter(comProfile, this);
-}
-
-UIItemCloudProvider *UICloudProfileManagerWidget::searchItem(const QUuid &uuid) const
-{
-    /* Iterated through top-level items: */
-    for (int i = 0; i < m_pTreeWidget->topLevelItemCount(); ++i)
-        if (m_pTreeWidget->topLevelItem(i)->data(0, Data_ProviderID).toUuid() == uuid)
-            return static_cast<UIItemCloudProvider*>(m_pTreeWidget->topLevelItem(i));
-    /* Null by default: */
-    return 0;
-}
-
-void UICloudProfileManagerWidget::createItemForCloudProvider(const UIDataCloudProvider &data, bool fChooseItem)
-{
-    /* Create new provider item: */
-    UIItemCloudProvider *pItem = new UIItemCloudProvider;
-    if (pItem)
-    {
-        /* Configure item: */
-        pItem->UIDataCloudProvider::operator=(data);
-        pItem->updateFields();
-        /* Add item to the tree: */
-        m_pTreeWidget->addTopLevelItem(pItem);
-        /* And choose it as current if necessary: */
-        if (fChooseItem)
-            m_pTreeWidget->setCurrentItem(pItem);
-    }
-}
-
-void UICloudProfileManagerWidget::createItemForCloudProfile(QTreeWidgetItem *pParent, const UIDataCloudProfile &data, bool fChooseItem)
-{
-    /* Create new profile item: */
-    UIItemCloudProfile *pItem = new UIItemCloudProfile;
-    if (pItem)
-    {
-        /* Configure item: */
-        pItem->UIDataCloudProfile::operator=(data);
-        pItem->updateFields();
-        /* Add item to the parent: */
-        pParent->addChild(pItem);
-        /* And choose it as current if necessary: */
-        if (fChooseItem)
-            m_pTreeWidget->setCurrentItem(pItem);
-    }
-}
-
-void UICloudProfileManagerWidget::updateItemForCloudProfile(const UIDataCloudProfile &data, bool fChooseItem, UIItemCloudProfile *pItem)
-{
-    /* Update passed item: */
-    if (pItem)
-    {
-        /* Configure item: */
-        pItem->UIDataCloudProfile::operator=(data);
-        pItem->updateFields();
-        /* And choose it as current if necessary: */
-        if (fChooseItem)
-            m_pTreeWidget->setCurrentItem(pItem);
-    }
-}
-
-
-/*********************************************************************************************************************************
-*   Class UICloudProfileManagerFactory implementation.                                                                           *
-*********************************************************************************************************************************/
-
-UICloudProfileManagerFactory::UICloudProfileManagerFactory(UIActionPool *pActionPool /* = 0 */)
-    : m_pActionPool(pActionPool)
-{
-}
-
-void UICloudProfileManagerFactory::create(QIManagerDialog *&pDialog, QWidget *pCenterWidget)
-{
-    pDialog = new UICloudProfileManager(pCenterWidget, m_pActionPool);
-}
-
-
-/*********************************************************************************************************************************
-*   Class UICloudProfileManager implementation.                                                                                  *
-*********************************************************************************************************************************/
-
-UICloudProfileManager::UICloudProfileManager(QWidget *pCenterWidget, UIActionPool *pActionPool)
-    : QIWithRetranslateUI<QIManagerDialog>(pCenterWidget)
-    , m_pActionPool(pActionPool)
-{
-}
-
-void UICloudProfileManager::sltHandleButtonBoxClick(QAbstractButton *pButton)
-{
-    /* Disable buttons first of all: */
-    button(ButtonType_Reset)->setEnabled(false);
-    button(ButtonType_Apply)->setEnabled(false);
-
-    /* Compare with known buttons: */
-    if (pButton == button(ButtonType_Reset))
-        emit sigDataChangeRejected();
-    else
-    if (pButton == button(ButtonType_Apply))
-        emit sigDataChangeAccepted();
-}
-
-void UICloudProfileManager::retranslateUi()
-{
-    /* Translate window title: */
-    setWindowTitle(tr("Cloud Profile Manager"));
-
-    /* Translate buttons: */
-    button(ButtonType_Reset)->setText(tr("Reset"));
-    button(ButtonType_Apply)->setText(tr("Apply"));
-    button(ButtonType_Close)->setText(tr("Close"));
-    button(ButtonType_Reset)->setStatusTip(tr("Reset changes in current cloud profile details"));
-    button(ButtonType_Apply)->setStatusTip(tr("Apply changes in current cloud profile details"));
-    button(ButtonType_Close)->setStatusTip(tr("Close dialog without saving"));
-    button(ButtonType_Reset)->setShortcut(QString("Ctrl+Backspace"));
-    button(ButtonType_Apply)->setShortcut(QString("Ctrl+Return"));
-    button(ButtonType_Close)->setShortcut(Qt::Key_Escape);
-    button(ButtonType_Reset)->setToolTip(tr("Reset Changes (%1)").arg(button(ButtonType_Reset)->shortcut().toString()));
-    button(ButtonType_Apply)->setToolTip(tr("Apply Changes (%1)").arg(button(ButtonType_Apply)->shortcut().toString()));
-    button(ButtonType_Close)->setToolTip(tr("Close Window (%1)").arg(button(ButtonType_Close)->shortcut().toString()));
-}
-
-void UICloudProfileManager::configure()
-{
-    /* Apply window icons: */
-    setWindowIcon(UIIconPool::iconSetFull(":/cloud_profile_manager_32px.png", ":/cloud_profile_manager_16px.png"));
-}
-
-void UICloudProfileManager::configureCentralWidget()
-{
-    /* Create widget: */
-    UICloudProfileManagerWidget *pWidget = new UICloudProfileManagerWidget(EmbedTo_Dialog, m_pActionPool, true, this);
-    if (pWidget)
-    {
-        /* Configure widget: */
-        setWidget(pWidget);
-        setWidgetMenu(pWidget->menu());
-#ifdef VBOX_WS_MAC
-        setWidgetToolbar(pWidget->toolbar());
-#endif
-        connect(pWidget, &UICloudProfileManagerWidget::sigChange,
-                this, &UICloudProfileManager::sigChange);
-        connect(this, &UICloudProfileManager::sigDataChangeRejected,
-                pWidget, &UICloudProfileManagerWidget::sltResetCloudProfileDetailsChanges);
-        connect(this, &UICloudProfileManager::sigDataChangeAccepted,
-                pWidget, &UICloudProfileManagerWidget::sltApplyCloudProfileDetailsChanges);
-
-        /* Add into layout: */
-        centralWidget()->layout()->addWidget(pWidget);
-    }
-}
-
-void UICloudProfileManager::configureButtonBox()
-{
-    /* Configure button-box: */
-    connect(widget(), &UICloudProfileManagerWidget::sigCloudProfileDetailsVisibilityChanged,
-            button(ButtonType_Apply), &QPushButton::setVisible);
-    connect(widget(), &UICloudProfileManagerWidget::sigCloudProfileDetailsVisibilityChanged,
-            button(ButtonType_Reset), &QPushButton::setVisible);
-    connect(widget(), &UICloudProfileManagerWidget::sigCloudProfileDetailsDataChanged,
-            button(ButtonType_Apply), &QPushButton::setEnabled);
-    connect(widget(), &UICloudProfileManagerWidget::sigCloudProfileDetailsDataChanged,
-            button(ButtonType_Reset), &QPushButton::setEnabled);
-    connect(buttonBox(), &QIDialogButtonBox::clicked,
-            this, &UICloudProfileManager::sltHandleButtonBoxClick);
-    // WORKAROUND:
-    // Since we connected signals later than extra-data loaded
-    // for signals above, we should handle that stuff here again:
-    button(ButtonType_Apply)->setVisible(gEDataManager->cloudProfileManagerDetailsExpanded());
-    button(ButtonType_Reset)->setVisible(gEDataManager->cloudProfileManagerDetailsExpanded());
-}
-
-void UICloudProfileManager::finalize()
-{
-    /* Apply language settings: */
-    retranslateUi();
-}
-
-UICloudProfileManagerWidget *UICloudProfileManager::widget()
-{
-    return qobject_cast<UICloudProfileManagerWidget*>(QIManagerDialog::widget());
-}
Index: trunk/src/VBox/Frontends/VirtualBox/src/cloud/UICloudProfileManager.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/cloud/UICloudProfileManager.h	(revision 83949)
+++ 	(revision )
@@ -1,270 +1,0 @@
-/* $Id$ */
-/** @file
- * VBox Qt GUI - UICloudProfileManager class declaration.
- */
-
-/*
- * Copyright (C) 2009-2020 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#ifndef FEQT_INCLUDED_SRC_cloud_UICloudProfileManager_h
-#define FEQT_INCLUDED_SRC_cloud_UICloudProfileManager_h
-#ifndef RT_WITHOUT_PRAGMA_ONCE
-# pragma once
-#endif
-
-/* GUI includes: */
-#include "QIManagerDialog.h"
-#include "QIWithRetranslateUI.h"
-
-/* Forward declarations: */
-class QAbstractButton;
-class QTreeWidgetItem;
-class QITreeWidget;
-class UIActionPool;
-class UICloudProfileDetailsWidget;
-class UIItemCloudProfile;
-class UIItemCloudProvider;
-class UIToolBar;
-struct UIDataCloudProfile;
-struct UIDataCloudProvider;
-class CCloudProfile;
-class CCloudProvider;
-
-
-/** QWidget extension providing GUI with the pane to control cloud profile related functionality. */
-class UICloudProfileManagerWidget : public QIWithRetranslateUI<QWidget>
-{
-    Q_OBJECT;
-
-signals:
-
-    /** Notifies listeners about dialog change. */
-    void sigChange();
-
-    /** Notifies listeners about cloud profile details-widget @a fVisible. */
-    void sigCloudProfileDetailsVisibilityChanged(bool fVisible);
-    /** Notifies listeners about cloud profile details data @a fDiffers. */
-    void sigCloudProfileDetailsDataChanged(bool fDiffers);
-
-public:
-
-    /** Constructs Cloud Profile Manager widget.
-      * @param  enmEmbedding  Brings the type of widget embedding.
-      * @param  pActionPool   Brings the action-pool reference.
-      * @param  fShowToolbar  Brings whether we should create/show toolbar. */
-    UICloudProfileManagerWidget(EmbedTo enmEmbedding, UIActionPool *pActionPool,
-                                bool fShowToolbar = true, QWidget *pParent = 0);
-
-    /** Returns the menu. */
-    QMenu *menu() const;
-
-#ifdef VBOX_WS_MAC
-    /** Returns the toolbar. */
-    UIToolBar *toolbar() const { return m_pToolBar; }
-#endif
-
-protected:
-
-    /** @name Event-handling stuff.
-      * @{ */
-        /** Handles translation event. */
-        virtual void retranslateUi() /* override */;
-    /** @} */
-
-public slots:
-
-    /** @name Details-widget stuff.
-      * @{ */
-        /** Handles command to reset cloud profile details changes. */
-        void sltResetCloudProfileDetailsChanges();
-        /** Handles command to apply cloud profile details changes. */
-        void sltApplyCloudProfileDetailsChanges();
-    /** @} */
-
-private slots:
-
-    /** @name Menu/action stuff.
-      * @{ */
-        /** Handles command to create cloud profile. */
-        void sltAddCloudProfile();
-        /** Handles command to import cloud profiles. */
-        void sltImportCloudProfiles();
-        /** Handles command to remove cloud profile. */
-        void sltRemoveCloudProfile();
-        /** Handles command to make cloud profile details @a fVisible. */
-        void sltToggleCloudProfileDetailsVisibility(bool fVisible);
-        /** Handles command to show cloud profile help. */
-        void sltShowCloudProfileTryPage();
-        /** Handles command to show cloud profile help. */
-        void sltShowCloudProfileHelp();
-    /** @} */
-
-    /** @name Tree-widget stuff.
-      * @{ */
-        /** Handles tree-widget current item change. */
-        void sltHandleCurrentItemChange();
-        /** Handles context menu request for tree-widget @a position. */
-        void sltHandleContextMenuRequest(const QPoint &position);
-    /** @} */
-
-private:
-
-    /** @name Prepare/cleanup cascade.
-      * @{ */
-        /** Prepares all. */
-        void prepare();
-        /** Prepares actions. */
-        void prepareActions();
-        /** Prepares widgets. */
-        void prepareWidgets();
-        /** Prepares toolbar. */
-        void prepareToolBar();
-        /** Prepares tree-widget. */
-        void prepareTreeWidget();
-        /** Prepares details-widget. */
-        void prepareDetailsWidget();
-        /** Load settings: */
-        void loadSettings();
-    /** @} */
-
-    /** @name Loading stuff.
-      * @{ */
-        /** Loads cloud stuff. */
-        void loadCloudStuff();
-        /** Loads cloud @a comProvider data to passed @a data container. */
-        void loadCloudProvider(const CCloudProvider &comProvider, UIDataCloudProvider &data);
-        /** Loads cloud @a comProfile data to passed @a profileData container, using @a providerData as hint. */
-        void loadCloudProfile(const CCloudProfile &comProfile, const UIDataCloudProvider &providerData, UIDataCloudProfile &profileData);
-    /** @} */
-
-    /** @name Tree-widget stuff.
-      * @{ */
-        /** Seearches a provider item with specified @a uuid. */
-        UIItemCloudProvider *searchItem(const QUuid &uuid) const;
-
-        /** Creates a new tree-widget item on the basis of passed @a data, @a fChooseItem if requested. */
-        void createItemForCloudProvider(const UIDataCloudProvider &data, bool fChooseItem);
-
-        /** Creates a new tree-widget item as a child of certain @a pParent, on the basis of passed @a data, @a fChooseItem if requested. */
-        void createItemForCloudProfile(QTreeWidgetItem *pParent, const UIDataCloudProfile &data, bool fChooseItem);
-        /** Updates the passed tree-widget item on the basis of passed @a data, @a fChooseItem if requested. */
-        void updateItemForCloudProfile(const UIDataCloudProfile &data, bool fChooseItem, UIItemCloudProfile *pItem);
-    /** @} */
-
-    /** @name General variables.
-      * @{ */
-        /** Holds the widget embedding type. */
-        const EmbedTo m_enmEmbedding;
-        /** Holds the action-pool reference. */
-        UIActionPool *m_pActionPool;
-        /** Holds whether we should create/show toolbar. */
-        const bool    m_fShowToolbar;
-    /** @} */
-
-    /** @name Toolbar and menu variables.
-      * @{ */
-        /** Holds the toolbar instance. */
-        UIToolBar *m_pToolBar;
-    /** @} */
-
-    /** @name Splitter variables.
-      * @{ */
-        /** Holds the tree-widget instance. */
-        QITreeWidget *m_pTreeWidget;
-        /** Holds the details-widget instance. */
-        UICloudProfileDetailsWidget *m_pDetailsWidget;
-    /** @} */
-};
-
-
-/** QIManagerDialogFactory extension used as a factory for Cloud Profile Manager dialog. */
-class UICloudProfileManagerFactory : public QIManagerDialogFactory
-{
-public:
-
-    /** Constructs Cloud Profile Manager factory acquiring additional arguments.
-      * @param  pActionPool  Brings the action-pool reference. */
-    UICloudProfileManagerFactory(UIActionPool *pActionPool = 0);
-
-protected:
-
-    /** Creates derived @a pDialog instance.
-      * @param  pCenterWidget  Brings the widget reference to center according to. */
-    virtual void create(QIManagerDialog *&pDialog, QWidget *pCenterWidget) /* override */;
-
-    /** Holds the action-pool reference. */
-    UIActionPool *m_pActionPool;
-};
-
-
-/** QIManagerDialog extension providing GUI with the dialog to control cloud profile related functionality. */
-class UICloudProfileManager : public QIWithRetranslateUI<QIManagerDialog>
-{
-    Q_OBJECT;
-
-signals:
-
-    /** Notifies listeners about data change rejected and should be reseted. */
-    void sigDataChangeRejected();
-    /** Notifies listeners about data change accepted and should be applied. */
-    void sigDataChangeAccepted();
-
-private slots:
-
-    /** @name Button-box stuff.
-      * @{ */
-        /** Handles button-box button click. */
-        void sltHandleButtonBoxClick(QAbstractButton *pButton);
-    /** @} */
-
-private:
-
-    /** Constructs Cloud Profile Manager dialog.
-      * @param  pCenterWidget  Brings the widget reference to center according to.
-      * @param  pActionPool    Brings the action-pool reference. */
-    UICloudProfileManager(QWidget *pCenterWidget, UIActionPool *pActionPool);
-
-    /** @name Event-handling stuff.
-      * @{ */
-        /** Handles translation event. */
-        virtual void retranslateUi() /* override */;
-    /** @} */
-
-    /** @name Prepare/cleanup cascade.
-      * @{ */
-        /** Configures all. */
-        virtual void configure() /* override */;
-        /** Configures central-widget. */
-        virtual void configureCentralWidget() /* override */;
-        /** Configures button-box. */
-        virtual void configureButtonBox() /* override */;
-        /** Perform final preparations. */
-        virtual void finalize() /* override */;
-    /** @} */
-
-    /** @name Widget stuff.
-      * @{ */
-        /** Returns the widget. */
-        virtual UICloudProfileManagerWidget *widget() /* override */;
-    /** @} */
-
-    /** @name Action related variables.
-      * @{ */
-        /** Holds the action-pool reference. */
-        UIActionPool *m_pActionPool;
-    /** @} */
-
-    /** Allow factory access to private/protected members: */
-    friend class UICloudProfileManagerFactory;
-};
-
-#endif /* !FEQT_INCLUDED_SRC_cloud_UICloudProfileManager_h */
Index: trunk/src/VBox/Frontends/VirtualBox/src/cloud/profilemanager/UICloudProfileDetailsWidget.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/cloud/profilemanager/UICloudProfileDetailsWidget.cpp	(revision 83950)
+++ trunk/src/VBox/Frontends/VirtualBox/src/cloud/profilemanager/UICloudProfileDetailsWidget.cpp	(revision 83950)
@@ -0,0 +1,409 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UICloudProfileDetailsWidget class implementation.
+ */
+
+/*
+ * Copyright (C) 2009-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/* Qt includes: */
+#include <QGridLayout>
+#include <QHeaderView>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QTableWidget>
+#include <QVBoxLayout>
+
+/* GUI includes: */
+#include "QIDialogButtonBox.h"
+#include "UICloudProfileDetailsWidget.h"
+
+/* Other VBox includes: */
+#include "iprt/assert.h"
+
+
+UICloudProfileDetailsWidget::UICloudProfileDetailsWidget(EmbedTo enmEmbedding, QWidget *pParent /* = 0 */)
+    : QIWithRetranslateUI<QWidget>(pParent)
+    , m_enmEmbedding(enmEmbedding)
+    , m_pTableWidget(0)
+    , m_pButtonBox(0)
+{
+    /* Prepare: */
+    prepare();
+}
+
+void UICloudProfileDetailsWidget::setData(const UIDataCloudProfile &data)
+{
+    /* Cache old/new data: */
+    m_oldData = data;
+    m_newData = m_oldData;
+
+    /* Load data: */
+    loadData();
+
+    /* Translate linked widgets: */
+    retranslateEditor();
+    retranslateButtons();
+}
+
+void UICloudProfileDetailsWidget::retranslateUi()
+{
+    /// @todo add description tool-tips
+
+    /* Translate name-editor label: */
+    m_pLabelName->setText(tr("Name:"));
+    /* Translate name-editor: */
+    retranslateEditor();
+
+    /* Translate table-widget label: */
+    m_pLabelTableWidget->setText(tr("Properties:"));
+    /* Translate table-widget: */
+    m_pTableWidget->setToolTip(tr("Contains cloud profile settings"));
+
+    /* Translate buttons: */
+    retranslateButtons();
+
+    /* Retranslate validation: */
+    retranslateValidation();
+
+    /* Update table tool-tips: */
+    updateTableToolTips();
+}
+
+void UICloudProfileDetailsWidget::retranslateEditor()
+{
+    /* Translate placeholders: */
+    m_pEditorName->setPlaceholderText(  m_oldData.m_strName.isNull()
+                                      ? tr("Enter a name for the new profile...")
+                                      : tr("Enter a name for this profile..."));
+}
+
+void UICloudProfileDetailsWidget::retranslateButtons()
+{
+    /* Translate button-box: */
+    if (m_pButtonBox)
+    {
+        /* Common: 'Reset' button: */
+        m_pButtonBox->button(QDialogButtonBox::Cancel)->setText(tr("Reset"));
+        m_pButtonBox->button(QDialogButtonBox::Cancel)->setStatusTip(tr("Reset changes in current profile details"));
+        m_pButtonBox->button(QDialogButtonBox::Cancel)->setShortcut(Qt::Key_Escape);
+        m_pButtonBox->button(QDialogButtonBox::Cancel)->
+            setToolTip(tr("Reset Changes (%1)").arg(m_pButtonBox->button(QDialogButtonBox::Cancel)->shortcut().toString()));
+
+        if (m_oldData.m_strName.isNull())
+        {
+            /* Provider: 'Add' button: */
+            m_pButtonBox->button(QDialogButtonBox::Ok)->setText(tr("Add"));
+            m_pButtonBox->button(QDialogButtonBox::Ok)->setStatusTip(tr("Add a new profile with following name"));
+            m_pButtonBox->button(QDialogButtonBox::Ok)->setShortcut(QString("Ctrl+Return"));
+            m_pButtonBox->button(QDialogButtonBox::Ok)->
+                setToolTip(tr("Add Profile (%1)").arg(m_pButtonBox->button(QDialogButtonBox::Ok)->shortcut().toString()));
+        }
+        else
+        {
+            /* Profile: 'Apply' button: */
+            m_pButtonBox->button(QDialogButtonBox::Ok)->setText(tr("Apply"));
+            m_pButtonBox->button(QDialogButtonBox::Ok)->setStatusTip(tr("Apply changes in current profile details"));
+            m_pButtonBox->button(QDialogButtonBox::Ok)->setShortcut(QString("Ctrl+Return"));
+            m_pButtonBox->button(QDialogButtonBox::Ok)->
+                setToolTip(tr("Apply Changes (%1)").arg(m_pButtonBox->button(QDialogButtonBox::Ok)->shortcut().toString()));
+        }
+    }
+}
+
+void UICloudProfileDetailsWidget::sltNameChanged(const QString &strName)
+{
+    /* Push changes back: */
+    m_newData.m_strName = strName;
+
+    /* Revalidate: */
+    revalidate(m_pEditorName);
+    /* Update button states: */
+    updateButtonStates();
+}
+
+void UICloudProfileDetailsWidget::sltTableChanged(QTableWidgetItem *pItem)
+{
+    /* Make sure item is valid: */
+    AssertPtrReturnVoid(pItem);
+    const int iRow = pItem->row();
+    AssertReturnVoid(iRow >= 0);
+
+    /* Skip if one of items isn't yet created.
+     * This can happen when 1st is already while 2nd isn't yet. */
+    QTableWidgetItem *pItemK = m_pTableWidget->item(iRow, 0);
+    QTableWidgetItem *pItemV = m_pTableWidget->item(iRow, 1);
+    if (!pItemK || !pItemV)
+        return;
+
+    /* Push changes back: */
+    const QString strKey = pItemK->text();
+    const QString strValue = pItemV->text();
+    m_newData.m_data[strKey] = qMakePair(strValue, m_newData.m_data.value(strKey).second);
+
+    /* Revalidate: */
+    revalidate(m_pTableWidget);
+    /* Update button states: */
+    updateButtonStates();
+}
+
+void UICloudProfileDetailsWidget::sltHandleButtonBoxClick(QAbstractButton *pButton)
+{
+    /* Make sure button-box exists: */
+    AssertPtrReturnVoid(m_pButtonBox);
+
+    /* Disable buttons first of all: */
+    m_pButtonBox->button(QDialogButtonBox::Cancel)->setEnabled(false);
+    m_pButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
+
+    /* Compare with known buttons: */
+    if (pButton == m_pButtonBox->button(QDialogButtonBox::Cancel))
+        emit sigDataChangeRejected();
+    else
+    if (pButton == m_pButtonBox->button(QDialogButtonBox::Ok))
+        emit sigDataChangeAccepted();
+}
+
+void UICloudProfileDetailsWidget::prepare()
+{
+    /* Prepare widgets: */
+    prepareWidgets();
+
+    /* Apply language settings: */
+    retranslateUi();
+
+    /* Update button states finally: */
+    updateButtonStates();
+}
+
+void UICloudProfileDetailsWidget::prepareWidgets()
+{
+    /* Create layout: */
+    QGridLayout *pLayout = new QGridLayout(this);
+    if (pLayout)
+    {
+        if (m_enmEmbedding == EmbedTo_Dialog)
+        {
+            pLayout->setContentsMargins(0, 0, 0, 0);
+#ifdef VBOX_WS_MAC
+            pLayout->setSpacing(10);
+#else
+            pLayout->setSpacing(qApp->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing) / 2);
+#endif
+        }
+        else
+        {
+#ifdef VBOX_WS_MAC
+            pLayout->setContentsMargins(13, 0, 13, 13);
+            pLayout->setSpacing(10);
+#else
+            const int iL = qApp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin) * 1.5;
+            const int iT = qApp->style()->pixelMetric(QStyle::PM_LayoutTopMargin) * 1.5;
+            const int iR = qApp->style()->pixelMetric(QStyle::PM_LayoutRightMargin) * 1.5;
+            const int iB = qApp->style()->pixelMetric(QStyle::PM_LayoutBottomMargin) * 1.5;
+            pLayout->setContentsMargins(iL, iT, iR, iB);
+#endif
+        }
+
+        /* Create name editor: */
+        m_pEditorName = new QLineEdit;
+        if (m_pEditorName)
+        {
+            connect(m_pEditorName, &QLineEdit::textChanged, this, &UICloudProfileDetailsWidget::sltNameChanged);
+
+            /* Add into layout: */
+            pLayout->addWidget(m_pEditorName, 0, 1);
+        }
+        /* Create name label: */
+        m_pLabelName = new QLabel;
+        if (m_pLabelName)
+        {
+            m_pLabelName->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
+            m_pLabelName->setBuddy(m_pEditorName);
+
+            /* Add into layout: */
+            pLayout->addWidget(m_pLabelName, 0, 0);
+        }
+
+        /* Create tab-widget: */
+        m_pTableWidget = new QTableWidget;
+        if (m_pTableWidget)
+        {
+            m_pTableWidget->setAlternatingRowColors(true);
+            m_pTableWidget->horizontalHeader()->setVisible(false);
+            m_pTableWidget->verticalHeader()->setVisible(false);
+            m_pTableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
+            connect(m_pTableWidget, &QTableWidget::itemChanged, this, &UICloudProfileDetailsWidget::sltTableChanged);
+
+            /* Add into layout: */
+            pLayout->addWidget(m_pTableWidget, 1, 1);
+        }
+        /* Create tab-widget label: */
+        m_pLabelTableWidget = new QLabel;
+        if (m_pLabelTableWidget)
+        {
+            m_pLabelTableWidget->setAlignment(Qt::AlignRight | Qt::AlignTop);
+            m_pLabelTableWidget->setBuddy(m_pTableWidget);
+
+            /* Add into layout: */
+            pLayout->addWidget(m_pLabelTableWidget, 1, 0);
+        }
+
+        /* If parent embedded into stack: */
+        if (m_enmEmbedding == EmbedTo_Stack)
+        {
+            /* Create button-box: */
+            m_pButtonBox = new QIDialogButtonBox;
+            if  (m_pButtonBox)
+            {
+                m_pButtonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
+                connect(m_pButtonBox, &QIDialogButtonBox::clicked, this, &UICloudProfileDetailsWidget::sltHandleButtonBoxClick);
+
+                /* Add into layout: */
+                pLayout->addWidget(m_pButtonBox, 2, 0, 1, 2);
+            }
+        }
+    }
+}
+
+void UICloudProfileDetailsWidget::loadData()
+{
+    /* Clear table initially: */
+    m_pTableWidget->clear();
+
+    /* Fill name editor: */
+    m_pEditorName->setText(m_oldData.m_strName);
+
+    /* Configure table: */
+    m_pTableWidget->setRowCount(m_oldData.m_data.keys().size());
+    m_pTableWidget->setColumnCount(2);
+
+    /* Push acquired keys/values to data fields: */
+    for (int i = 0; i < m_pTableWidget->rowCount(); ++i)
+    {
+        /* Gather values: */
+        const QString strKey = m_oldData.m_data.keys().at(i);
+        const QString strValue = m_oldData.m_data.value(strKey).first;
+        const QString strToolTip = m_oldData.m_data.value(strKey).second;
+
+        /* Create key item: */
+        QTableWidgetItem *pItemK = new QTableWidgetItem(strKey);
+        if (pItemK)
+        {
+            /* Non-editable for sure, but non-selectable? */
+            pItemK->setFlags(pItemK->flags() & ~Qt::ItemIsEditable);
+            /* Use non-translated description as tool-tip: */
+            pItemK->setData(Qt::UserRole, strToolTip);
+
+            /* Insert into table: */
+            m_pTableWidget->setItem(i, 0, pItemK);
+        }
+
+        /* Create value item: */
+        QTableWidgetItem *pItemV = new QTableWidgetItem(strValue);
+        if (pItemV)
+        {
+            /* Use the value as tool-tip, there can be quite long values: */
+            pItemV->setToolTip(strValue);
+
+            /* Insert into table: */
+            m_pTableWidget->setItem(i, 1, pItemV);
+        }
+    }
+
+    /* Update table tooltips: */
+    updateTableToolTips();
+    /* Adjust table contents: */
+    adjustTableContents();
+}
+
+void UICloudProfileDetailsWidget::revalidate(QWidget *pWidget /* = 0 */)
+{
+    /// @todo validate profile settings table!
+
+    /* Retranslate validation: */
+    retranslateValidation(pWidget);
+}
+
+void UICloudProfileDetailsWidget::retranslateValidation(QWidget *pWidget /* = 0 */)
+{
+    Q_UNUSED(pWidget);
+
+    /// @todo translate vaidation errors!
+}
+
+void UICloudProfileDetailsWidget::updateTableToolTips()
+{
+    /* Iterate through all the key items: */
+    for (int i = 0; i < m_pTableWidget->rowCount(); ++i)
+    {
+        /* Acquire current key item: */
+        QTableWidgetItem *pItemK = m_pTableWidget->item(i, 0);
+        if (pItemK)
+        {
+            const QString strToolTip = pItemK->data(Qt::UserRole).toString();
+            pItemK->setToolTip(tr(strToolTip.toUtf8().constData()));
+        }
+    }
+}
+
+void UICloudProfileDetailsWidget::adjustTableContents()
+{
+    /* Disable last column stretching temporary: */
+    m_pTableWidget->horizontalHeader()->setStretchLastSection(false);
+
+    /* Resize both columns to contents: */
+    m_pTableWidget->resizeColumnsToContents();
+    /* Then acquire full available width: */
+    const int iFullWidth = m_pTableWidget->viewport()->width();
+    /* First column should not be less than it's minimum size, last gets the rest: */
+    const int iMinimumWidth0 = qMin(m_pTableWidget->horizontalHeader()->sectionSize(0), iFullWidth / 2);
+    m_pTableWidget->horizontalHeader()->resizeSection(0, iMinimumWidth0);
+
+    /* Enable last column stretching again: */
+    m_pTableWidget->horizontalHeader()->setStretchLastSection(true);
+}
+
+void UICloudProfileDetailsWidget::updateButtonStates()
+{
+#if 0
+    if (m_oldData != m_newData)
+    {
+        printf("Old data:\n");
+        foreach (const QString &strKey, m_oldData.m_data.keys())
+        {
+            const QString strValue = m_oldData.m_data.value(strKey).first;
+            const QString strDecription = m_oldData.m_data.value(strKey).second;
+            printf(" %s: %s, %s\n", strKey.toUtf8().constData(), strValue.toUtf8().constData(), strDecription.toUtf8().constData());
+        }
+        printf("New data:\n");
+        foreach (const QString &strKey, m_newData.m_data.keys())
+        {
+            const QString strValue = m_newData.m_data.value(strKey).first;
+            const QString strDecription = m_newData.m_data.value(strKey).second;
+            printf(" %s: %s, %s\n", strKey.toUtf8().constData(), strValue.toUtf8().constData(), strDecription.toUtf8().constData());
+        }
+        printf("\n");
+    }
+#endif
+
+    /* Update 'Apply' / 'Reset' button states: */
+    if (m_pButtonBox)
+    {
+        m_pButtonBox->button(QDialogButtonBox::Cancel)->setEnabled(m_oldData != m_newData);
+        m_pButtonBox->button(QDialogButtonBox::Ok)->setEnabled(m_oldData != m_newData);
+    }
+
+    /* Notify listeners as well: */
+    emit sigDataChanged(m_oldData != m_newData);
+}
Index: trunk/src/VBox/Frontends/VirtualBox/src/cloud/profilemanager/UICloudProfileDetailsWidget.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/cloud/profilemanager/UICloudProfileDetailsWidget.h	(revision 83950)
+++ trunk/src/VBox/Frontends/VirtualBox/src/cloud/profilemanager/UICloudProfileDetailsWidget.h	(revision 83950)
@@ -0,0 +1,213 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UICloudProfileDetailsWidget class declaration.
+ */
+
+/*
+ * Copyright (C) 2009-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef FEQT_INCLUDED_SRC_cloud_profilemanager_UICloudProfileDetailsWidget_h
+#define FEQT_INCLUDED_SRC_cloud_profilemanager_UICloudProfileDetailsWidget_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* Qt includes: */
+#include <QMap>
+#include <QUuid>
+#include <QWidget>
+
+/* GUI includes: */
+#include "QIManagerDialog.h"
+#include "QIWithRetranslateUI.h"
+
+/* Forward declarations: */
+class QAbstractButton;
+class QLabel;
+class QLineEdit;
+class QTableWidget;
+class QTableWidgetItem;
+class QIDialogButtonBox;
+
+
+/** Cloud Provider data structure. */
+struct UIDataCloudProvider
+{
+    /** Constructs data. */
+    UIDataCloudProvider()
+        : m_strName(QString())
+    {}
+
+    /** Returns whether the @a other passed data is equal to this one. */
+    bool equal(const UIDataCloudProvider &other) const
+    {
+        return true
+               && (m_uuid == other.m_uuid)
+               && (m_strName == other.m_strName)
+               ;
+    }
+
+    /** Returns whether the @a other passed data is equal to this one. */
+    bool operator==(const UIDataCloudProvider &other) const { return equal(other); }
+    /** Returns whether the @a other passed data is different from this one. */
+    bool operator!=(const UIDataCloudProvider &other) const { return !equal(other); }
+
+    /** Holds the provider ID. */
+    QUuid    m_uuid;
+    /** Holds the provider name. */
+    QString  m_strName;
+
+    /** Holds the profile supported property descriptions. */
+    QMap<QString, QString>  m_propertyDescriptions;
+};
+
+/** Cloud Profile data structure. */
+struct UIDataCloudProfile
+{
+    /** Constructs data. */
+    UIDataCloudProfile()
+        : m_strName(QString())
+    {}
+
+    /** Returns whether the @a other passed data is equal to this one. */
+    bool equal(const UIDataCloudProfile &other) const
+    {
+        return true
+               && (m_strName == other.m_strName)
+               && (m_data == other.m_data)
+               ;
+    }
+
+    /** Returns whether the @a other passed data is equal to this one. */
+    bool operator==(const UIDataCloudProfile &other) const { return equal(other); }
+    /** Returns whether the @a other passed data is different from this one. */
+    bool operator!=(const UIDataCloudProfile &other) const { return !equal(other); }
+
+    /** Holds the profile name. */
+    QString  m_strName;
+
+    /** Holds the profile data. */
+    QMap<QString, QPair<QString, QString> >  m_data;
+};
+
+
+/** Cloud Profile details widget. */
+class UICloudProfileDetailsWidget : public QIWithRetranslateUI<QWidget>
+{
+    Q_OBJECT;
+
+signals:
+
+    /** Notifies listeners about data changed and whether it @a fDiffers. */
+    void sigDataChanged(bool fDiffers);
+
+    /** Notifies listeners about data change rejected and should be reseted. */
+    void sigDataChangeRejected();
+    /** Notifies listeners about data change accepted and should be applied. */
+    void sigDataChangeAccepted();
+
+public:
+
+    /** Constructs cloud profile details widget passing @a pParent to the base-class.
+      * @param  enmEmbedding  Brings embedding type. */
+    UICloudProfileDetailsWidget(EmbedTo enmEmbedding, QWidget *pParent = 0);
+
+    /** Returns the cloud profile data. */
+    const UIDataCloudProfile &data() const { return m_newData; }
+    /** Defines the cloud profile @a data. */
+    void setData(const UIDataCloudProfile &data);
+
+protected:
+
+    /** Handles translation event. */
+    virtual void retranslateUi() /* override */;
+    /** Handles editor translation. */
+    void retranslateEditor();
+    /** Handles buttons translation. */
+    void retranslateButtons();
+
+private slots:
+
+    /** @name Change handling stuff.
+      * @{ */
+        /** Handles name change. */
+        void sltNameChanged(const QString &strName);
+        /** Handles table change. */
+        void sltTableChanged(QTableWidgetItem *pItem);
+
+        /** Handles button-box button click. */
+        void sltHandleButtonBoxClick(QAbstractButton *pButton);
+    /** @} */
+
+private:
+
+    /** @name Prepare/cleanup cascade.
+      * @{ */
+        /** Prepares all. */
+        void prepare();
+        /** Prepares widgets. */
+        void prepareWidgets();
+    /** @} */
+
+    /** @name Loading stuff.
+      * @{ */
+        /** Loads data. */
+        void loadData();
+    /** @} */
+
+    /** @name Change handling stuff.
+      * @{ */
+        /** Revalidates changes for passed @a pWidget. */
+        void revalidate(QWidget *pWidget = 0);
+
+        /** Retranslates validation for passed @a pWidget. */
+        void retranslateValidation(QWidget *pWidget = 0);
+
+        /** Updates table tooltips. */
+        void updateTableToolTips();
+        /** Adjusts table contents. */
+        void adjustTableContents();
+
+        /** Updates button states. */
+        void updateButtonStates();
+    /** @} */
+
+    /** @name General variables.
+      * @{ */
+        /** Holds the parent widget embedding type. */
+        const EmbedTo  m_enmEmbedding;
+
+        /** Holds the old data copy. */
+        UIDataCloudProfile  m_oldData;
+        /** Holds the new data copy. */
+        UIDataCloudProfile  m_newData;
+    /** @} */
+
+    /** @name Widget variables.
+      * @{ */
+        /** Holds the name label instance. */
+        QLabel    *m_pLabelName;
+        /** Holds the name editor instance. */
+        QLineEdit *m_pEditorName;
+
+        /** Holds the table-widget label instance. */
+        QLabel       *m_pLabelTableWidget;
+        /** Holds the table-widget instance. */
+        QTableWidget *m_pTableWidget;
+
+        /** Holds the server button-box instance. */
+        QIDialogButtonBox *m_pButtonBox;
+    /** @} */
+};
+
+
+#endif /* !FEQT_INCLUDED_SRC_cloud_profilemanager_UICloudProfileDetailsWidget_h */
Index: trunk/src/VBox/Frontends/VirtualBox/src/cloud/profilemanager/UICloudProfileManager.cpp
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/cloud/profilemanager/UICloudProfileManager.cpp	(revision 83950)
+++ trunk/src/VBox/Frontends/VirtualBox/src/cloud/profilemanager/UICloudProfileManager.cpp	(revision 83950)
@@ -0,0 +1,978 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UICloudProfileManager class implementation.
+ */
+
+/*
+ * Copyright (C) 2009-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/* Qt includes: */
+#include <QHeaderView>
+#include <QPushButton>
+#include <QVBoxLayout>
+
+/* GUI includes: */
+#include "QIDialogButtonBox.h"
+#include "QIInputDialog.h"
+#include "QITreeWidget.h"
+#include "UICommon.h"
+#include "UIActionPoolManager.h"
+#include "UIExtraDataManager.h"
+#include "UIIconPool.h"
+#include "UICloudProfileDetailsWidget.h"
+#include "UICloudProfileManager.h"
+#include "UIMessageCenter.h"
+#include "UIToolBar.h"
+#ifdef VBOX_WS_MAC
+# include "UIWindowMenuManager.h"
+#endif
+
+/* COM includes: */
+#include "CCloudProfile.h"
+#include "CCloudProvider.h"
+#include "CCloudProviderManager.h"
+
+
+/** Tree-widget item types. */
+enum CloudItemType
+{
+    CloudItemType_Provider = QTreeWidgetItem::UserType + 1,
+    CloudItemType_Profile  = QTreeWidgetItem::UserType + 2
+};
+Q_DECLARE_METATYPE(CloudItemType);
+
+/** Tree-widget data types. */
+enum
+{
+    Data_ItemType   = Qt::UserRole + 1,
+    Data_ProviderID = Qt::UserRole + 2,
+};
+
+/** Tree-widget column types. */
+enum
+{
+    Column_Name,
+    Column_Max
+};
+
+
+/** Cloud Profile Manager provider's tree-widget item. */
+class UIItemCloudProvider : public QITreeWidgetItem, public UIDataCloudProvider
+{
+public:
+
+    /** Constructs item. */
+    UIItemCloudProvider();
+
+    /** Updates item fields from base-class data. */
+    void updateFields();
+
+    /** Returns item name. */
+    QString name() const { return m_strName; }
+};
+
+/** Cloud Profile Manager profile's tree-widget item. */
+class UIItemCloudProfile : public QITreeWidgetItem, public UIDataCloudProfile
+{
+public:
+
+    /** Constructs item. */
+    UIItemCloudProfile();
+
+    /** Updates item fields from base-class data. */
+    void updateFields();
+
+    /** Returns item name. */
+    QString name() const { return m_strName; }
+};
+
+
+/*********************************************************************************************************************************
+*   Class UIItemCloudProvider implementation.                                                                                    *
+*********************************************************************************************************************************/
+
+UIItemCloudProvider::UIItemCloudProvider()
+{
+    /* Assign icon: */
+    setIcon(Column_Name, UIIconPool::iconSet(":/provider_oracle_16px.png"));
+    /* Assign item type: */
+    setData(Column_Name, Data_ItemType, QVariant::fromValue(CloudItemType_Provider));
+}
+
+void UIItemCloudProvider::updateFields()
+{
+    /* Update item fields: */
+    setText(Column_Name, m_strName);
+    setData(Column_Name, Data_ProviderID, m_uuid);
+}
+
+
+/*********************************************************************************************************************************
+*   Class UIItemCloudProfile implementation.                                                                                     *
+*********************************************************************************************************************************/
+
+UIItemCloudProfile::UIItemCloudProfile()
+{
+    /* Assign icon: */
+    setIcon(Column_Name, UIIconPool::iconSet(":/profile_16px.png"));
+    /* Assign item type: */
+    setData(Column_Name, Data_ItemType, QVariant::fromValue(CloudItemType_Profile));
+}
+
+void UIItemCloudProfile::updateFields()
+{
+    /* Update item fields: */
+    setText(Column_Name, m_strName);
+}
+
+
+/*********************************************************************************************************************************
+*   Class UICloudProfileManagerWidget implementation.                                                                            *
+*********************************************************************************************************************************/
+
+UICloudProfileManagerWidget::UICloudProfileManagerWidget(EmbedTo enmEmbedding, UIActionPool *pActionPool,
+                                                         bool fShowToolbar /* = true */, QWidget *pParent /* = 0 */)
+    : QIWithRetranslateUI<QWidget>(pParent)
+    , m_enmEmbedding(enmEmbedding)
+    , m_pActionPool(pActionPool)
+    , m_fShowToolbar(fShowToolbar)
+    , m_pToolBar(0)
+    , m_pTreeWidget(0)
+    , m_pDetailsWidget(0)
+{
+    /* Prepare: */
+    prepare();
+}
+
+QMenu *UICloudProfileManagerWidget::menu() const
+{
+    return m_pActionPool->action(UIActionIndexST_M_CloudWindow)->menu();
+}
+
+void UICloudProfileManagerWidget::retranslateUi()
+{
+    /* Adjust toolbar: */
+#ifdef VBOX_WS_MAC
+    // WORKAROUND:
+    // There is a bug in Qt Cocoa which result in showing a "more arrow" when
+    // the necessary size of the toolbar is increased. Also for some languages
+    // the with doesn't match if the text increase. So manually adjust the size
+    // after changing the text.
+    if (m_pToolBar)
+        m_pToolBar->updateLayout();
+#endif
+}
+
+void UICloudProfileManagerWidget::sltResetCloudProfileDetailsChanges()
+{
+    /* Just push the current item data there again: */
+    sltHandleCurrentItemChange();
+}
+
+void UICloudProfileManagerWidget::sltApplyCloudProfileDetailsChanges()
+{
+    /* Is can be that there is provider item, not profile item currently selected.
+     * In such case we are not applying parameters, we are creating new one profile. */
+    QTreeWidgetItem *pItem = m_pTreeWidget->currentItem();
+    UIItemCloudProvider *pMaybeProviderItem = pItem && pItem->data(0, Data_ItemType).value<CloudItemType>() == CloudItemType_Provider
+                                            ? static_cast<UIItemCloudProvider*>(pItem) : 0;
+    if (pMaybeProviderItem)
+        return sltAddCloudProfile();
+
+    /* Get profile item: */
+    UIItemCloudProfile *pProfileItem = static_cast<UIItemCloudProfile*>(m_pTreeWidget->currentItem());
+    AssertMsgReturnVoid(pProfileItem, ("Current item must not be null!\n"));
+
+    /* Get item data: */
+    UIDataCloudProfile oldData = *pProfileItem;
+    UIDataCloudProfile newData = m_pDetailsWidget->data();
+
+    /* Get VirtualBox for further activities: */
+    const CVirtualBox comVBox = uiCommon().virtualBox();
+
+    /* Get CloudProviderManager for further activities: */
+    CCloudProviderManager comCloudProviderManager = comVBox.GetCloudProviderManager();
+    /* Show error message if necessary: */
+    if (!comVBox.isOk())
+        msgCenter().cannotAcquireCloudProviderManager(comVBox, this);
+    else
+    {
+        /* Get provider item: */
+        UIItemCloudProvider *pProviderItem = static_cast<UIItemCloudProvider*>(pProfileItem->parentItem());
+        /* Acquire provider ID: */
+        const QUuid uId = pProviderItem->data(Column_Name, Data_ProviderID).toUuid();
+
+        /* Look for corresponding provider: */
+        CCloudProvider comCloudProvider = comCloudProviderManager.GetProviderById(uId);
+        /* Show error message if necessary: */
+        if (!comCloudProviderManager.isOk())
+            msgCenter().cannotFindCloudProvider(comCloudProviderManager, uId, this);
+        else
+        {
+            /* Look for corresponding profile: */
+            CCloudProfile comCloudProfile = comCloudProvider.GetProfileByName(oldData.m_strName);
+            /* Show error message if necessary: */
+            if (!comCloudProvider.isOk())
+                msgCenter().cannotFindCloudProfile(comCloudProvider, oldData.m_strName, this);
+            else
+            {
+                /* Set profile name, if necessary: */
+                if (newData.m_strName != oldData.m_strName)
+                    comCloudProfile.SetName(newData.m_strName);
+                /* Show error message if necessary: */
+                if (!comCloudProfile.isOk())
+                    msgCenter().cannotAssignCloudProfileParameter(comCloudProfile, this);
+                else
+                {
+                    /* Iterate through old/new data: */
+                    foreach (const QString &strKey, oldData.m_data.keys())
+                    {
+                        /* Get values: */
+                        const QString strOldValue = oldData.m_data.value(strKey).first;
+                        const QString strNewValue = newData.m_data.value(strKey).first;
+                        if (strNewValue != strOldValue)
+                        {
+                            /* Apply property: */
+                            comCloudProfile.SetProperty(strKey, strNewValue);
+                            /* Show error message if necessary: */
+                            if (!comCloudProfile.isOk())
+                            {
+                                msgCenter().cannotAssignCloudProfileParameter(comCloudProfile, this);
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                /* If profile is Ok finally: */
+                if (comCloudProfile.isOk())
+                {
+                    /* Update profile in the tree: */
+                    UIDataCloudProfile data;
+                    loadCloudProfile(comCloudProfile, *pProviderItem, data);
+                    updateItemForCloudProfile(data, true, pProfileItem);
+
+                    /* Make sure current item fetched: */
+                    sltHandleCurrentItemChange();
+
+                    /* Save profile changes: */
+                    comCloudProvider.SaveProfiles();
+                    /* Show error message if necessary: */
+                    if (!comCloudProvider.isOk())
+                        msgCenter().cannotSaveCloudProfiles(comCloudProvider, this);
+                }
+            }
+        }
+    }
+
+    /* Notify listeners: */
+    emit sigChange();
+}
+
+void UICloudProfileManagerWidget::sltAddCloudProfile()
+{
+    /* Get provider item: */
+    UIItemCloudProvider *pProviderItem = static_cast<UIItemCloudProvider*>(m_pTreeWidget->currentItem());
+    AssertMsgReturnVoid(pProviderItem, ("Current item must not be null!\n"));
+
+    /* Acquire profile name if not proposed by details widget: */
+    QString strProfileName = m_pDetailsWidget->data().m_strName;
+    if (strProfileName.isEmpty())
+    {
+        bool fCancelled = true;
+        QISafePointerInputDialog pDialog = new QIInputDialog(this);
+        if (pDialog)
+        {
+            pDialog->setWindowIcon(UIIconPool::iconSet(":/cloud_profile_add_16px.png"));
+            pDialog->setWindowTitle(UICloudProfileManager::tr("Add Profile"));
+            if (pDialog->exec() == QDialog::Accepted)
+            {
+                strProfileName = pDialog->textValue();
+                fCancelled = false;
+            }
+            delete pDialog;
+        }
+        if (fCancelled)
+            return;
+    }
+
+    /* Get VirtualBox for further activities: */
+    const CVirtualBox comVBox = uiCommon().virtualBox();
+
+    /* Get CloudProviderManager for further activities: */
+    CCloudProviderManager comCloudProviderManager = comVBox.GetCloudProviderManager();
+    /* Show error message if necessary: */
+    if (!comVBox.isOk())
+        msgCenter().cannotAcquireCloudProviderManager(comVBox, this);
+    else
+    {
+        /* Acquire provider ID: */
+        const QUuid uId = pProviderItem->data(Column_Name, Data_ProviderID).toUuid();
+
+        /* Look for corresponding provider: */
+        CCloudProvider comCloudProvider = comCloudProviderManager.GetProviderById(uId);
+        /* Show error message if necessary: */
+        if (!comCloudProviderManager.isOk())
+            msgCenter().cannotFindCloudProvider(comCloudProviderManager, uId, this);
+        else
+        {
+            /* Create new profile: */
+            const QVector<QString> keys = pProviderItem->m_propertyDescriptions.keys().toVector();
+            const QVector<QString> values(keys.size());
+            comCloudProvider.CreateProfile(strProfileName, keys, values);
+
+            /* Show error message if necessary: */
+            if (!comCloudProvider.isOk())
+                msgCenter().cannotCreateCloudProfle(comCloudProvider, this);
+            else
+            {
+                /* Look for corresponding profile: */
+                CCloudProfile comCloudProfile = comCloudProvider.GetProfileByName(strProfileName);
+                /* Show error message if necessary: */
+                if (!comCloudProvider.isOk())
+                    msgCenter().cannotFindCloudProfile(comCloudProvider, strProfileName, this);
+                else
+                {
+                    /* Add profile to the tree: */
+                    UIDataCloudProfile data;
+                    loadCloudProfile(comCloudProfile, *pProviderItem, data);
+                    createItemForCloudProfile(pProviderItem, data, true);
+
+                    /* Save profile changes: */
+                    comCloudProvider.SaveProfiles();
+                    /* Show error message if necessary: */
+                    if (!comCloudProvider.isOk())
+                        msgCenter().cannotSaveCloudProfiles(comCloudProvider, this);
+                }
+            }
+        }
+    }
+
+    /* Notify listeners: */
+    emit sigChange();
+}
+
+void UICloudProfileManagerWidget::sltImportCloudProfiles()
+{
+    /* Get provider item: */
+    UIItemCloudProvider *pProviderItem = static_cast<UIItemCloudProvider*>(m_pTreeWidget->currentItem());
+    AssertMsgReturnVoid(pProviderItem, ("Current item must not be null!\n"));
+
+    /* If there are profiles exist => confirm cloud profile import. */
+    if (   pProviderItem->childCount() != 0
+        && !msgCenter().confirmCloudProfilesImport(this))
+        return;
+
+    /* Get VirtualBox for further activities: */
+    const CVirtualBox comVBox = uiCommon().virtualBox();
+
+    /* Get CloudProviderManager for further activities: */
+    CCloudProviderManager comCloudProviderManager = comVBox.GetCloudProviderManager();
+    /* Show error message if necessary: */
+    if (!comVBox.isOk())
+        msgCenter().cannotAcquireCloudProviderManager(comVBox, this);
+    else
+    {
+        /* Acquire provider ID: */
+        const QUuid uId = pProviderItem->data(Column_Name, Data_ProviderID).toUuid();
+
+        /* Look for corresponding provider: */
+        CCloudProvider comCloudProvider = comCloudProviderManager.GetProviderById(uId);
+        /* Show error message if necessary: */
+        if (!comCloudProviderManager.isOk())
+            msgCenter().cannotFindCloudProvider(comCloudProviderManager, uId, this);
+        else
+        {
+            /* Import profiles: */
+            comCloudProvider.ImportProfiles();
+
+            /* Show error message if necessary: */
+            if (!comCloudProvider.isOk())
+                msgCenter().cannotImportCloudProfiles(comCloudProvider, this);
+            else
+                loadCloudStuff();
+        }
+    }
+
+    /* Notify listeners: */
+    emit sigChange();
+}
+
+void UICloudProfileManagerWidget::sltRemoveCloudProfile()
+{
+    /* Get profile item: */
+    UIItemCloudProfile *pProfileItem = static_cast<UIItemCloudProfile*>(m_pTreeWidget->currentItem());
+    AssertMsgReturnVoid(pProfileItem, ("Current item must not be null!\n"));
+
+    /* Get profile name: */
+    const QString strProfileName(pProfileItem->name());
+
+    /* Confirm cloud profile removal: */
+    if (!msgCenter().confirmCloudProfileRemoval(strProfileName, this))
+        return;
+
+    /* Get VirtualBox for further activities: */
+    const CVirtualBox comVBox = uiCommon().virtualBox();
+
+    /* Get CloudProviderManager for further activities: */
+    CCloudProviderManager comCloudProviderManager = comVBox.GetCloudProviderManager();
+    /* Show error message if necessary: */
+    if (!comVBox.isOk())
+        msgCenter().cannotAcquireCloudProviderManager(comVBox, this);
+    else
+    {
+        /* Get provider item: */
+        UIItemCloudProvider *pProviderItem = static_cast<UIItemCloudProvider*>(pProfileItem->parentItem());
+        /* Acquire provider ID: */
+        const QUuid uId = pProviderItem->data(Column_Name, Data_ProviderID).toUuid();
+
+        /* Look for corresponding provider: */
+        CCloudProvider comCloudProvider = comCloudProviderManager.GetProviderById(uId);
+        /* Show error message if necessary: */
+        if (!comCloudProviderManager.isOk())
+            msgCenter().cannotFindCloudProvider(comCloudProviderManager, uId, this);
+        else
+        {
+            /* Look for corresponding profile: */
+            CCloudProfile comCloudProfile = comCloudProvider.GetProfileByName(strProfileName);
+            /* Show error message if necessary: */
+            if (!comCloudProvider.isOk())
+                msgCenter().cannotFindCloudProfile(comCloudProvider, strProfileName, this);
+            else
+            {
+                /* Remove current profile: */
+                comCloudProfile.Remove();
+                /// @todo how do we check that?
+
+                /* Remove interface from the tree: */
+                delete pProfileItem;
+
+                /* Save profile changes: */
+                comCloudProvider.SaveProfiles();
+                /* Show error message if necessary: */
+                if (!comCloudProvider.isOk())
+                    msgCenter().cannotSaveCloudProfiles(comCloudProvider, this);
+            }
+        }
+    }
+
+    /* Notify listeners: */
+    emit sigChange();
+}
+
+void UICloudProfileManagerWidget::sltToggleCloudProfileDetailsVisibility(bool fVisible)
+{
+    /* Save the setting: */
+    gEDataManager->setCloudProfileManagerDetailsExpanded(fVisible);
+    /* Show/hide details area and Apply button: */
+    m_pDetailsWidget->setVisible(fVisible);
+    /* Notify external lsiteners: */
+    emit sigCloudProfileDetailsVisibilityChanged(fVisible);
+}
+
+void UICloudProfileManagerWidget::sltShowCloudProfileTryPage()
+{
+    uiCommon().openURL("https://myservices.us.oraclecloud.com/mycloud/signup");
+}
+
+void UICloudProfileManagerWidget::sltShowCloudProfileHelp()
+{
+    uiCommon().openURL("https://docs.cloud.oracle.com/iaas/Content/API/Concepts/sdkconfig.htm");
+}
+
+void UICloudProfileManagerWidget::sltHandleCurrentItemChange()
+{
+    /* Get items: */
+    QTreeWidgetItem *pItem = m_pTreeWidget->currentItem();
+    UIItemCloudProvider *pItemProvider = pItem && pItem->data(0, Data_ItemType).value<CloudItemType>() == CloudItemType_Provider
+                                       ? static_cast<UIItemCloudProvider*>(pItem)
+                                       : 0;
+    UIItemCloudProfile  *pItemProfile  = pItem && pItem->data(0, Data_ItemType).value<CloudItemType>() == CloudItemType_Profile
+                                       ? static_cast<UIItemCloudProfile*>(pItem)
+                                       : 0;
+
+    /* Update actions availability: */
+    m_pActionPool->action(UIActionIndexST_M_Cloud_S_Add)->setEnabled(!pItem || pItemProvider);
+    m_pActionPool->action(UIActionIndexST_M_Cloud_S_Import)->setEnabled(!pItem || pItemProvider);
+    m_pActionPool->action(UIActionIndexST_M_Cloud_S_Remove)->setEnabled(pItemProfile);
+    m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details)->setEnabled(pItemProfile || pItemProvider);
+
+    /* If there is an item => update details data: */
+    if (pItemProfile)
+        m_pDetailsWidget->setData(*pItemProfile);
+    /* Otherwise => clear details data: */
+    else
+        m_pDetailsWidget->setData(UIDataCloudProfile());
+
+    /* Update details area visibility: */
+    sltToggleCloudProfileDetailsVisibility(pItem && m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details)->isChecked());
+}
+
+void UICloudProfileManagerWidget::sltHandleContextMenuRequest(const QPoint &position)
+{
+    /* Get items: */
+    QTreeWidgetItem *pItem = m_pTreeWidget->itemAt(position);
+    UIItemCloudProvider *pItemProvider = pItem && pItem->data(0, Data_ItemType).value<CloudItemType>() == CloudItemType_Provider
+                                       ? static_cast<UIItemCloudProvider*>(pItem)
+                                       : 0;
+    UIItemCloudProfile  *pItemProfile  = pItem && pItem->data(0, Data_ItemType).value<CloudItemType>() == CloudItemType_Profile
+                                       ? static_cast<UIItemCloudProfile*>(pItem)
+                                       : 0;
+
+    /* Compose temporary context-menu: */
+    QMenu menu;
+    if (pItemProfile)
+    {
+        menu.addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Remove));
+        menu.addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details));
+    }
+    else if (pItemProvider)
+    {
+        menu.addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Add));
+        menu.addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Import));
+        menu.addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details));
+    }
+
+    /* And show it: */
+    menu.exec(m_pTreeWidget->mapToGlobal(position));
+}
+
+void UICloudProfileManagerWidget::prepare()
+{
+    /* Prepare actions: */
+    prepareActions();
+    /* Prepare widgets: */
+    prepareWidgets();
+
+    /* Load settings: */
+    loadSettings();
+
+    /* Apply language settings: */
+    retranslateUi();
+
+    /* Load cloud stuff: */
+    loadCloudStuff();
+}
+
+void UICloudProfileManagerWidget::prepareActions()
+{
+    /* First of all, add actions which has smaller shortcut scope: */
+    addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Add));
+    addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Import));
+    addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Remove));
+    addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details));
+    addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_TryPage));
+    addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Help));
+
+    /* Connect actions: */
+    connect(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Add), &QAction::triggered,
+            this, &UICloudProfileManagerWidget::sltAddCloudProfile);
+    connect(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Import), &QAction::triggered,
+            this, &UICloudProfileManagerWidget::sltImportCloudProfiles);
+    connect(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Remove), &QAction::triggered,
+            this, &UICloudProfileManagerWidget::sltRemoveCloudProfile);
+    connect(m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details), &QAction::toggled,
+            this, &UICloudProfileManagerWidget::sltToggleCloudProfileDetailsVisibility);
+    connect(m_pActionPool->action(UIActionIndexST_M_Cloud_S_TryPage), &QAction::triggered,
+            this, &UICloudProfileManagerWidget::sltShowCloudProfileTryPage);
+    connect(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Help), &QAction::triggered,
+            this, &UICloudProfileManagerWidget::sltShowCloudProfileHelp);
+}
+
+void UICloudProfileManagerWidget::prepareWidgets()
+{
+    /* Create main-layout: */
+    new QVBoxLayout(this);
+    if (layout())
+    {
+        /* Configure layout: */
+        layout()->setContentsMargins(0, 0, 0, 0);
+#ifdef VBOX_WS_MAC
+        layout()->setSpacing(10);
+#else
+        layout()->setSpacing(qApp->style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing) / 2);
+#endif
+
+        /* Prepare toolbar, if requested: */
+        if (m_fShowToolbar)
+            prepareToolBar();
+        /* Prepare tree-widget: */
+        prepareTreeWidget();
+        /* Prepare details-widget: */
+        prepareDetailsWidget();
+    }
+}
+
+void UICloudProfileManagerWidget::prepareToolBar()
+{
+    /* Create toolbar: */
+    m_pToolBar = new UIToolBar(parentWidget());
+    if (m_pToolBar)
+    {
+        /* Configure toolbar: */
+        const int iIconMetric = (int)(QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize));
+        m_pToolBar->setIconSize(QSize(iIconMetric, iIconMetric));
+        m_pToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
+
+        /* Add toolbar actions: */
+        m_pToolBar->addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Add));
+        m_pToolBar->addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Import));
+        m_pToolBar->addSeparator();
+        m_pToolBar->addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Remove));
+        m_pToolBar->addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details));
+        m_pToolBar->addSeparator();
+        m_pToolBar->addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_TryPage));
+        m_pToolBar->addAction(m_pActionPool->action(UIActionIndexST_M_Cloud_S_Help));
+
+#ifdef VBOX_WS_MAC
+        /* Check whether we are embedded into a stack: */
+        if (m_enmEmbedding == EmbedTo_Stack)
+        {
+            /* Add into layout: */
+            layout()->addWidget(m_pToolBar);
+        }
+#else
+        /* Add into layout: */
+        layout()->addWidget(m_pToolBar);
+#endif
+    }
+}
+
+void UICloudProfileManagerWidget::prepareTreeWidget()
+{
+    /* Create tree-widget: */
+    m_pTreeWidget = new QITreeWidget;
+    if (m_pTreeWidget)
+    {
+        /* Configure tree-widget: */
+        m_pTreeWidget->header()->hide();
+        m_pTreeWidget->setRootIsDecorated(false);
+        m_pTreeWidget->setAlternatingRowColors(true);
+        m_pTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+        m_pTreeWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+        m_pTreeWidget->setColumnCount(Column_Max);
+        m_pTreeWidget->setSortingEnabled(true);
+        m_pTreeWidget->sortByColumn(Column_Name, Qt::AscendingOrder);
+        m_pTreeWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+        connect(m_pTreeWidget, &QITreeWidget::currentItemChanged,
+                this, &UICloudProfileManagerWidget::sltHandleCurrentItemChange);
+        connect(m_pTreeWidget, &QITreeWidget::customContextMenuRequested,
+                this, &UICloudProfileManagerWidget::sltHandleContextMenuRequest);
+        connect(m_pTreeWidget, &QITreeWidget::itemDoubleClicked,
+                m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details), &QAction::setChecked);
+
+        /* Add into layout: */
+        layout()->addWidget(m_pTreeWidget);
+    }
+}
+
+void UICloudProfileManagerWidget::prepareDetailsWidget()
+{
+    /* Create details-widget: */
+    m_pDetailsWidget = new UICloudProfileDetailsWidget(m_enmEmbedding);
+    if (m_pDetailsWidget)
+    {
+        /* Configure details-widget: */
+        m_pDetailsWidget->setVisible(false);
+        m_pDetailsWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
+        connect(m_pDetailsWidget, &UICloudProfileDetailsWidget::sigDataChanged,
+                this, &UICloudProfileManagerWidget::sigCloudProfileDetailsDataChanged);
+        connect(m_pDetailsWidget, &UICloudProfileDetailsWidget::sigDataChangeRejected,
+                this, &UICloudProfileManagerWidget::sltResetCloudProfileDetailsChanges);
+        connect(m_pDetailsWidget, &UICloudProfileDetailsWidget::sigDataChangeAccepted,
+                this, &UICloudProfileManagerWidget::sltApplyCloudProfileDetailsChanges);
+
+        /* Add into layout: */
+        layout()->addWidget(m_pDetailsWidget);
+    }
+}
+
+void UICloudProfileManagerWidget::loadSettings()
+{
+    /* Details action/widget: */
+    m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details)->setChecked(gEDataManager->cloudProfileManagerDetailsExpanded());
+    sltToggleCloudProfileDetailsVisibility(m_pActionPool->action(UIActionIndexST_M_Cloud_T_Details)->isChecked());
+}
+
+void UICloudProfileManagerWidget::loadCloudStuff()
+{
+    /* Clear tree first of all: */
+    m_pTreeWidget->clear();
+
+    /* Get VirtualBox for further activities: */
+    const CVirtualBox comVBox = uiCommon().virtualBox();
+
+    /* Get CloudProviderManager for further activities: */
+    const CCloudProviderManager comCloudProviderManager = comVBox.GetCloudProviderManager();
+    /* Show error message if necessary: */
+    if (!comVBox.isOk())
+        msgCenter().cannotAcquireCloudProviderManager(comVBox, this);
+    else
+    {
+        /* Iterate through existing providers: */
+        foreach (const CCloudProvider &comCloudProvider, comCloudProviderManager.GetProviders())
+        {
+            /* Skip if we have nothing to populate (file missing?): */
+            if (comCloudProvider.isNull())
+                continue;
+
+            /* Load provider data: */
+            UIDataCloudProvider providerData;
+            loadCloudProvider(comCloudProvider, providerData);
+            createItemForCloudProvider(providerData, false);
+
+            /* Make sure provider item is properly inserted: */
+            UIItemCloudProvider *pItem = searchItem(providerData.m_uuid);
+
+            /* Iterate through existing profiles: */
+            foreach (const CCloudProfile &comCloudProfile, comCloudProvider.GetProfiles())
+            {
+                /* Load profile data: */
+                UIDataCloudProfile profileData;
+                loadCloudProfile(comCloudProfile, providerData, profileData);
+                createItemForCloudProfile(pItem, profileData, false);
+            }
+
+            /* Expand provider item finally: */
+            pItem->setExpanded(true);
+        }
+
+        /* Choose the 1st item as current initially: */
+        m_pTreeWidget->setCurrentItem(m_pTreeWidget->topLevelItem(0));
+        sltHandleCurrentItemChange();
+    }
+}
+
+void UICloudProfileManagerWidget::loadCloudProvider(const CCloudProvider &comProvider, UIDataCloudProvider &data)
+{
+    /* Gather provider settings: */
+    if (comProvider.isOk())
+        data.m_uuid = comProvider.GetId();
+    if (comProvider.isOk())
+        data.m_strName = comProvider.GetName();
+    foreach (const QString &strSupportedPropertyName, comProvider.GetSupportedPropertyNames())
+        data.m_propertyDescriptions[strSupportedPropertyName] = comProvider.GetPropertyDescription(strSupportedPropertyName);
+
+    /* Show error message if necessary: */
+    if (!comProvider.isOk())
+        msgCenter().cannotAcquireCloudProviderParameter(comProvider, this);
+}
+
+void UICloudProfileManagerWidget::loadCloudProfile(const CCloudProfile &comProfile, const UIDataCloudProvider &providerData, UIDataCloudProfile &profileData)
+{
+    /* Gather profile settings: */
+    if (comProfile.isOk())
+        profileData.m_strName = comProfile.GetName();
+
+    if (comProfile.isOk())
+    {
+        /* Acquire properties: */
+        QVector<QString> keys;
+        QVector<QString> values;
+        QVector<QString> descriptions;
+        values = comProfile.GetProperties(QString(), keys);
+
+        /* Sync sizes: */
+        values.resize(keys.size());
+        descriptions.resize(keys.size());
+
+        if (comProfile.isOk())
+        {
+            /* Enumerate all the keys: */
+            for (int i = 0; i < keys.size(); ++i)
+                profileData.m_data[keys.at(i)] = qMakePair(values.at(i), providerData.m_propertyDescriptions.value(keys.at(i)));
+        }
+    }
+
+    /* Show error message if necessary: */
+    if (!comProfile.isOk())
+        msgCenter().cannotAcquireCloudProfileParameter(comProfile, this);
+}
+
+UIItemCloudProvider *UICloudProfileManagerWidget::searchItem(const QUuid &uuid) const
+{
+    /* Iterated through top-level items: */
+    for (int i = 0; i < m_pTreeWidget->topLevelItemCount(); ++i)
+        if (m_pTreeWidget->topLevelItem(i)->data(0, Data_ProviderID).toUuid() == uuid)
+            return static_cast<UIItemCloudProvider*>(m_pTreeWidget->topLevelItem(i));
+    /* Null by default: */
+    return 0;
+}
+
+void UICloudProfileManagerWidget::createItemForCloudProvider(const UIDataCloudProvider &data, bool fChooseItem)
+{
+    /* Create new provider item: */
+    UIItemCloudProvider *pItem = new UIItemCloudProvider;
+    if (pItem)
+    {
+        /* Configure item: */
+        pItem->UIDataCloudProvider::operator=(data);
+        pItem->updateFields();
+        /* Add item to the tree: */
+        m_pTreeWidget->addTopLevelItem(pItem);
+        /* And choose it as current if necessary: */
+        if (fChooseItem)
+            m_pTreeWidget->setCurrentItem(pItem);
+    }
+}
+
+void UICloudProfileManagerWidget::createItemForCloudProfile(QTreeWidgetItem *pParent, const UIDataCloudProfile &data, bool fChooseItem)
+{
+    /* Create new profile item: */
+    UIItemCloudProfile *pItem = new UIItemCloudProfile;
+    if (pItem)
+    {
+        /* Configure item: */
+        pItem->UIDataCloudProfile::operator=(data);
+        pItem->updateFields();
+        /* Add item to the parent: */
+        pParent->addChild(pItem);
+        /* And choose it as current if necessary: */
+        if (fChooseItem)
+            m_pTreeWidget->setCurrentItem(pItem);
+    }
+}
+
+void UICloudProfileManagerWidget::updateItemForCloudProfile(const UIDataCloudProfile &data, bool fChooseItem, UIItemCloudProfile *pItem)
+{
+    /* Update passed item: */
+    if (pItem)
+    {
+        /* Configure item: */
+        pItem->UIDataCloudProfile::operator=(data);
+        pItem->updateFields();
+        /* And choose it as current if necessary: */
+        if (fChooseItem)
+            m_pTreeWidget->setCurrentItem(pItem);
+    }
+}
+
+
+/*********************************************************************************************************************************
+*   Class UICloudProfileManagerFactory implementation.                                                                           *
+*********************************************************************************************************************************/
+
+UICloudProfileManagerFactory::UICloudProfileManagerFactory(UIActionPool *pActionPool /* = 0 */)
+    : m_pActionPool(pActionPool)
+{
+}
+
+void UICloudProfileManagerFactory::create(QIManagerDialog *&pDialog, QWidget *pCenterWidget)
+{
+    pDialog = new UICloudProfileManager(pCenterWidget, m_pActionPool);
+}
+
+
+/*********************************************************************************************************************************
+*   Class UICloudProfileManager implementation.                                                                                  *
+*********************************************************************************************************************************/
+
+UICloudProfileManager::UICloudProfileManager(QWidget *pCenterWidget, UIActionPool *pActionPool)
+    : QIWithRetranslateUI<QIManagerDialog>(pCenterWidget)
+    , m_pActionPool(pActionPool)
+{
+}
+
+void UICloudProfileManager::sltHandleButtonBoxClick(QAbstractButton *pButton)
+{
+    /* Disable buttons first of all: */
+    button(ButtonType_Reset)->setEnabled(false);
+    button(ButtonType_Apply)->setEnabled(false);
+
+    /* Compare with known buttons: */
+    if (pButton == button(ButtonType_Reset))
+        emit sigDataChangeRejected();
+    else
+    if (pButton == button(ButtonType_Apply))
+        emit sigDataChangeAccepted();
+}
+
+void UICloudProfileManager::retranslateUi()
+{
+    /* Translate window title: */
+    setWindowTitle(tr("Cloud Profile Manager"));
+
+    /* Translate buttons: */
+    button(ButtonType_Reset)->setText(tr("Reset"));
+    button(ButtonType_Apply)->setText(tr("Apply"));
+    button(ButtonType_Close)->setText(tr("Close"));
+    button(ButtonType_Reset)->setStatusTip(tr("Reset changes in current cloud profile details"));
+    button(ButtonType_Apply)->setStatusTip(tr("Apply changes in current cloud profile details"));
+    button(ButtonType_Close)->setStatusTip(tr("Close dialog without saving"));
+    button(ButtonType_Reset)->setShortcut(QString("Ctrl+Backspace"));
+    button(ButtonType_Apply)->setShortcut(QString("Ctrl+Return"));
+    button(ButtonType_Close)->setShortcut(Qt::Key_Escape);
+    button(ButtonType_Reset)->setToolTip(tr("Reset Changes (%1)").arg(button(ButtonType_Reset)->shortcut().toString()));
+    button(ButtonType_Apply)->setToolTip(tr("Apply Changes (%1)").arg(button(ButtonType_Apply)->shortcut().toString()));
+    button(ButtonType_Close)->setToolTip(tr("Close Window (%1)").arg(button(ButtonType_Close)->shortcut().toString()));
+}
+
+void UICloudProfileManager::configure()
+{
+    /* Apply window icons: */
+    setWindowIcon(UIIconPool::iconSetFull(":/cloud_profile_manager_32px.png", ":/cloud_profile_manager_16px.png"));
+}
+
+void UICloudProfileManager::configureCentralWidget()
+{
+    /* Create widget: */
+    UICloudProfileManagerWidget *pWidget = new UICloudProfileManagerWidget(EmbedTo_Dialog, m_pActionPool, true, this);
+    if (pWidget)
+    {
+        /* Configure widget: */
+        setWidget(pWidget);
+        setWidgetMenu(pWidget->menu());
+#ifdef VBOX_WS_MAC
+        setWidgetToolbar(pWidget->toolbar());
+#endif
+        connect(pWidget, &UICloudProfileManagerWidget::sigChange,
+                this, &UICloudProfileManager::sigChange);
+        connect(this, &UICloudProfileManager::sigDataChangeRejected,
+                pWidget, &UICloudProfileManagerWidget::sltResetCloudProfileDetailsChanges);
+        connect(this, &UICloudProfileManager::sigDataChangeAccepted,
+                pWidget, &UICloudProfileManagerWidget::sltApplyCloudProfileDetailsChanges);
+
+        /* Add into layout: */
+        centralWidget()->layout()->addWidget(pWidget);
+    }
+}
+
+void UICloudProfileManager::configureButtonBox()
+{
+    /* Configure button-box: */
+    connect(widget(), &UICloudProfileManagerWidget::sigCloudProfileDetailsVisibilityChanged,
+            button(ButtonType_Apply), &QPushButton::setVisible);
+    connect(widget(), &UICloudProfileManagerWidget::sigCloudProfileDetailsVisibilityChanged,
+            button(ButtonType_Reset), &QPushButton::setVisible);
+    connect(widget(), &UICloudProfileManagerWidget::sigCloudProfileDetailsDataChanged,
+            button(ButtonType_Apply), &QPushButton::setEnabled);
+    connect(widget(), &UICloudProfileManagerWidget::sigCloudProfileDetailsDataChanged,
+            button(ButtonType_Reset), &QPushButton::setEnabled);
+    connect(buttonBox(), &QIDialogButtonBox::clicked,
+            this, &UICloudProfileManager::sltHandleButtonBoxClick);
+    // WORKAROUND:
+    // Since we connected signals later than extra-data loaded
+    // for signals above, we should handle that stuff here again:
+    button(ButtonType_Apply)->setVisible(gEDataManager->cloudProfileManagerDetailsExpanded());
+    button(ButtonType_Reset)->setVisible(gEDataManager->cloudProfileManagerDetailsExpanded());
+}
+
+void UICloudProfileManager::finalize()
+{
+    /* Apply language settings: */
+    retranslateUi();
+}
+
+UICloudProfileManagerWidget *UICloudProfileManager::widget()
+{
+    return qobject_cast<UICloudProfileManagerWidget*>(QIManagerDialog::widget());
+}
Index: trunk/src/VBox/Frontends/VirtualBox/src/cloud/profilemanager/UICloudProfileManager.h
===================================================================
--- trunk/src/VBox/Frontends/VirtualBox/src/cloud/profilemanager/UICloudProfileManager.h	(revision 83950)
+++ trunk/src/VBox/Frontends/VirtualBox/src/cloud/profilemanager/UICloudProfileManager.h	(revision 83950)
@@ -0,0 +1,270 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UICloudProfileManager class declaration.
+ */
+
+/*
+ * Copyright (C) 2009-2020 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef FEQT_INCLUDED_SRC_cloud_profilemanager_UICloudProfileManager_h
+#define FEQT_INCLUDED_SRC_cloud_profilemanager_UICloudProfileManager_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+/* GUI includes: */
+#include "QIManagerDialog.h"
+#include "QIWithRetranslateUI.h"
+
+/* Forward declarations: */
+class QAbstractButton;
+class QTreeWidgetItem;
+class QITreeWidget;
+class UIActionPool;
+class UICloudProfileDetailsWidget;
+class UIItemCloudProfile;
+class UIItemCloudProvider;
+class UIToolBar;
+struct UIDataCloudProfile;
+struct UIDataCloudProvider;
+class CCloudProfile;
+class CCloudProvider;
+
+
+/** QWidget extension providing GUI with the pane to control cloud profile related functionality. */
+class UICloudProfileManagerWidget : public QIWithRetranslateUI<QWidget>
+{
+    Q_OBJECT;
+
+signals:
+
+    /** Notifies listeners about dialog change. */
+    void sigChange();
+
+    /** Notifies listeners about cloud profile details-widget @a fVisible. */
+    void sigCloudProfileDetailsVisibilityChanged(bool fVisible);
+    /** Notifies listeners about cloud profile details data @a fDiffers. */
+    void sigCloudProfileDetailsDataChanged(bool fDiffers);
+
+public:
+
+    /** Constructs Cloud Profile Manager widget.
+      * @param  enmEmbedding  Brings the type of widget embedding.
+      * @param  pActionPool   Brings the action-pool reference.
+      * @param  fShowToolbar  Brings whether we should create/show toolbar. */
+    UICloudProfileManagerWidget(EmbedTo enmEmbedding, UIActionPool *pActionPool,
+                                bool fShowToolbar = true, QWidget *pParent = 0);
+
+    /** Returns the menu. */
+    QMenu *menu() const;
+
+#ifdef VBOX_WS_MAC
+    /** Returns the toolbar. */
+    UIToolBar *toolbar() const { return m_pToolBar; }
+#endif
+
+protected:
+
+    /** @name Event-handling stuff.
+      * @{ */
+        /** Handles translation event. */
+        virtual void retranslateUi() /* override */;
+    /** @} */
+
+public slots:
+
+    /** @name Details-widget stuff.
+      * @{ */
+        /** Handles command to reset cloud profile details changes. */
+        void sltResetCloudProfileDetailsChanges();
+        /** Handles command to apply cloud profile details changes. */
+        void sltApplyCloudProfileDetailsChanges();
+    /** @} */
+
+private slots:
+
+    /** @name Menu/action stuff.
+      * @{ */
+        /** Handles command to create cloud profile. */
+        void sltAddCloudProfile();
+        /** Handles command to import cloud profiles. */
+        void sltImportCloudProfiles();
+        /** Handles command to remove cloud profile. */
+        void sltRemoveCloudProfile();
+        /** Handles command to make cloud profile details @a fVisible. */
+        void sltToggleCloudProfileDetailsVisibility(bool fVisible);
+        /** Handles command to show cloud profile help. */
+        void sltShowCloudProfileTryPage();
+        /** Handles command to show cloud profile help. */
+        void sltShowCloudProfileHelp();
+    /** @} */
+
+    /** @name Tree-widget stuff.
+      * @{ */
+        /** Handles tree-widget current item change. */
+        void sltHandleCurrentItemChange();
+        /** Handles context menu request for tree-widget @a position. */
+        void sltHandleContextMenuRequest(const QPoint &position);
+    /** @} */
+
+private:
+
+    /** @name Prepare/cleanup cascade.
+      * @{ */
+        /** Prepares all. */
+        void prepare();
+        /** Prepares actions. */
+        void prepareActions();
+        /** Prepares widgets. */
+        void prepareWidgets();
+        /** Prepares toolbar. */
+        void prepareToolBar();
+        /** Prepares tree-widget. */
+        void prepareTreeWidget();
+        /** Prepares details-widget. */
+        void prepareDetailsWidget();
+        /** Load settings: */
+        void loadSettings();
+    /** @} */
+
+    /** @name Loading stuff.
+      * @{ */
+        /** Loads cloud stuff. */
+        void loadCloudStuff();
+        /** Loads cloud @a comProvider data to passed @a data container. */
+        void loadCloudProvider(const CCloudProvider &comProvider, UIDataCloudProvider &data);
+        /** Loads cloud @a comProfile data to passed @a profileData container, using @a providerData as hint. */
+        void loadCloudProfile(const CCloudProfile &comProfile, const UIDataCloudProvider &providerData, UIDataCloudProfile &profileData);
+    /** @} */
+
+    /** @name Tree-widget stuff.
+      * @{ */
+        /** Seearches a provider item with specified @a uuid. */
+        UIItemCloudProvider *searchItem(const QUuid &uuid) const;
+
+        /** Creates a new tree-widget item on the basis of passed @a data, @a fChooseItem if requested. */
+        void createItemForCloudProvider(const UIDataCloudProvider &data, bool fChooseItem);
+
+        /** Creates a new tree-widget item as a child of certain @a pParent, on the basis of passed @a data, @a fChooseItem if requested. */
+        void createItemForCloudProfile(QTreeWidgetItem *pParent, const UIDataCloudProfile &data, bool fChooseItem);
+        /** Updates the passed tree-widget item on the basis of passed @a data, @a fChooseItem if requested. */
+        void updateItemForCloudProfile(const UIDataCloudProfile &data, bool fChooseItem, UIItemCloudProfile *pItem);
+    /** @} */
+
+    /** @name General variables.
+      * @{ */
+        /** Holds the widget embedding type. */
+        const EmbedTo m_enmEmbedding;
+        /** Holds the action-pool reference. */
+        UIActionPool *m_pActionPool;
+        /** Holds whether we should create/show toolbar. */
+        const bool    m_fShowToolbar;
+    /** @} */
+
+    /** @name Toolbar and menu variables.
+      * @{ */
+        /** Holds the toolbar instance. */
+        UIToolBar *m_pToolBar;
+    /** @} */
+
+    /** @name Splitter variables.
+      * @{ */
+        /** Holds the tree-widget instance. */
+        QITreeWidget *m_pTreeWidget;
+        /** Holds the details-widget instance. */
+        UICloudProfileDetailsWidget *m_pDetailsWidget;
+    /** @} */
+};
+
+
+/** QIManagerDialogFactory extension used as a factory for Cloud Profile Manager dialog. */
+class UICloudProfileManagerFactory : public QIManagerDialogFactory
+{
+public:
+
+    /** Constructs Cloud Profile Manager factory acquiring additional arguments.
+      * @param  pActionPool  Brings the action-pool reference. */
+    UICloudProfileManagerFactory(UIActionPool *pActionPool = 0);
+
+protected:
+
+    /** Creates derived @a pDialog instance.
+      * @param  pCenterWidget  Brings the widget reference to center according to. */
+    virtual void create(QIManagerDialog *&pDialog, QWidget *pCenterWidget) /* override */;
+
+    /** Holds the action-pool reference. */
+    UIActionPool *m_pActionPool;
+};
+
+
+/** QIManagerDialog extension providing GUI with the dialog to control cloud profile related functionality. */
+class UICloudProfileManager : public QIWithRetranslateUI<QIManagerDialog>
+{
+    Q_OBJECT;
+
+signals:
+
+    /** Notifies listeners about data change rejected and should be reseted. */
+    void sigDataChangeRejected();
+    /** Notifies listeners about data change accepted and should be applied. */
+    void sigDataChangeAccepted();
+
+private slots:
+
+    /** @name Button-box stuff.
+      * @{ */
+        /** Handles button-box button click. */
+        void sltHandleButtonBoxClick(QAbstractButton *pButton);
+    /** @} */
+
+private:
+
+    /** Constructs Cloud Profile Manager dialog.
+      * @param  pCenterWidget  Brings the widget reference to center according to.
+      * @param  pActionPool    Brings the action-pool reference. */
+    UICloudProfileManager(QWidget *pCenterWidget, UIActionPool *pActionPool);
+
+    /** @name Event-handling stuff.
+      * @{ */
+        /** Handles translation event. */
+        virtual void retranslateUi() /* override */;
+    /** @} */
+
+    /** @name Prepare/cleanup cascade.
+      * @{ */
+        /** Configures all. */
+        virtual void configure() /* override */;
+        /** Configures central-widget. */
+        virtual void configureCentralWidget() /* override */;
+        /** Configures button-box. */
+        virtual void configureButtonBox() /* override */;
+        /** Perform final preparations. */
+        virtual void finalize() /* override */;
+    /** @} */
+
+    /** @name Widget stuff.
+      * @{ */
+        /** Returns the widget. */
+        virtual UICloudProfileManagerWidget *widget() /* override */;
+    /** @} */
+
+    /** @name Action related variables.
+      * @{ */
+        /** Holds the action-pool reference. */
+        UIActionPool *m_pActionPool;
+    /** @} */
+
+    /** Allow factory access to private/protected members: */
+    friend class UICloudProfileManagerFactory;
+};
+
+#endif /* !FEQT_INCLUDED_SRC_cloud_profilemanager_UICloudProfileManager_h */
