VirtualBox

Changeset 87354 in vbox


Ignore:
Timestamp:
Jan 21, 2021 4:08:36 PM (4 years ago)
Author:
vboxsync
Message:

FE/Qt: bugref:9913: Implementing Extension Pack Manager (initial version, no icons for now).

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
4 deleted
14 edited
3 copied

Legend:

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

    r87316 r87354  
    258258        ./src/cloud/profilemanager \
    259259        ./src/converter \
     260        ./src/extensionpackmanager \
    260261        ./src/extensions \
    261262        ./src/extensions/graphics \
     
    573574        src/cloud/profilemanager/UICloudProfileDetailsWidget.h \
    574575        src/cloud/profilemanager/UICloudProfileManager.h \
     576        src/extensionpackmanager/UIExtensionPackManager.h \
    575577        src/globals/UIStarter.h \
    576578        src/manager/UIErrorPane.h \
     
    937939        src/cloud/consolemanager/UICloudConsoleManager.cpp \
    938940        src/cloud/profilemanager/UICloudProfileManager.cpp \
     941        src/extensionpackmanager/UIExtensionPackManager.cpp \
    939942        src/manager/UIVirtualBoxManager.cpp \
    940943        src/manager/UIVirtualMachineItemCloud.cpp \
     
    10521055        src/cloud/profilemanager/UICloudProfileDetailsWidget.cpp \
    10531056        src/cloud/profilemanager/UICloudProfileManager.cpp \
     1057        src/extensionpackmanager/UIExtensionPackManager.cpp \
    10541058        src/globals/UIStarter.cpp \
    10551059        src/manager/UICloudEntityKey.cpp \
  • trunk/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackendGlobal.cpp

    r87316 r87354  
    15131513    {
    15141514        case UIToolType_Welcome:     strResult = "Welcome"; break;
     1515        case UIToolType_Extensions:  strResult = "Extensions"; break;
    15151516        case UIToolType_Media:       strResult = "Media"; break;
    15161517        case UIToolType_Network:     strResult = "Network"; break;
     
    15371538    QStringList keys;      QList<UIToolType> values;
    15381539    keys << "Welcome";     values << UIToolType_Welcome;
     1540    keys << "Extensions";  values << UIToolType_Extensions;
    15391541    keys << "Media";       values << UIToolType_Media;
    15401542    keys << "Network";     values << UIToolType_Network;
  • trunk/src/VBox/Frontends/VirtualBox/src/extensionpackmanager/UIExtensionPackManager.cpp

    r87311 r87354  
    11/* $Id$ */
    22/** @file
    3  * VBox Qt GUI - UICloudProfileManager class implementation.
     3 * VBox Qt GUI - UIExtensionPackManager class implementation.
    44 */
    55
    66/*
    7  * Copyright (C) 2009-2020 Oracle Corporation
     7 * Copyright (C) 2009-2021 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1717
    1818/* Qt includes: */
     19#include <QDir>
    1920#include <QHeaderView>
    2021#include <QPushButton>
     22#include <QTextStream>
    2123#include <QVBoxLayout>
    2224
    2325/* GUI includes: */
    24 #include "QIDialogButtonBox.h"
    25 #include "QIInputDialog.h"
    26 #include "QIMessageBox.h"
     26//#include "QIDialogButtonBox.h"
     27//#include "QIInputDialog.h"
     28//#include "QIMessageBox.h"
     29#include "QIFileDialog.h"
    2730#include "QIToolBar.h"
    2831#include "QITreeWidget.h"
    2932#include "UIActionPoolManager.h"
    30 #include "UICloudNetworkingStuff.h"
    31 #include "UICloudProfileDetailsWidget.h"
    32 #include "UICloudProfileManager.h"
    3333#include "UICommon.h"
     34#include "UIExtensionPackManager.h"
    3435#include "UIExtraDataManager.h"
    3536#include "UIIconPool.h"
    3637#include "UIMessageCenter.h"
    37 #include "UIVirtualBoxEventHandler.h"
     38//#include "UIVirtualBoxEventHandler.h"
    3839
    3940/* COM includes: */
    40 #include "CCloudProfile.h"
    41 #include "CCloudProvider.h"
    42 #include "CCloudProviderManager.h"
    43 
    44 
    45 /** Tree-widget item types. */
    46 enum CloudItemType
    47 {
    48     CloudItemType_Invalid  = 0,
    49     CloudItemType_Provider = 1,
    50     CloudItemType_Profile  = 2
     41#include "CExtPack.h"
     42#include "CExtPackManager.h"
     43
     44
     45/** Extension pack tree-widget column indexes. */
     46enum ExtensionPackColumn
     47{
     48    ExtensionPackColumn_Usable,
     49    ExtensionPackColumn_Name,
     50    ExtensionPackColumn_Version,
     51    ExtensionPackColumn_Max,
    5152};
    52 Q_DECLARE_METATYPE(CloudItemType);
    53 
    54 /** Tree-widget data types. */
    55 enum
    56 {
    57     Data_ItemType          = Qt::UserRole + 1,
    58     Data_ProviderShortName = Qt::UserRole + 2,
    59     Data_Definition        = Qt::UserRole + 3,
     53
     54
     55/** Extension Pack Manager: Extension Pack data structure. */
     56struct UIDataExtensionPack
     57{
     58    /** Constructs data. */
     59    UIDataExtensionPack()
     60        : m_strName(QString())
     61        , m_strDescription(QString())
     62        , m_strVersion(QString())
     63        , m_uRevision(0)
     64        , m_fIsUsable(false)
     65        , m_strWhyUnusable(QString())
     66    {}
     67
     68    /** Returns whether the @a other passed data is equal to this one. */
     69    bool equal(const UIDataExtensionPack &other) const
     70    {
     71        return true
     72               && (m_strName == other.m_strName)
     73               && (m_strDescription == other.m_strDescription)
     74               && (m_strVersion == other.m_strVersion)
     75               && (m_uRevision == other.m_uRevision)
     76               && (m_fIsUsable == other.m_fIsUsable)
     77               && (m_strWhyUnusable == other.m_strWhyUnusable)
     78               ;
     79    }
     80
     81    /** Returns whether the @a other passed data is equal to this one. */
     82    bool operator==(const UIDataExtensionPack &other) const { return equal(other); }
     83    /** Returns whether the @a other passed data is different from this one. */
     84    bool operator!=(const UIDataExtensionPack &other) const { return !equal(other); }
     85
     86    /** Holds the extension item name. */
     87    QString  m_strName;
     88    /** Holds the extension item description. */
     89    QString  m_strDescription;
     90    /** Holds the extension item version. */
     91    QString  m_strVersion;
     92    /** Holds the extension item revision. */
     93    ULONG    m_uRevision;
     94    /** Holds whether the extension item usable. */
     95    bool     m_fIsUsable;
     96    /** Holds why the extension item is unusable. */
     97    QString  m_strWhyUnusable;
    6098};
    6199
    62 /** Tree-widget column types. */
    63 enum
    64 {
    65     Column_Name,
    66     Column_ListVMs,
    67     Column_Max
    68 };
    69 
    70 
    71 /** Cloud Profile Manager provider's tree-widget item. */
    72 class UIItemCloudProvider : public QITreeWidgetItem, public UIDataCloudProvider
     100
     101/** Extension Pack Manager tree-widget item. */
     102class UIItemExtensionPack : public QITreeWidgetItem, public UIDataExtensionPack
    73103{
    74104    Q_OBJECT;
    75105
    76106public:
    77 
    78     /** Constructs item. */
    79     UIItemCloudProvider();
    80107
    81108    /** Updates item fields from base-class data. */
     
    85112    QString name() const { return m_strName; }
    86113
    87     /** Returns definition composed on the basis of @a strShortName. */
    88     static QString definition(const QString &strShortName);
     114protected:
     115
     116    /** Returns default text. */
     117    virtual QString defaultText() const /* override */;
    89118};
    90119
    91 /** Cloud Profile Manager profile's tree-widget item. */
    92 class UIItemCloudProfile : public QITreeWidgetItem, public UIDataCloudProfile
    93 {
    94     Q_OBJECT;
    95 
    96 public:
    97 
    98     /** Constructs item. */
    99     UIItemCloudProfile();
    100 
    101     /** Updates item fields from base-class data. */
    102     void updateFields();
    103 
    104     /** Returns item name. */
    105     QString name() const { return m_strName; }
    106 
    107     /** Returns definition composed on the basis of @a strProviderShortName and @a strName. */
    108     static QString definition(const QString &strProviderShortName, const QString &strName);
    109 };
    110 
    111120
    112121/*********************************************************************************************************************************
    113 *   Class UIItemCloudProvider implementation.                                                                                    *
     122*   Class UIItemExtensionPack implementation.                                                                                    *
    114123*********************************************************************************************************************************/
    115124
    116 UIItemCloudProvider::UIItemCloudProvider()
    117 {
    118     /* Assign icon: */
    119     setIcon(Column_Name, UIIconPool::iconSet(":/provider_oracle_16px.png"));
    120     /* Assign item type: */
    121     setData(Column_Name, Data_ItemType, QVariant::fromValue(CloudItemType_Provider));
    122 }
    123 
    124 void UIItemCloudProvider::updateFields()
    125 {
    126     /* Update item fields: */
    127     setText(Column_Name, m_strName);
    128     setData(Column_Name, Data_ProviderShortName, m_strShortName);
    129     setData(Column_Name, Data_Definition, QVariant::fromValue(definition(m_strShortName)));
    130     setCheckState(Column_ListVMs, m_fRestricted ? Qt::Unchecked : Qt::Checked);
    131 }
    132 
    133 /* static */
    134 QString UIItemCloudProvider::definition(const QString &strShortName)
    135 {
    136     return QString("/%1").arg(strShortName);
     125void UIItemExtensionPack::updateFields()
     126{
     127    /* Icon: */
     128    setIcon(ExtensionPackColumn_Usable, UIIconPool::iconSet(  m_fIsUsable
     129                                                      ? ":/status_check_16px.png"
     130                                                      : ":/status_error_16px.png"));
     131
     132    /* Name: */
     133    setText(ExtensionPackColumn_Name, m_strName);
     134
     135    /* Version, Revision, Edition: */
     136    const QString strVersion(m_strVersion.section(QRegExp("[-_]"), 0, 0));
     137    // WORKAROUND:
     138    // for http://qt.gitorious.org/qt/qt/commit/7fc63dd0ff368a637dcd17e692b9d6b26278b538
     139    QString strAppend;
     140    if (m_strVersion.contains(QRegExp("[-_]")))
     141        strAppend = m_strVersion.section(QRegExp("[-_]"), 1, -1, QString::SectionIncludeLeadingSep);
     142    setText(ExtensionPackColumn_Version, QString("%1r%2%3").arg(strVersion).arg(m_uRevision).arg(strAppend));
     143
     144    /* Tool-tip: */
     145    QString strTip = m_strDescription;
     146    if (!m_fIsUsable)
     147    {
     148        strTip += QString("<hr>");
     149        strTip += m_strWhyUnusable;
     150    }
     151    setToolTip(ExtensionPackColumn_Usable, strTip);
     152    setToolTip(ExtensionPackColumn_Name, strTip);
     153    setToolTip(ExtensionPackColumn_Version, strTip);
     154}
     155
     156QString UIItemExtensionPack::defaultText() const
     157{
     158    return   m_fIsUsable
     159           ? tr("%1, %2: %3, %4", "col.2 text, col.3 name: col.3 text, col.1 name")
     160               .arg(text(1))
     161               .arg(parentTree()->headerItem()->text(2)).arg(text(2))
     162               .arg(parentTree()->headerItem()->text(0))
     163           : tr("%1, %2: %3",     "col.2 text, col.3 name: col.3 text")
     164               .arg(text(1))
     165               .arg(parentTree()->headerItem()->text(2)).arg(text(2));
    137166}
    138167
    139168
    140169/*********************************************************************************************************************************
    141 *   Class UIItemCloudProfile implementation.                                                                                     *
     170*   Class UIExtensionPackManagerWidget implementation.                                                                           *
    142171*********************************************************************************************************************************/
    143172
    144 UIItemCloudProfile::UIItemCloudProfile()
    145 {
    146     /* Assign icon: */
    147     setIcon(Column_Name, UIIconPool::iconSet(":/profile_16px.png"));
    148     /* Assign item type: */
    149     setData(Column_Name, Data_ItemType, QVariant::fromValue(CloudItemType_Profile));
    150 }
    151 
    152 void UIItemCloudProfile::updateFields()
    153 {
    154     /* Update item fields: */
    155     setText(Column_Name, m_strName);
    156     setData(Column_Name, Data_Definition, QVariant::fromValue(definition(m_strProviderShortName, m_strName)));
    157     setCheckState(Column_ListVMs, m_fRestricted ? Qt::Unchecked : Qt::Checked);
    158 }
    159 
    160 /* static */
    161 QString UIItemCloudProfile::definition(const QString &strProviderShortName, const QString &strName)
    162 {
    163     return QString("/%1/%2").arg(strProviderShortName, strName);
    164 }
    165 
    166 
    167 /*********************************************************************************************************************************
    168 *   Class UICloudProfileManagerWidget implementation.                                                                            *
    169 *********************************************************************************************************************************/
    170 
    171 UICloudProfileManagerWidget::UICloudProfileManagerWidget(EmbedTo enmEmbedding, UIActionPool *pActionPool,
    172                                                          bool fShowToolbar /* = true */, QWidget *pParent /* = 0 */)
     173UIExtensionPackManagerWidget::UIExtensionPackManagerWidget(EmbedTo enmEmbedding, UIActionPool *pActionPool,
     174                                               bool fShowToolbar /* = true */, QWidget *pParent /* = 0 */)
    173175    : QIWithRetranslateUI<QWidget>(pParent)
    174176    , m_enmEmbedding(enmEmbedding)
     
    177179    , m_pToolBar(0)
    178180    , m_pTreeWidget(0)
    179     , m_pDetailsWidget(0)
    180181{
    181182    prepare();
    182183}
    183184
    184 QMenu *UICloudProfileManagerWidget::menu() const
    185 {
    186     return m_pActionPool->action(UIActionIndexMN_M_CloudWindow)->menu();
    187 }
    188 
    189 void UICloudProfileManagerWidget::retranslateUi()
     185QMenu *UIExtensionPackManagerWidget::menu() const
     186{
     187    return m_pActionPool->action(UIActionIndexMN_M_ExtensionWindow)->menu();
     188}
     189
     190void UIExtensionPackManagerWidget::retranslateUi()
    190191{
    191192    /* Adjust toolbar: */
     
    202203    /* Translate tree-widget: */
    203204    m_pTreeWidget->setHeaderLabels(   QStringList()
    204                                    << tr("Source")
    205                                    << tr("List VMs"));
    206 }
    207 
    208 bool UICloudProfileManagerWidget::makeSureChangesResolved()
    209 {
    210     /* Check if currently selected item is of profile type: */
     205                                   << tr("Active")
     206                                   << tr("Name")
     207                                   << tr("Version"));
     208}
     209
     210void UIExtensionPackManagerWidget::sltInstallExtensionPack()
     211{
     212    /* Show file-open dialog to let user to choose package file.
     213     * The default location is the user's Download or Downloads directory
     214     * with the user's home directory as a fallback. ExtPacks are downloaded. */
     215    QString strBaseFolder = QDir::homePath() + "/Downloads";
     216    if (!QDir(strBaseFolder).exists())
     217    {
     218        strBaseFolder = QDir::homePath() + "/Download";
     219        if (!QDir(strBaseFolder).exists())
     220            strBaseFolder = QDir::homePath();
     221    }
     222    const QString strTitle = tr("Select an extension package file");
     223    QStringList extensions;
     224    for (int i = 0; i < VBoxExtPackFileExts.size(); ++i)
     225        extensions << QString("*.%1").arg(VBoxExtPackFileExts[i]);
     226    const QString strFilter = tr("Extension package files (%1)").arg(extensions.join(" "));
     227    const QStringList fileNames = QIFileDialog::getOpenFileNames(strBaseFolder, strFilter, this, strTitle, 0, true, true);
     228    QString strFilePath;
     229    if (!fileNames.isEmpty())
     230        strFilePath = fileNames.at(0);
     231
     232    /* Install the chosen package: */
     233    if (!strFilePath.isEmpty())
     234    {
     235        QString strExtensionPackName;
     236        uiCommon().doExtPackInstallation(strFilePath, QString(), this, &strExtensionPackName);
     237
     238        /* Since we might be reinstalling an existing package, we have to
     239         * do a little refreshing regardless of what the user chose. */
     240        if (!strExtensionPackName.isNull())
     241        {
     242            /* Remove it from the tree: */
     243            for (int i = 0; i < m_pTreeWidget->topLevelItemCount(); ++i)
     244            {
     245                UIItemExtensionPack *pItem = qobject_cast<UIItemExtensionPack*>(m_pTreeWidget->childItem(i));
     246                if (!strExtensionPackName.compare(pItem->name(), Qt::CaseInsensitive))
     247                {
     248                    delete pItem;
     249                    break;
     250                }
     251            }
     252
     253            /* [Re]insert it into the tree: */
     254            CExtPackManager comManager = uiCommon().virtualBox().GetExtensionPackManager();
     255            const CExtPack &comExtensionPack = comManager.Find(strExtensionPackName);
     256            if (comExtensionPack.isOk())
     257            {
     258                /* Load extension pack data: */
     259                UIDataExtensionPack extensionPackData;
     260                loadExtensionPack(comExtensionPack, extensionPackData);
     261                createItemForExtensionPack(extensionPackData, true /* choose item? */);
     262            }
     263        }
     264    }
     265}
     266
     267void UIExtensionPackManagerWidget::sltUninstallExtensionPack()
     268{
     269    /* Get current item: */
    211270    QITreeWidgetItem *pItem = QITreeWidgetItem::toItem(m_pTreeWidget->currentItem());
    212     UIItemCloudProfile *pProfileItem = qobject_cast<UIItemCloudProfile*>(pItem);
    213     if (!pProfileItem)
    214         return true;
    215 
    216     /* Get item data: */
    217     UIDataCloudProfile oldData = *pProfileItem;
    218     UIDataCloudProfile newData = m_pDetailsWidget->data();
    219 
    220     /* Check if data has changed: */
    221     if (newData == oldData)
    222         return true;
    223 
    224     /* Ask whether user wants to Accept/Reset changes or still not sure: */
    225     const int iResult = msgCenter().confirmCloudProfileManagerClosing(window());
    226     switch (iResult)
    227     {
    228         case AlertButton_Choice1:
     271    UIItemExtensionPack *pItemEP = qobject_cast<UIItemExtensionPack*>(pItem);
     272
     273    /* Uninstall chosen package: */
     274    if (pItemEP)
     275    {
     276        /* Get name of current package: */
     277        const QString strSelectedPackageName = pItemEP->name();
     278        /* Ask user about package removing: */
     279        if (msgCenter().confirmRemoveExtensionPack(strSelectedPackageName, this))
    229280        {
    230             sltApplyCloudProfileDetailsChanges();
    231             return true;
    232         }
    233         case AlertButton_Choice2:
    234         {
    235             sltResetCloudProfileDetailsChanges();
    236             return true;
    237         }
    238         default:
    239             break;
    240     }
    241 
    242     /* False by default: */
    243     return false;
    244 }
    245 
    246 void UICloudProfileManagerWidget::sltResetCloudProfileDetailsChanges()
    247 {
    248     /* Just push the current-item data there again: */
    249     sltHandleCurrentItemChange();
    250 }
    251 
    252 void UICloudProfileManagerWidget::sltApplyCloudProfileDetailsChanges()
    253 {
    254     /* It can be that this is provider item, not profile item currently selected.
    255      * In such case we are not applying parameters, we are creating new one profile. */
    256     QITreeWidgetItem *pItem = QITreeWidgetItem::toItem(m_pTreeWidget->currentItem());
    257     UIItemCloudProvider *pMaybeProviderItem = qobject_cast<UIItemCloudProvider*>(pItem);
    258     if (pMaybeProviderItem)
    259         return sltAddCloudProfile();
    260 
    261     /* Get profile item: */
    262     UIItemCloudProfile *pProfileItem = qobject_cast<UIItemCloudProfile*>(pItem);
    263     AssertPtrReturnVoid(pProfileItem);
    264     /* Get provider item: */
    265     UIItemCloudProvider *pProviderItem = qobject_cast<UIItemCloudProvider*>(pProfileItem->parentItem());
    266     AssertPtrReturnVoid(pProviderItem);
    267 
    268     /* Acquire provider short name: */
    269     const QString strShortName = pProviderItem->data(Column_Name, Data_ProviderShortName).toString();
    270 
    271     /* Look for corresponding provider: */
    272     CCloudProvider comCloudProvider = cloudProviderByShortName(strShortName, this);
    273     if (comCloudProvider.isNotNull())
    274     {
    275         /* Get old/new data: */
    276         UIDataCloudProfile oldData = *pProfileItem;
    277         UIDataCloudProfile newData = m_pDetailsWidget->data();
    278 
    279         /* Look for corresponding profile: */
    280         CCloudProfile comCloudProfile = cloudProfileByName(strShortName, oldData.m_strName, this);
    281         if (comCloudProfile.isNotNull())
    282         {
    283             /* Set profile name, if necessary: */
    284             if (newData.m_strName != oldData.m_strName)
    285                 comCloudProfile.SetName(newData.m_strName);
     281            /* Get VirtualBox for further activities: */
     282            const CVirtualBox comVBox = uiCommon().virtualBox();
     283            /* Get Extension Pack Manager for further activities: */
     284            CExtPackManager comEPManager = comVBox.GetExtensionPackManager();
     285
    286286            /* Show error message if necessary: */
    287             if (!comCloudProfile.isOk())
    288                 msgCenter().cannotAssignCloudProfileParameter(comCloudProfile, this);
     287            if (!comVBox.isOk())
     288                msgCenter().cannotAcquireExtensionPackManager(comVBox);
    289289            else
    290290            {
    291                 /* Iterate through old/new data: */
    292                 foreach (const QString &strKey, oldData.m_data.keys())
     291                /* Uninstall the package: */
     292                /** @todo Refuse this if any VMs are running. */
     293                QString displayInfo;
     294#ifdef VBOX_WS_WIN
     295                QTextStream stream(&displayInfo);
     296                stream.setNumberFlags(QTextStream::ShowBase);
     297                stream.setIntegerBase(16);
     298                stream << "hwnd=" << winId();
     299#endif
     300
     301                /* Uninstall extension pack finally: */
     302                CProgress comProgress = comEPManager.Uninstall(strSelectedPackageName, false /* forced removal? */, displayInfo);
     303
     304                /* Show error message if necessary: */
     305                if (!comEPManager.isOk() || comProgress.isNull())
     306                    msgCenter().cannotUninstallExtPack(comEPManager, strSelectedPackageName, this);
     307                else
    293308                {
    294                     /* Get values: */
    295                     const QString strOldValue = oldData.m_data.value(strKey).first;
    296                     const QString strNewValue = newData.m_data.value(strKey).first;
    297                     if (strNewValue != strOldValue)
     309                    /* Show uninstallation progress: */
     310                    msgCenter().showModalProgressDialog(comProgress, tr("Extensions"), ":/progress_install_guest_additions_90px.png", this);
     311
     312                    /* Show error message if necessary: */
     313                    if (!comProgress.isOk() || comProgress.GetResultCode() != 0)
     314                        msgCenter().cannotUninstallExtPack(comProgress, strSelectedPackageName, this);
     315                    else
    298316                    {
    299                         /* Apply property: */
    300                         comCloudProfile.SetProperty(strKey, strNewValue);
    301                         /* Show error message if necessary: */
    302                         if (!comCloudProfile.isOk())
    303                         {
    304                             msgCenter().cannotAssignCloudProfileParameter(comCloudProfile, this);
    305                             break;
    306                         }
     317                        /* Remove package from tree: */
     318                        delete pItem;
     319
     320                        /* Adjust tree-widget: */
     321                        sltAdjustTreeWidget();
    307322                    }
    308323                }
    309324            }
    310 
    311             /* If profile is Ok finally: */
    312             if (comCloudProfile.isOk())
    313             {
    314                 /* Save profile changes: */
    315                 comCloudProvider.SaveProfiles();
    316                 /* Show error message if necessary: */
    317                 if (!comCloudProvider.isOk())
    318                     msgCenter().cannotSaveCloudProfiles(comCloudProvider, this);
    319             }
    320325        }
    321326    }
    322327}
    323328
    324 void UICloudProfileManagerWidget::sltAddCloudProfile()
    325 {
    326     /* Get provider item: */
    327     QITreeWidgetItem *pItem = QITreeWidgetItem::toItem(m_pTreeWidget->currentItem());
    328     UIItemCloudProvider *pProviderItem = qobject_cast<UIItemCloudProvider*>(pItem);
    329     AssertPtrReturnVoid(pProviderItem);
    330 
    331     /* Acquire profile name if not proposed by details widget: */
    332     QString strProfileName = m_pDetailsWidget->data().m_strName;
    333     if (strProfileName.isEmpty())
    334     {
    335         bool fCancelled = true;
    336         QISafePointerInputDialog pDialog = new QIInputDialog(this);
    337         if (pDialog)
    338         {
    339             pDialog->setWindowIcon(UIIconPool::iconSet(":/cloud_profile_add_16px.png"));
    340             pDialog->setWindowTitle(UICloudProfileManager::tr("Add Profile"));
    341             if (pDialog->exec() == QDialog::Accepted)
    342             {
    343                 strProfileName = pDialog->textValue();
    344                 fCancelled = false;
    345             }
    346             delete pDialog;
    347         }
    348         if (fCancelled)
    349             return;
    350     }
    351 
    352     /* Acquire provider short name: */
    353     const QString strShortName = pProviderItem->data(Column_Name, Data_ProviderShortName).toString();
    354 
    355     /* Look for corresponding provider: */
    356     CCloudProvider comCloudProvider = cloudProviderByShortName(strShortName, this);
    357     if (comCloudProvider.isNotNull())
    358     {
    359         /* Create new profile: */
    360         const QVector<QString> keys = pProviderItem->m_propertyDescriptions.keys().toVector();
    361         const QVector<QString> values(keys.size());
    362         comCloudProvider.CreateProfile(strProfileName, keys, values);
    363         /* Show error message if necessary: */
    364         if (!comCloudProvider.isOk())
    365             msgCenter().cannotCreateCloudProfile(comCloudProvider, this);
    366         else
    367         {
    368             /* Save profile changes: */
    369             comCloudProvider.SaveProfiles();
    370             /* Show error message if necessary: */
    371             if (!comCloudProvider.isOk())
    372                 msgCenter().cannotSaveCloudProfiles(comCloudProvider, this);
    373         }
    374     }
    375 }
    376 
    377 void UICloudProfileManagerWidget::sltImportCloudProfiles()
    378 {
    379     /* Get provider item: */
    380     QITreeWidgetItem *pItem = QITreeWidgetItem::toItem(m_pTreeWidget->currentItem());
    381     UIItemCloudProvider *pProviderItem = qobject_cast<UIItemCloudProvider*>(pItem);
    382     AssertPtrReturnVoid(pProviderItem);
    383 
    384     /* If there are profiles exist => confirm cloud profile import. */
    385     if (   pProviderItem->childCount() != 0
    386         && !msgCenter().confirmCloudProfilesImport(this))
    387         return;
    388 
    389     /* Acquire provider short name: */
    390     const QString strShortName = pProviderItem->data(Column_Name, Data_ProviderShortName).toString();
    391 
    392     /* Look for corresponding provider: */
    393     CCloudProvider comCloudProvider = cloudProviderByShortName(strShortName, this);
    394     if (comCloudProvider.isNotNull())
    395     {
    396         /* Import profiles: */
    397         comCloudProvider.ImportProfiles();
    398         /* Show error message if necessary: */
    399         if (!comCloudProvider.isOk())
    400             msgCenter().cannotImportCloudProfiles(comCloudProvider, this);
    401     }
    402 }
    403 
    404 void UICloudProfileManagerWidget::sltRemoveCloudProfile()
    405 {
    406     /* Get profile item: */
    407     QITreeWidgetItem *pItem = QITreeWidgetItem::toItem(m_pTreeWidget->currentItem());
    408     UIItemCloudProfile *pProfileItem = qobject_cast<UIItemCloudProfile*>(pItem);
    409     AssertPtrReturnVoid(pProfileItem);
    410     /* Get provider item: */
    411     UIItemCloudProvider *pProviderItem = qobject_cast<UIItemCloudProvider*>(pProfileItem->parentItem());
    412     AssertPtrReturnVoid(pProviderItem);
    413 
    414     /* Acquire profile name: */
    415     const QString strProfileName = pProfileItem->name();
    416 
    417     /* Confirm cloud profile removal: */
    418     if (!msgCenter().confirmCloudProfileRemoval(strProfileName, this))
    419         return;
    420 
    421     /* Acquire provider short name: */
    422     const QString strShortName = pProviderItem->data(Column_Name, Data_ProviderShortName).toString();
    423 
    424     /* Look for corresponding provider: */
    425     CCloudProvider comCloudProvider = cloudProviderByShortName(strShortName, this);
    426     if (comCloudProvider.isNotNull())
    427     {
    428         /* Look for corresponding profile: */
    429         CCloudProfile comCloudProfile = cloudProfileByName(strShortName, strProfileName, this);
    430         if (comCloudProfile.isNotNull())
    431         {
    432             /* Remove current profile: */
    433             comCloudProfile.Remove();
    434             /* Show error message if necessary: */
    435             if (!comCloudProfile.isOk())
    436                 msgCenter().cannotRemoveCloudProfile(comCloudProfile, this);
    437             else
    438             {
    439                 /* Save profile changes: */
    440                 comCloudProvider.SaveProfiles();
    441                 /* Show error message if necessary: */
    442                 if (!comCloudProvider.isOk())
    443                     msgCenter().cannotSaveCloudProfiles(comCloudProvider, this);
    444             }
    445         }
    446     }
    447 }
    448 
    449 void UICloudProfileManagerWidget::sltToggleCloudProfileDetailsVisibility(bool fVisible)
    450 {
    451     /* Save the setting: */
    452     gEDataManager->setCloudProfileManagerDetailsExpanded(fVisible);
    453     /* Show/hide details area and Apply button: */
    454     m_pDetailsWidget->setVisible(fVisible);
    455     /* Notify external lsiteners: */
    456     emit sigCloudProfileDetailsVisibilityChanged(fVisible);
    457 }
    458 
    459 void UICloudProfileManagerWidget::sltShowCloudProfileTryPage()
    460 {
    461     uiCommon().openURL("https://myservices.us.oraclecloud.com/mycloud/signup");
    462 }
    463 
    464 void UICloudProfileManagerWidget::sltShowCloudProfileHelp()
    465 {
    466     uiCommon().openURL("https://docs.cloud.oracle.com/iaas/Content/API/Concepts/sdkconfig.htm");
    467 }
    468 
    469 void UICloudProfileManagerWidget::sltPerformTableAdjustment()
    470 {
    471     AssertPtrReturnVoid(m_pTreeWidget);
    472     AssertPtrReturnVoid(m_pTreeWidget->header());
    473     AssertPtrReturnVoid(m_pTreeWidget->viewport());
    474     m_pTreeWidget->header()->resizeSection(0, m_pTreeWidget->viewport()->width() - m_pTreeWidget->header()->sectionSize(1));
    475 }
    476 
    477 void UICloudProfileManagerWidget::sltHandleCurrentItemChange()
     329void UIExtensionPackManagerWidget::sltAdjustTreeWidget()
     330{
     331    /* Get the tree-widget abstract interface: */
     332    QAbstractItemView *pItemView = m_pTreeWidget;
     333    /* Get the tree-widget header-view: */
     334    QHeaderView *pItemHeader = m_pTreeWidget->header();
     335
     336    /* Calculate the total tree-widget width: */
     337    const int iTotal = m_pTreeWidget->viewport()->width();
     338    /* Look for a minimum width hints for non-important columns: */
     339    const int iMinWidth1 = qMax(pItemView->sizeHintForColumn(ExtensionPackColumn_Usable),
     340                                pItemHeader->sectionSizeHint(ExtensionPackColumn_Usable));
     341    const int iMinWidth2 = qMax(pItemView->sizeHintForColumn(ExtensionPackColumn_Version),
     342                                pItemHeader->sectionSizeHint(ExtensionPackColumn_Version));
     343    /* Propose suitable width hints for non-important columns: */
     344    const int iWidth1 = iMinWidth1 < iTotal / ExtensionPackColumn_Max ? iMinWidth1 : iTotal / ExtensionPackColumn_Max;
     345    const int iWidth2 = iMinWidth2 < iTotal / ExtensionPackColumn_Max ? iMinWidth2 : iTotal / ExtensionPackColumn_Max;
     346    /* Apply the proposal: */
     347    m_pTreeWidget->setColumnWidth(ExtensionPackColumn_Usable, iWidth1);
     348    m_pTreeWidget->setColumnWidth(ExtensionPackColumn_Version, iWidth2);
     349    m_pTreeWidget->setColumnWidth(ExtensionPackColumn_Name, iTotal - iWidth1 - iWidth2);
     350}
     351
     352void UIExtensionPackManagerWidget::sltHandleCurrentItemChange()
    478353{
    479354    /* Check current-item type: */
    480355    QITreeWidgetItem *pItem = QITreeWidgetItem::toItem(m_pTreeWidget->currentItem());
    481     UIItemCloudProvider *pItemProvider = qobject_cast<UIItemCloudProvider*>(pItem);
    482     UIItemCloudProfile *pItemProfile = qobject_cast<UIItemCloudProfile*>(pItem);
    483356
    484357    /* Update actions availability: */
    485     m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Add)->setEnabled(pItemProvider);
    486     m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Import)->setEnabled(pItemProvider);
    487     m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Remove)->setEnabled(pItemProfile);
    488     m_pActionPool->action(UIActionIndexMN_M_Cloud_T_Details)->setEnabled(pItemProvider || pItemProfile);
    489 
    490     /* If there is an item => update details data: */
    491     if (pItemProfile)
    492         m_pDetailsWidget->setData(*pItemProfile);
    493     /* Otherwise => clear details data: */
    494     else
    495         m_pDetailsWidget->setData(UIDataCloudProfile());
    496 
    497     /* Update details area visibility: */
    498     sltToggleCloudProfileDetailsVisibility(pItem && m_pActionPool->action(UIActionIndexMN_M_Cloud_T_Details)->isChecked());
    499 }
    500 
    501 void UICloudProfileManagerWidget::sltHandleContextMenuRequest(const QPoint &position)
     358    m_pActionPool->action(UIActionIndexMN_M_Extension_S_Uninstall)->setEnabled(pItem);
     359}
     360
     361void UIExtensionPackManagerWidget::sltHandleContextMenuRequest(const QPoint &position)
    502362{
    503363    /* Check clicked-item type: */
    504364    QITreeWidgetItem *pItem = QITreeWidgetItem::toItem(m_pTreeWidget->itemAt(position));
    505     UIItemCloudProvider *pItemProvider = qobject_cast<UIItemCloudProvider*>(pItem);
    506     UIItemCloudProfile *pItemProfile = qobject_cast<UIItemCloudProfile*>(pItem);
    507365
    508366    /* Compose temporary context-menu: */
    509367    QMenu menu;
    510     if (pItemProfile)
    511     {
    512         menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Remove));
    513         menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_T_Details));
    514     }
    515     else if (pItemProvider)
    516     {
    517         menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Add));
    518         menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Import));
    519         menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_T_Details));
    520     }
     368    if (pItem)
     369        menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Extension_S_Uninstall));
     370    else
     371        menu.addAction(m_pActionPool->action(UIActionIndexMN_M_Extension_S_Install));
    521372
    522373    /* And show it: */
     
    524375}
    525376
    526 void UICloudProfileManagerWidget::sltHandleItemChange(QTreeWidgetItem *pItem)
    527 {
    528     /* Check item type: */
    529     QITreeWidgetItem *pChangedItem = QITreeWidgetItem::toItem(pItem);
    530     UIItemCloudProvider *pProviderItem = qobject_cast<UIItemCloudProvider*>(pChangedItem);
    531     UIItemCloudProfile *pProfileItem = qobject_cast<UIItemCloudProfile*>(pChangedItem);
    532 
    533     /* Check whether item is of provider or profile type, then check whether it changed: */
    534     bool fChanged = false;
    535     if (pProviderItem)
    536     {
    537         const UIDataCloudProvider oldData = *pProviderItem;
    538         if (   (oldData.m_fRestricted && pProviderItem->checkState(Column_ListVMs) == Qt::Checked)
    539             || (!oldData.m_fRestricted && pProviderItem->checkState(Column_ListVMs) == Qt::Unchecked))
    540             fChanged = true;
    541     }
    542     else if (pProfileItem)
    543     {
    544         const UIDataCloudProfile oldData = *pProfileItem;
    545         if (   (oldData.m_fRestricted && pProfileItem->checkState(Column_ListVMs) == Qt::Checked)
    546             || (!oldData.m_fRestricted && pProfileItem->checkState(Column_ListVMs) == Qt::Unchecked))
    547             fChanged = true;
    548     }
    549 
    550     /* Gather Cloud Profile Manager restrictions and save them to extra-data: */
    551     if (fChanged)
    552         gEDataManager->setCloudProfileManagerRestrictions(gatherCloudProfileManagerRestrictions(m_pTreeWidget->invisibleRootItem()));
    553 }
    554 
    555 void UICloudProfileManagerWidget::prepare()
    556 {
    557     /* Prepare actions: */
     377void UIExtensionPackManagerWidget::prepare()
     378{
     379    /* Prepare self: */
     380    uiCommon().setHelpKeyword(this, "extensionsdetails"); /// @todo use proper help tag
     381
     382    /* Prepare stuff: */
    558383    prepareActions();
    559     /* Prepare widgets: */
    560384    prepareWidgets();
    561 
    562     /* Load settings: */
    563     loadSettings();
    564385
    565386    /* Apply language settings: */
    566387    retranslateUi();
    567388
    568     /* Load cloud stuff: */
    569     loadCloudStuff();
    570 
    571     /* Set help keyowrd for context sensitive help: */
    572     uiCommon().setHelpKeyword(this, "ovf-cloud-profile-manager");
    573 
    574 }
    575 
    576 void UICloudProfileManagerWidget::prepareActions()
     389    /* Load extension packs: */
     390    loadExtensionPacks();
     391}
     392
     393void UIExtensionPackManagerWidget::prepareActions()
    577394{
    578395    /* First of all, add actions which has smaller shortcut scope: */
    579     addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Add));
    580     addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Import));
    581     addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Remove));
    582     addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_T_Details));
    583     addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_TryPage));
    584     addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Help));
    585 }
    586 
    587 void UICloudProfileManagerWidget::prepareWidgets()
     396    addAction(m_pActionPool->action(UIActionIndexMN_M_Extension_S_Install));
     397    addAction(m_pActionPool->action(UIActionIndexMN_M_Extension_S_Uninstall));
     398
     399    /* Connect actions: */
     400    connect(m_pActionPool->action(UIActionIndexMN_M_Extension_S_Install), &QAction::triggered,
     401            this, &UIExtensionPackManagerWidget::sltInstallExtensionPack);
     402    connect(m_pActionPool->action(UIActionIndexMN_M_Extension_S_Uninstall), &QAction::triggered,
     403            this, &UIExtensionPackManagerWidget::sltUninstallExtensionPack);
     404}
     405
     406void UIExtensionPackManagerWidget::prepareWidgets()
    588407{
    589408    /* Create main-layout: */
     
    602421        if (m_fShowToolbar)
    603422            prepareToolBar();
     423
    604424        /* Prepare tree-widget: */
    605425        prepareTreeWidget();
    606         /* Prepare details-widget: */
    607         prepareDetailsWidget();
    608         /* Prepare connections: */
    609         prepareConnections();
    610     }
    611 }
    612 
    613 void UICloudProfileManagerWidget::prepareToolBar()
    614 {
    615     /* Create toolbar: */
     426    }
     427}
     428
     429void UIExtensionPackManagerWidget::prepareToolBar()
     430{
     431    /* Prepare toolbar: */
    616432    m_pToolBar = new QIToolBar(parentWidget());
    617433    if (m_pToolBar)
    618434    {
    619         /* Configure toolbar: */
    620435        const int iIconMetric = (int)(QApplication::style()->pixelMetric(QStyle::PM_LargeIconSize));
    621436        m_pToolBar->setIconSize(QSize(iIconMetric, iIconMetric));
    622437        m_pToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
    623 
    624         /* Add toolbar actions: */
    625         m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Add));
    626         m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Import));
    627         m_pToolBar->addSeparator();
    628         m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Remove));
    629         m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_T_Details));
    630         m_pToolBar->addSeparator();
    631         m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_TryPage));
    632         m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Help));
     438        m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Extension_S_Install));
     439        m_pToolBar->addAction(m_pActionPool->action(UIActionIndexMN_M_Extension_S_Uninstall));
    633440
    634441#ifdef VBOX_WS_MAC
     
    646453}
    647454
    648 void UICloudProfileManagerWidget::prepareTreeWidget()
    649 {
    650     /* Create tree-widget: */
    651     m_pTreeWidget = new QITreeWidget;
     455void UIExtensionPackManagerWidget::prepareTreeWidget()
     456{
     457    /* Prepare tree-widget: */
     458    m_pTreeWidget = new QITreeWidget(this);
    652459    if (m_pTreeWidget)
    653460    {
    654         /* Configure tree-widget: */
    655         m_pTreeWidget->header()->setStretchLastSection(false);
    656461        m_pTreeWidget->setRootIsDecorated(false);
    657462        m_pTreeWidget->setAlternatingRowColors(true);
    658463        m_pTreeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
    659464        m_pTreeWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    660         m_pTreeWidget->setColumnCount(Column_Max);
     465        m_pTreeWidget->setColumnCount(ExtensionPackColumn_Max);
    661466        m_pTreeWidget->setSortingEnabled(true);
    662         m_pTreeWidget->sortByColumn(Column_Name, Qt::AscendingOrder);
     467        m_pTreeWidget->sortByColumn(ExtensionPackColumn_Name, Qt::AscendingOrder);
    663468        m_pTreeWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
     469        connect(m_pTreeWidget, &QITreeWidget::resized,
     470                this, &UIExtensionPackManagerWidget::sltAdjustTreeWidget, Qt::QueuedConnection);
     471        connect(m_pTreeWidget->header(), &QHeaderView::sectionResized,
     472                this, &UIExtensionPackManagerWidget::sltAdjustTreeWidget, Qt::QueuedConnection);
     473        connect(m_pTreeWidget, &QITreeWidget::currentItemChanged,
     474                this, &UIExtensionPackManagerWidget::sltHandleCurrentItemChange);
     475        connect(m_pTreeWidget, &QITreeWidget::customContextMenuRequested,
     476                this, &UIExtensionPackManagerWidget::sltHandleContextMenuRequest);
    664477
    665478        /* Add into layout: */
     
    668481}
    669482
    670 void UICloudProfileManagerWidget::prepareDetailsWidget()
    671 {
    672     /* Create details-widget: */
    673     m_pDetailsWidget = new UICloudProfileDetailsWidget(m_enmEmbedding);
    674     if (m_pDetailsWidget)
    675     {
    676         /* Configure details-widget: */
    677         m_pDetailsWidget->setVisible(false);
    678         m_pDetailsWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
    679 
    680         /* Add into layout: */
    681         layout()->addWidget(m_pDetailsWidget);
    682     }
    683 }
    684 
    685 void UICloudProfileManagerWidget::prepareConnections()
    686 {
    687     /* Action connections: */
    688     connect(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Add), &QAction::triggered,
    689             this, &UICloudProfileManagerWidget::sltAddCloudProfile);
    690     connect(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Import), &QAction::triggered,
    691             this, &UICloudProfileManagerWidget::sltImportCloudProfiles);
    692     connect(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Remove), &QAction::triggered,
    693             this, &UICloudProfileManagerWidget::sltRemoveCloudProfile);
    694     connect(m_pActionPool->action(UIActionIndexMN_M_Cloud_T_Details), &QAction::toggled,
    695             this, &UICloudProfileManagerWidget::sltToggleCloudProfileDetailsVisibility);
    696     connect(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_TryPage), &QAction::triggered,
    697             this, &UICloudProfileManagerWidget::sltShowCloudProfileTryPage);
    698     connect(m_pActionPool->action(UIActionIndexMN_M_Cloud_S_Help), &QAction::triggered,
    699             this, &UICloudProfileManagerWidget::sltShowCloudProfileHelp);
    700 
    701     /* Tree-widget connections: */
    702     connect(m_pTreeWidget, &QITreeWidget::resized,
    703             this, &UICloudProfileManagerWidget::sltPerformTableAdjustment, Qt::QueuedConnection);
    704     connect(m_pTreeWidget->header(), &QHeaderView::sectionResized,
    705             this, &UICloudProfileManagerWidget::sltPerformTableAdjustment, Qt::QueuedConnection);
    706     connect(m_pTreeWidget, &QITreeWidget::currentItemChanged,
    707             this, &UICloudProfileManagerWidget::sltHandleCurrentItemChange);
    708     connect(m_pTreeWidget, &QITreeWidget::customContextMenuRequested,
    709             this, &UICloudProfileManagerWidget::sltHandleContextMenuRequest);
    710     connect(m_pTreeWidget, &QITreeWidget::itemDoubleClicked,
    711             m_pActionPool->action(UIActionIndexMN_M_Cloud_T_Details), &QAction::setChecked);
    712     connect(m_pTreeWidget, &QITreeWidget::itemChanged,
    713             this, &UICloudProfileManagerWidget::sltHandleItemChange);
    714 
    715     /* Details-widget connections: */
    716     connect(m_pDetailsWidget, &UICloudProfileDetailsWidget::sigDataChanged,
    717             this, &UICloudProfileManagerWidget::sigCloudProfileDetailsDataChanged);
    718     connect(m_pDetailsWidget, &UICloudProfileDetailsWidget::sigDataChangeRejected,
    719             this, &UICloudProfileManagerWidget::sltResetCloudProfileDetailsChanges);
    720     connect(m_pDetailsWidget, &UICloudProfileDetailsWidget::sigDataChangeAccepted,
    721             this, &UICloudProfileManagerWidget::sltApplyCloudProfileDetailsChanges);
    722 
    723     /* Extra-data connections: */
    724     connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigCloudProviderListChanged,
    725             this, &UICloudProfileManagerWidget::sltLoadCloudStuff);
    726     connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigCloudProfileRegistered,
    727             this, &UICloudProfileManagerWidget::sltLoadCloudStuff);
    728     connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigCloudProfileChanged,
    729             this, &UICloudProfileManagerWidget::sltLoadCloudStuff);
    730     connect(gEDataManager, &UIExtraDataManager::sigCloudProfileManagerRestrictionChange,
    731             this, &UICloudProfileManagerWidget::sltLoadCloudStuff);
    732 }
    733 
    734 void UICloudProfileManagerWidget::loadSettings()
    735 {
    736     /* Details action/widget: */
    737     m_pActionPool->action(UIActionIndexMN_M_Cloud_T_Details)->setChecked(gEDataManager->cloudProfileManagerDetailsExpanded());
    738     sltToggleCloudProfileDetailsVisibility(m_pActionPool->action(UIActionIndexMN_M_Cloud_T_Details)->isChecked());
    739 }
    740 
    741 void UICloudProfileManagerWidget::loadCloudStuff()
    742 {
    743     /* Save current item definition: */
    744     QITreeWidgetItem *pCurrentItem = QITreeWidgetItem::toItem(m_pTreeWidget->currentItem());
    745     const QString strDefinition = pCurrentItem ? pCurrentItem->data(Column_Name, Data_Definition).toString() : QString();
     483void UIExtensionPackManagerWidget::loadExtensionPacks()
     484{
     485    /* Check tree-widget: */
     486    if (!m_pTreeWidget)
     487        return;
    746488
    747489    /* Clear tree first of all: */
    748490    m_pTreeWidget->clear();
    749491
    750     /* Acquire cloud profile manager restrictions: */
    751     const QStringList restrictions = gEDataManager->cloudProfileManagerRestrictions();
    752 
    753     /* Iterate through existing providers: */
    754     foreach (const CCloudProvider &comCloudProvider, listCloudProviders())
    755     {
    756         /* Skip if we have nothing to populate: */
    757         if (comCloudProvider.isNull())
    758             continue;
    759 
    760         /* Load provider data: */
    761         UIDataCloudProvider providerData;
    762         loadCloudProvider(comCloudProvider, restrictions, providerData);
    763         createItemForCloudProvider(providerData);
    764 
    765         /* Make sure provider item is properly inserted: */
    766         QTreeWidgetItem *pItem = searchItem(UIItemCloudProvider::definition(providerData.m_strShortName));
    767         AssertPtrReturnVoid(pItem);
    768 
    769         /* Iterate through provider's profiles: */
    770         foreach (const CCloudProfile &comCloudProfile, listCloudProfiles(comCloudProvider))
     492    /* Get VirtualBox for further activities: */
     493    const CVirtualBox comVBox = uiCommon().virtualBox();
     494    /* Get Extension Pack Manager for further activities: */
     495    const CExtPackManager comEPManager = comVBox.GetExtensionPackManager();
     496
     497    /* Show error message if necessary: */
     498    if (!comVBox.isOk())
     499        msgCenter().cannotAcquireExtensionPackManager(comVBox);
     500    else
     501    {
     502        /* Get extension packs for further activities: */
     503        const QVector<CExtPack> extensionPacks = comEPManager.GetInstalledExtPacks();
     504
     505        /* Show error message if necessary: */
     506        if (!comEPManager.isOk())
     507            msgCenter().cannotAcquireExtensionPacks(comEPManager);
     508        else
    771509        {
    772             /* Skip if we have nothing to populate: */
    773             if (comCloudProfile.isNull())
    774                 continue;
    775 
    776             /* Load profile data: */
    777             UIDataCloudProfile profileData;
    778             loadCloudProfile(comCloudProfile, restrictions, providerData, profileData);
    779             createItemForCloudProfile(pItem, profileData);
     510            /* Iterate through existing extension packs: */
     511            foreach (const CExtPack &comExtensionPack, extensionPacks)
     512            {
     513                /* Skip if we have nothing to populate: */
     514                if (comExtensionPack.isNull())
     515                    continue;
     516
     517                /* Load extension pack data: */
     518                UIDataExtensionPack extensionPackData;
     519                loadExtensionPack(comExtensionPack, extensionPackData);
     520                createItemForExtensionPack(extensionPackData, false /* choose item? */);
     521            }
     522
     523            /* Choose the 1st item as current if nothing chosen: */
     524            if (!m_pTreeWidget->currentItem())
     525                m_pTreeWidget->setCurrentItem(m_pTreeWidget->topLevelItem(0));
     526            /* Handle current item change in any case: */
     527            sltHandleCurrentItemChange();
    780528        }
    781 
    782         /* Expand provider item finally: */
    783         pItem->setExpanded(true);
    784     }
    785 
    786     /* Try to restore current item by definition: */
    787     if (!strDefinition.isEmpty())
    788         m_pTreeWidget->setCurrentItem(searchItem(strDefinition));
    789     /* Choose the 1st item as current if nothing chosen: */
    790     if (!m_pTreeWidget->currentItem())
    791         m_pTreeWidget->setCurrentItem(m_pTreeWidget->topLevelItem(0));
    792     /* Handle current item change in any case: */
    793     sltHandleCurrentItemChange();
    794 }
    795 
    796 void UICloudProfileManagerWidget::loadCloudProvider(const CCloudProvider &comProvider,
    797                                                     const QStringList &restrictions,
    798                                                     UIDataCloudProvider &providerData)
    799 {
    800     /* Gather provider settings: */
    801     if (comProvider.isOk())
    802         cloudProviderId(comProvider, providerData.m_uId, this);
    803     if (comProvider.isOk())
    804         cloudProviderShortName(comProvider, providerData.m_strShortName);
    805     if (comProvider.isOk())
    806         cloudProviderName(comProvider, providerData.m_strName);
    807     providerData.m_fRestricted = restrictions.contains(UIItemCloudProvider::definition(providerData.m_strShortName));
    808     foreach (const QString &strSupportedPropertyName, comProvider.GetSupportedPropertyNames())
    809         providerData.m_propertyDescriptions[strSupportedPropertyName] = comProvider.GetPropertyDescription(strSupportedPropertyName);
    810 }
    811 
    812 void UICloudProfileManagerWidget::loadCloudProfile(const CCloudProfile &comProfile,
    813                                                    const QStringList &restrictions,
    814                                                    const UIDataCloudProvider &providerData,
    815                                                    UIDataCloudProfile &profileData)
    816 {
    817     /* Gather provider settings: */
    818     profileData.m_strProviderShortName = providerData.m_strShortName;
    819 
    820     /* Gather profile settings: */
    821     if (comProfile.isOk())
    822         cloudProfileName(comProfile, profileData.m_strName);
    823     profileData.m_fRestricted = restrictions.contains(UIItemCloudProfile::definition(providerData.m_strShortName, profileData.m_strName));
    824     if (comProfile.isOk())
    825     {
    826         QVector<QString> keys;
    827         QVector<QString> values;
    828         if (cloudProfileProperties(comProfile, keys, values))
    829             for (int i = 0; i < keys.size(); ++i)
    830                 profileData.m_data[keys.at(i)] = qMakePair(values.at(i), providerData.m_propertyDescriptions.value(keys.at(i)));
    831     }
    832 }
    833 
    834 QTreeWidgetItem *UICloudProfileManagerWidget::searchItem(const QString &strDefinition,
    835                                                          QTreeWidgetItem *pParentItem /* = 0 */) const
    836 {
    837     /* If no parent-item passed => we will start from the invisible-root-item: */
    838     if (!pParentItem)
    839         pParentItem = m_pTreeWidget->invisibleRootItem();
    840 
    841     /* Check whether parent-item is of required type: */
    842     QITreeWidgetItem *pParentItemOfType = QITreeWidgetItem::toItem(pParentItem);
    843     if (pParentItemOfType)
    844     {
    845         /* Check if parent-item has required definition: */
    846         if (pParentItemOfType->data(Column_Name, Data_Definition).toString() == strDefinition)
    847             return pParentItem;
    848     }
    849 
    850     /* Iterate through parent-item children: */
    851     for (int i = 0; i < pParentItem->childCount(); ++i)
    852         if (QTreeWidgetItem *pChildItem = searchItem(strDefinition, pParentItem->child(i)))
    853             return pChildItem;
    854 
    855     /* Null by default: */
    856     return 0;
    857 }
    858 
    859 void UICloudProfileManagerWidget::createItemForCloudProvider(const UIDataCloudProvider &providerData)
    860 {
    861     /* Create new provider item: */
    862     UIItemCloudProvider *pItem = new UIItemCloudProvider;
     529    }
     530}
     531
     532void UIExtensionPackManagerWidget::loadExtensionPack(const CExtPack &comExtensionPack, UIDataExtensionPack &extensionPackData)
     533{
     534    /* Gather extension pack settings: */
     535    if (comExtensionPack.isOk())
     536        extensionPackData.m_strName = comExtensionPack.GetName();
     537    if (comExtensionPack.isOk())
     538        extensionPackData.m_strDescription = comExtensionPack.GetDescription();
     539    if (comExtensionPack.isOk())
     540        extensionPackData.m_strVersion = comExtensionPack.GetVersion();
     541    if (comExtensionPack.isOk())
     542        extensionPackData.m_uRevision = comExtensionPack.GetRevision();
     543    if (comExtensionPack.isOk())
     544    {
     545        extensionPackData.m_fIsUsable = comExtensionPack.GetUsable();
     546        if (!extensionPackData.m_fIsUsable && comExtensionPack.isOk())
     547            extensionPackData.m_strWhyUnusable = comExtensionPack.GetWhyUnusable();
     548    }
     549
     550    /* Show error message if necessary: */
     551    if (!comExtensionPack.isOk())
     552        msgCenter().cannotAcquireExtensionPackParameter(comExtensionPack, this);
     553}
     554
     555void UIExtensionPackManagerWidget::createItemForExtensionPack(const UIDataExtensionPack &extensionPackData, bool fChooseItem)
     556{
     557    /* Prepare new provider item: */
     558    UIItemExtensionPack *pItem = new UIItemExtensionPack;
    863559    if (pItem)
    864560    {
    865         /* Configure item: */
    866         pItem->UIDataCloudProvider::operator=(providerData);
     561        pItem->UIDataExtensionPack::operator=(extensionPackData);
    867562        pItem->updateFields();
     563
    868564        /* Add item to the tree: */
    869565        m_pTreeWidget->addTopLevelItem(pItem);
    870     }
    871 }
    872 
    873 void UICloudProfileManagerWidget::createItemForCloudProfile(QTreeWidgetItem *pParent,
    874                                                             const UIDataCloudProfile &profileData)
    875 {
    876     /* Create new profile item: */
    877     UIItemCloudProfile *pItem = new UIItemCloudProfile;
    878     if (pItem)
    879     {
    880         /* Configure item: */
    881         pItem->UIDataCloudProfile::operator=(profileData);
    882         pItem->updateFields();
    883         /* Add item to the parent: */
    884         pParent->addChild(pItem);
    885     }
    886 }
    887 
    888 QStringList UICloudProfileManagerWidget::gatherCloudProfileManagerRestrictions(QTreeWidgetItem *pParentItem)
    889 {
    890     /* Prepare result: */
    891     QStringList result;
    892     AssertPtrReturn(pParentItem, result);
    893 
    894     /* Process unchecked QITreeWidgetItem(s) only: */
    895     QITreeWidgetItem *pChangedItem = QITreeWidgetItem::toItem(pParentItem);
    896     if (   pChangedItem
    897         && pChangedItem->checkState(Column_ListVMs) == Qt::Unchecked)
    898         result << pChangedItem->data(Column_Name, Data_Definition).toString();
    899 
    900     /* Iterate through children recursively: */
    901     for (int i = 0; i < pParentItem->childCount(); ++i)
    902         result << gatherCloudProfileManagerRestrictions(pParentItem->child(i));
    903 
    904     /* Return result: */
    905     return result;
     566
     567        /* And choose it as current if necessary: */
     568        if (fChooseItem)
     569            m_pTreeWidget->setCurrentItem(pItem);
     570    }
    906571}
    907572
    908573
    909574/*********************************************************************************************************************************
    910 *   Class UICloudProfileManagerFactory implementation.                                                                           *
     575*   Class UIExtensionPackManagerFactory implementation.                                                                          *
    911576*********************************************************************************************************************************/
    912577
    913 UICloudProfileManagerFactory::UICloudProfileManagerFactory(UIActionPool *pActionPool /* = 0 */)
     578UIExtensionPackManagerFactory::UIExtensionPackManagerFactory(UIActionPool *pActionPool /* = 0 */)
    914579    : m_pActionPool(pActionPool)
    915580{
    916581}
    917582
    918 void UICloudProfileManagerFactory::create(QIManagerDialog *&pDialog, QWidget *pCenterWidget)
    919 {
    920     pDialog = new UICloudProfileManager(pCenterWidget, m_pActionPool);
     583void UIExtensionPackManagerFactory::create(QIManagerDialog *&pDialog, QWidget *pCenterWidget)
     584{
     585    pDialog = new UIExtensionPackManager(pCenterWidget, m_pActionPool);
    921586}
    922587
    923588
    924589/*********************************************************************************************************************************
    925 *   Class UICloudProfileManager implementation.                                                                                  *
     590*   Class UIExtensionPackManager implementation.                                                                                 *
    926591*********************************************************************************************************************************/
    927592
    928 UICloudProfileManager::UICloudProfileManager(QWidget *pCenterWidget, UIActionPool *pActionPool)
     593UIExtensionPackManager::UIExtensionPackManager(QWidget *pCenterWidget, UIActionPool *pActionPool)
    929594    : QIWithRetranslateUI<QIManagerDialog>(pCenterWidget)
    930595    , m_pActionPool(pActionPool)
     
    932597}
    933598
    934 void UICloudProfileManager::sltHandleButtonBoxClick(QAbstractButton *pButton)
    935 {
    936     /* Disable buttons first of all: */
    937     button(ButtonType_Reset)->setEnabled(false);
    938     button(ButtonType_Apply)->setEnabled(false);
    939 
    940     /* Compare with known buttons: */
    941     if (pButton == button(ButtonType_Reset))
    942         emit sigDataChangeRejected();
    943     else
    944     if (pButton == button(ButtonType_Apply))
    945         emit sigDataChangeAccepted();
    946 }
    947 
    948 void UICloudProfileManager::retranslateUi()
     599void UIExtensionPackManager::retranslateUi()
    949600{
    950601    /* Translate window title: */
    951     setWindowTitle(tr("Cloud Profile Manager"));
     602    setWindowTitle(tr("Extension Pack Manager"));
    952603
    953604    /* Translate buttons: */
    954     button(ButtonType_Reset)->setText(tr("Reset"));
    955     button(ButtonType_Apply)->setText(tr("Apply"));
    956605    button(ButtonType_Close)->setText(tr("Close"));
    957606    button(ButtonType_Help)->setText(tr("Help"));
    958     button(ButtonType_Reset)->setStatusTip(tr("Reset changes in current cloud profile details"));
    959     button(ButtonType_Apply)->setStatusTip(tr("Apply changes in current cloud profile details"));
    960     button(ButtonType_Close)->setStatusTip(tr("Close dialog without saving"));
     607    button(ButtonType_Close)->setStatusTip(tr("Close dialog"));
    961608    button(ButtonType_Help)->setStatusTip(tr("Show dialog help"));
    962     button(ButtonType_Reset)->setShortcut(QString("Ctrl+Backspace"));
    963     button(ButtonType_Apply)->setShortcut(QString("Ctrl+Return"));
    964609    button(ButtonType_Close)->setShortcut(Qt::Key_Escape);
    965610    button(ButtonType_Help)->setShortcut(QKeySequence::HelpContents);
    966     button(ButtonType_Reset)->setToolTip(tr("Reset Changes (%1)").arg(button(ButtonType_Reset)->shortcut().toString()));
    967     button(ButtonType_Apply)->setToolTip(tr("Apply Changes (%1)").arg(button(ButtonType_Apply)->shortcut().toString()));
    968611    button(ButtonType_Close)->setToolTip(tr("Close Window (%1)").arg(button(ButtonType_Close)->shortcut().toString()));
    969     button(ButtonType_Help)->setToolTip(tr("Close Window (%1)").arg(button(ButtonType_Help)->shortcut().toString()));
    970 }
    971 
    972 void UICloudProfileManager::configure()
     612    button(ButtonType_Help)->setToolTip(tr("Show Help (%1)").arg(button(ButtonType_Help)->shortcut().toString()));
     613}
     614
     615void UIExtensionPackManager::configure()
    973616{
    974617    /* Apply window icons: */
    975     setWindowIcon(UIIconPool::iconSetFull(":/cloud_profile_manager_32px.png", ":/cloud_profile_manager_16px.png"));
    976 }
    977 
    978 void UICloudProfileManager::configureCentralWidget()
    979 {
    980     /* Create widget: */
    981     UICloudProfileManagerWidget *pWidget = new UICloudProfileManagerWidget(EmbedTo_Dialog, m_pActionPool, true, this);
     618    setWindowIcon(UIIconPool::iconSetFull(":/extension_pack_manager_32px.png", ":/extension_pack_manager_16px.png"));
     619}
     620
     621void UIExtensionPackManager::configureCentralWidget()
     622{
     623    /* Prepare widget: */
     624    UIExtensionPackManagerWidget *pWidget = new UIExtensionPackManagerWidget(EmbedTo_Dialog, m_pActionPool, true, this);
    982625    if (pWidget)
    983626    {
    984         /* Configure widget: */
    985627        setWidget(pWidget);
    986628        setWidgetMenu(pWidget->menu());
     
    988630        setWidgetToolbar(pWidget->toolbar());
    989631#endif
    990         connect(this, &UICloudProfileManager::sigDataChangeRejected,
    991                 pWidget, &UICloudProfileManagerWidget::sltResetCloudProfileDetailsChanges);
    992         connect(this, &UICloudProfileManager::sigDataChangeAccepted,
    993                 pWidget, &UICloudProfileManagerWidget::sltApplyCloudProfileDetailsChanges);
    994632
    995633        /* Add into layout: */
     
    998636}
    999637
    1000 void UICloudProfileManager::configureButtonBox()
    1001 {
    1002     /* Configure button-box: */
    1003     connect(widget(), &UICloudProfileManagerWidget::sigCloudProfileDetailsVisibilityChanged,
    1004             button(ButtonType_Apply), &QPushButton::setVisible);
    1005     connect(widget(), &UICloudProfileManagerWidget::sigCloudProfileDetailsVisibilityChanged,
    1006             button(ButtonType_Reset), &QPushButton::setVisible);
    1007     connect(widget(), &UICloudProfileManagerWidget::sigCloudProfileDetailsDataChanged,
    1008             button(ButtonType_Apply), &QPushButton::setEnabled);
    1009     connect(widget(), &UICloudProfileManagerWidget::sigCloudProfileDetailsDataChanged,
    1010             button(ButtonType_Reset), &QPushButton::setEnabled);
    1011     connect(buttonBox(), &QIDialogButtonBox::clicked,
    1012             this, &UICloudProfileManager::sltHandleButtonBoxClick);
    1013     // WORKAROUND:
    1014     // Since we connected signals later than extra-data loaded
    1015     // for signals above, we should handle that stuff here again:
    1016     button(ButtonType_Apply)->setVisible(gEDataManager->cloudProfileManagerDetailsExpanded());
    1017     button(ButtonType_Reset)->setVisible(gEDataManager->cloudProfileManagerDetailsExpanded());
    1018 }
    1019 
    1020 void UICloudProfileManager::finalize()
     638void UIExtensionPackManager::finalize()
    1021639{
    1022640    /* Apply language settings: */
     
    1024642}
    1025643
    1026 UICloudProfileManagerWidget *UICloudProfileManager::widget()
    1027 {
    1028     return qobject_cast<UICloudProfileManagerWidget*>(QIManagerDialog::widget());
    1029 }
    1030 
    1031 void UICloudProfileManager::closeEvent(QCloseEvent *pEvent)
    1032 {
    1033     /* Make sure all changes resolved: */
    1034     if (widget()->makeSureChangesResolved())
    1035     {
    1036         /* Call to base class: */
    1037         QIWithRetranslateUI<QIManagerDialog>::closeEvent(pEvent);
    1038     }
    1039     else
    1040     {
    1041         /* Just ignore the event otherwise: */
    1042         pEvent->ignore();
    1043     }
    1044 }
    1045 
    1046 
    1047 #include "UICloudProfileManager.moc"
     644UIExtensionPackManagerWidget *UIExtensionPackManager::widget()
     645{
     646    return qobject_cast<UIExtensionPackManagerWidget*>(QIManagerDialog::widget());
     647}
     648
     649
     650#include "UIExtensionPackManager.moc"
  • trunk/src/VBox/Frontends/VirtualBox/src/extensionpackmanager/UIExtensionPackManager.h

    r87311 r87354  
    11/* $Id$ */
    22/** @file
    3  * VBox Qt GUI - UICloudProfileManager class declaration.
     3 * VBox Qt GUI - UIExtensionPackManager class declaration.
    44 */
    55
    66/*
    7  * Copyright (C) 2009-2020 Oracle Corporation
     7 * Copyright (C) 2009-2021 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1616 */
    1717
    18 #ifndef FEQT_INCLUDED_SRC_cloud_profilemanager_UICloudProfileManager_h
    19 #define FEQT_INCLUDED_SRC_cloud_profilemanager_UICloudProfileManager_h
     18#ifndef FEQT_INCLUDED_SRC_extensionpackmanager_UIExtensionPackManager_h
     19#define FEQT_INCLUDED_SRC_extensionpackmanager_UIExtensionPackManager_h
    2020#ifndef RT_WITHOUT_PRAGMA_ONCE
    2121# pragma once
     
    2727
    2828/* Forward declarations: */
    29 class QAbstractButton;
    30 class QTreeWidgetItem;
     29class QIToolBar;
    3130class QITreeWidget;
    3231class UIActionPool;
    33 class UICloudProfileDetailsWidget;
    34 class UIItemCloudProfile;
    35 class UIItemCloudProvider;
    36 class QIToolBar;
    37 struct UIDataCloudProfile;
    38 struct UIDataCloudProvider;
    39 class CCloudProfile;
    40 class CCloudProvider;
    41 
    42 
    43 /** QWidget extension providing GUI with the pane to control cloud profile related functionality. */
    44 class UICloudProfileManagerWidget : public QIWithRetranslateUI<QWidget>
     32struct UIDataExtensionPack;
     33class CExtPack;
     34
     35
     36/** QWidget extension providing GUI with the pane to control extension pack related functionality. */
     37class UIExtensionPackManagerWidget : public QIWithRetranslateUI<QWidget>
    4538{
    4639    Q_OBJECT;
    4740
    48 signals:
    49 
    50     /** Notifies listeners about cloud profile details-widget @a fVisible. */
    51     void sigCloudProfileDetailsVisibilityChanged(bool fVisible);
    52     /** Notifies listeners about cloud profile details data @a fDiffers. */
    53     void sigCloudProfileDetailsDataChanged(bool fDiffers);
    54 
    5541public:
    5642
    57     /** Constructs Cloud Profile Manager widget.
     43    /** Constructs Extension Pack Manager widget.
    5844      * @param  enmEmbedding  Brings the type of widget embedding.
    5945      * @param  pActionPool   Brings the action-pool reference.
    6046      * @param  fShowToolbar  Brings whether we should create/show toolbar. */
    61     UICloudProfileManagerWidget(EmbedTo enmEmbedding, UIActionPool *pActionPool,
    62                                 bool fShowToolbar = true, QWidget *pParent = 0);
     47    UIExtensionPackManagerWidget(EmbedTo enmEmbedding, UIActionPool *pActionPool,
     48                                 bool fShowToolbar = true, QWidget *pParent = 0);
    6349
    6450    /** Returns the menu. */
     
    7056#endif
    7157
    72     /** Check for changes committed.
    73       * @returns Whether changes were resolved (accepted or discarded) or still a problem otherwise. */
    74     bool makeSureChangesResolved();
    75 
    7658protected:
    7759
     
    8264    /** @} */
    8365
    84 public slots:
    85 
    86     /** @name Details-widget stuff.
    87       * @{ */
    88         /** Handles command to reset cloud profile details changes. */
    89         void sltResetCloudProfileDetailsChanges();
    90         /** Handles command to apply cloud profile details changes. */
    91         void sltApplyCloudProfileDetailsChanges();
    92     /** @} */
    93 
    9466private slots:
    9567
    9668    /** @name Menu/action stuff.
    9769      * @{ */
    98         /** Handles command to add cloud profile. */
    99         void sltAddCloudProfile();
    100         /** Handles command to import cloud profiles. */
    101         void sltImportCloudProfiles();
    102         /** Handles command to remove cloud profile. */
    103         void sltRemoveCloudProfile();
    104         /** Handles command to make cloud profile details @a fVisible. */
    105         void sltToggleCloudProfileDetailsVisibility(bool fVisible);
    106         /** Handles command to show cloud profile try page. */
    107         void sltShowCloudProfileTryPage();
    108         /** Handles command to show cloud profile help. */
    109         void sltShowCloudProfileHelp();
     70        /** Handles command to install extension pack. */
     71        void sltInstallExtensionPack();
     72        /** Handles command to uninstall extension pack. */
     73        void sltUninstallExtensionPack();
    11074    /** @} */
    11175
    11276    /** @name Tree-widget stuff.
    11377      * @{ */
    114         /** Handles request to load cloud stuff. */
    115         void sltLoadCloudStuff() { loadCloudStuff(); }
    116         /** Adjusts tree-widget according content. */
    117         void sltPerformTableAdjustment();
     78        /** Handles command to adjust tree-widget. */
     79        void sltAdjustTreeWidget();
     80
    11881        /** Handles tree-widget current item change. */
    11982        void sltHandleCurrentItemChange();
    12083        /** Handles context-menu request for tree-widget @a position. */
    12184        void sltHandleContextMenuRequest(const QPoint &position);
    122         /** Handles tree-widget @a pItem change. */
    123         void sltHandleItemChange(QTreeWidgetItem *pItem);
    12485    /** @} */
    12586
     
    13899        /** Prepares tree-widget. */
    139100        void prepareTreeWidget();
    140         /** Prepares details-widget. */
    141         void prepareDetailsWidget();
    142         /** Prepares connections. */
    143         void prepareConnections();
    144         /** Load settings: */
    145         void loadSettings();
    146101    /** @} */
    147102
    148103    /** @name Loading stuff.
    149104      * @{ */
    150         /** Loads cloud stuff. */
    151         void loadCloudStuff();
    152         /** Loads cloud @a comProvider data to passed @a providerData container,
    153           * using @a restrictions as hint. */
    154         void loadCloudProvider(const CCloudProvider &comProvider,
    155                                const QStringList &restrictions,
    156                                UIDataCloudProvider &providerData);
    157         /** Loads cloud @a comProfile data to passed @a profileData container,
    158           * using @a restrictions & @a providerData as hint. */
    159         void loadCloudProfile(const CCloudProfile &comProfile,
    160                               const QStringList &restrictions,
    161                               const UIDataCloudProvider &providerData,
    162                               UIDataCloudProfile &profileData);
     105        /** Loads extension pack stuff. */
     106        void loadExtensionPacks();
     107        /** Loads extention @a comPackage data to passed @a extensionPackData container. */
     108        void loadExtensionPack(const CExtPack &comPackage, UIDataExtensionPack &extensionPackData);
    163109    /** @} */
    164110
    165111    /** @name Tree-widget stuff.
    166112      * @{ */
    167         /** Recursively searches for an item with specified @a strDefinition,
    168           * using @a pParentItem as an item to start search from. */
    169         QTreeWidgetItem *searchItem(const QString &strDefinition,
    170                                     QTreeWidgetItem *pParentItem = 0) const;
    171 
    172113        /** Creates a new tree-widget item
    173           * on the basis of passed @a providerData. */
    174         void createItemForCloudProvider(const UIDataCloudProvider &providerData);
    175         /** Creates a new tree-widget item as a child of certain @a pParent,
    176           * on the basis of passed @a profileData. */
    177         void createItemForCloudProfile(QTreeWidgetItem *pParent, const UIDataCloudProfile &profileData);
    178 
    179         /* Gathers a list of Cloud Profile Manager restrictions starting from @a pParentItem. */
    180         QStringList gatherCloudProfileManagerRestrictions(QTreeWidgetItem *pParentItem);
     114          * on the basis of passed @a extensionPackData, @a fChooseItem if requested. */
     115        void createItemForExtensionPack(const UIDataExtensionPack &extensionPackData, bool fChooseItem);
    181116    /** @} */
    182117
     
    197132    /** @} */
    198133
    199     /** @name Splitter variables.
     134    /** @name Widget variables.
    200135      * @{ */
    201136        /** Holds the tree-widget instance. */
    202         QITreeWidget                *m_pTreeWidget;
    203         /** Holds the details-widget instance. */
    204         UICloudProfileDetailsWidget *m_pDetailsWidget;
     137        QITreeWidget *m_pTreeWidget;
    205138    /** @} */
    206139};
    207140
    208141
    209 /** QIManagerDialogFactory extension used as a factory for Cloud Profile Manager dialog. */
    210 class UICloudProfileManagerFactory : public QIManagerDialogFactory
     142/** QIManagerDialogFactory extension used as a factory for Extension Pack Manager dialog. */
     143class UIExtensionPackManagerFactory : public QIManagerDialogFactory
    211144{
    212145public:
    213146
    214     /** Constructs Cloud Profile Manager factory acquiring additional arguments.
     147    /** Constructs Extension Pack Manager factory acquiring additional arguments.
    215148      * @param  pActionPool  Brings the action-pool reference. */
    216     UICloudProfileManagerFactory(UIActionPool *pActionPool = 0);
     149    UIExtensionPackManagerFactory(UIActionPool *pActionPool = 0);
    217150
    218151protected:
     
    227160
    228161
    229 /** QIManagerDialog extension providing GUI with the dialog to control cloud profile related functionality. */
    230 class UICloudProfileManager : public QIWithRetranslateUI<QIManagerDialog>
     162/** QIManagerDialog extension providing GUI with the dialog to control extension pack related functionality. */
     163class UIExtensionPackManager : public QIWithRetranslateUI<QIManagerDialog>
    231164{
    232165    Q_OBJECT;
    233166
    234 signals:
    235 
    236     /** Notifies listeners about data change rejected and should be reseted. */
    237     void sigDataChangeRejected();
    238     /** Notifies listeners about data change accepted and should be applied. */
    239     void sigDataChangeAccepted();
    240 
    241 private slots:
    242 
    243     /** @name Button-box stuff.
    244       * @{ */
    245         /** Handles button-box button click. */
    246         void sltHandleButtonBoxClick(QAbstractButton *pButton);
    247     /** @} */
    248 
    249167private:
    250168
    251     /** Constructs Cloud Profile Manager dialog.
     169    /** Constructs Extension Pack Manager dialog.
    252170      * @param  pCenterWidget  Brings the widget reference to center according to.
    253171      * @param  pActionPool    Brings the action-pool reference. */
    254     UICloudProfileManager(QWidget *pCenterWidget, UIActionPool *pActionPool);
     172    UIExtensionPackManager(QWidget *pCenterWidget, UIActionPool *pActionPool);
    255173
    256174    /** @name Event-handling stuff.
     
    266184        /** Configures central-widget. */
    267185        virtual void configureCentralWidget() /* override */;
    268         /** Configures button-box. */
    269         virtual void configureButtonBox() /* override */;
    270186        /** Perform final preparations. */
    271187        virtual void finalize() /* override */;
     
    275191      * @{ */
    276192        /** Returns the widget. */
    277         virtual UICloudProfileManagerWidget *widget() /* override */;
    278     /** @} */
    279 
    280     /** @name Event-handling stuff.
    281       * @{ */
    282         /** Handles close @a pEvent. */
    283         virtual void closeEvent(QCloseEvent *pEvent) /* override */;
     193        virtual UIExtensionPackManagerWidget *widget() /* override */;
    284194    /** @} */
    285195
     
    291201
    292202    /** Allow factory access to private/protected members: */
    293     friend class UICloudProfileManagerFactory;
     203    friend class UIExtensionPackManagerFactory;
    294204};
    295205
    296 #endif /* !FEQT_INCLUDED_SRC_cloud_profilemanager_UICloudProfileManager_h */
     206#endif /* !FEQT_INCLUDED_SRC_extensionpackmanager_UIExtensionPackManager_h */
  • trunk/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.cpp

    r86958 r87354  
    266266            {
    267267                case UIToolType_Welcome:
     268                case UIToolType_Extensions:
    268269                case UIToolType_Media:
    269270                case UIToolType_Network:
  • trunk/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.h

    r87316 r87354  
    893893    /* Global types: */
    894894    UIToolType_Welcome,
     895    UIToolType_Extensions,
    895896    UIToolType_Media,
    896897    UIToolType_Network,
  • trunk/src/VBox/Frontends/VirtualBox/src/globals/UIActionPoolManager.cpp

    r87342 r87354  
    5959        setName(QApplication::translate("UIActionPool", "&File", "Non Mac OS X version"));
    6060#endif /* !VBOX_WS_MAC */
     61    }
     62};
     63
     64/** Simple action extension, used as 'Show Extension Pack Manager' action class. */
     65class UIActionSimpleManagerFileShowExtensionPackManager : public UIActionSimple
     66{
     67    Q_OBJECT;
     68
     69public:
     70
     71    /** Constructs action passing @a pParent to the base-class. */
     72    UIActionSimpleManagerFileShowExtensionPackManager(UIActionPool *pParent)
     73        : UIActionSimple(pParent, ":/extension_pack_manager_16px.png", ":/extension_pack_manager_disabled_16px.png")
     74    {}
     75
     76protected:
     77
     78    /** Returns shortcut extra-data ID. */
     79    virtual QString shortcutExtraDataID() const /* override */
     80    {
     81        return QString("ExtensionPackManager");
     82    }
     83
     84    /** Handles translation event. */
     85    virtual void retranslateUi() /* override */
     86    {
     87        setName(QApplication::translate("UIActionPool", "&Extension Pack Manager..."));
     88        setStatusTip(QApplication::translate("UIActionPool", "Display the Extension Pack Manager window"));
    6189    }
    6290};
     
    17831811};
    17841812
     1813/** Simple action extension, used as 'Show Extension Pack Manager' action class. */
     1814class UIActionSimpleManagerToolsGlobalShowExtensionPackManager : public UIActionSimple
     1815{
     1816    Q_OBJECT;
     1817
     1818public:
     1819
     1820    /** Constructs action passing @a pParent to the base-class. */
     1821    UIActionSimpleManagerToolsGlobalShowExtensionPackManager(UIActionPool *pParent)
     1822        : UIActionSimple(pParent,
     1823                         ":/extension_pack_manager_24px.png", ":/extension_pack_manager_16px.png",
     1824                         ":/extension_pack_manager_disabled_24px.png", ":/extension_pack_manager_disabled_16px.png")
     1825    {}
     1826
     1827protected:
     1828
     1829    /** Returns shortcut extra-data ID. */
     1830    virtual QString shortcutExtraDataID() const /* override */
     1831    {
     1832        return QString("ToolsGlobalExtensionPackManager");
     1833    }
     1834
     1835    /** Handles translation event. */
     1836    virtual void retranslateUi() /* override */
     1837    {
     1838        setName(QApplication::translate("UIActionPool", "&Extension Pack Manager"));
     1839        setStatusTip(QApplication::translate("UIActionPool", "Open the Extension Pack Manager"));
     1840    }
     1841};
     1842
    17851843/** Simple action extension, used as 'Show Virtual Media Manager' action class. */
    17861844class UIActionSimpleManagerToolsGlobalShowVirtualMediaManager : public UIActionSimple
     
    21332191        setStatusTip(QApplication::translate("UIActionPool", "Clone selected virtual machine"));
    21342192        setToolTip(  QApplication::translate("UIActionPool", "Clone Virtual Machine")
     2193                   + (shortcut().isEmpty() ? QString() : QString(" (%1)").arg(shortcut().toString())));
     2194    }
     2195};
     2196
     2197
     2198/** Menu action extension, used as 'Extension' menu class. */
     2199class UIActionMenuManagerExtension : public UIActionMenu
     2200{
     2201    Q_OBJECT;
     2202
     2203public:
     2204
     2205    /** Constructs action passing @a pParent to the base-class. */
     2206    UIActionMenuManagerExtension(UIActionPool *pParent)
     2207        : UIActionMenu(pParent)
     2208    {}
     2209
     2210protected:
     2211
     2212    /** Returns shortcut extra-data ID. */
     2213    virtual QString shortcutExtraDataID() const /* override */
     2214    {
     2215        return QString("ExtensionMenu");
     2216    }
     2217
     2218    /** Handles translation event. */
     2219    virtual void retranslateUi() /* override */
     2220    {
     2221        setName(QApplication::translate("UIActionPool", "&Extension"));
     2222    }
     2223};
     2224
     2225/** Simple action extension, used as 'Perform Install' action class. */
     2226class UIActionSimpleManagerExtensionPerformInstall : public UIActionSimple
     2227{
     2228    Q_OBJECT;
     2229
     2230public:
     2231
     2232    /** Constructs action passing @a pParent to the base-class. */
     2233    UIActionSimpleManagerExtensionPerformInstall(UIActionPool *pParent)
     2234        : UIActionSimple(pParent,
     2235//                         ":/extension_pack_install_32px.png",          ":/extension_pack_install_16px.png",
     2236//                         ":/extension_pack_install_disabled_32px.png", ":/extension_pack_install_disabled_16px.png"
     2237                         ":/extension_pack_32px.png", ":/extension_pack_16px.png",
     2238                         ":/extension_pack_disabled_32px.png", ":/extension_pack_disabled_16px.png")
     2239    {
     2240        setShortcutContext(Qt::WidgetWithChildrenShortcut);
     2241    }
     2242
     2243protected:
     2244
     2245    /** Returns shortcut extra-data ID. */
     2246    virtual QString shortcutExtraDataID() const /* override */
     2247    {
     2248        return QString("InstallExtension");
     2249    }
     2250
     2251    /** Returns default shortcut. */
     2252    virtual QKeySequence defaultShortcut(UIActionPoolType) const /* override */
     2253    {
     2254        return QKeySequence("Ctrl+Shift+I");
     2255    }
     2256
     2257    /** Handles translation event. */
     2258    virtual void retranslateUi() /* override */
     2259    {
     2260        setName(QApplication::translate("UIActionPool", "&Install..."));
     2261        setShortcutScope(QApplication::translate("UIActionPool", "Extension Pack Manager"));
     2262        setStatusTip(QApplication::translate("UIActionPool", "Install extension pack"));
     2263        setToolTip(  QApplication::translate("UIActionPool", "Install Extension Pack")
     2264                   + (shortcut().isEmpty() ? QString() : QString(" (%1)").arg(shortcut().toString())));
     2265    }
     2266};
     2267
     2268/** Simple action extension, used as 'Perform Uninstall' action class. */
     2269class UIActionSimpleManagerExtensionPerformUninstall : public UIActionSimple
     2270{
     2271    Q_OBJECT;
     2272
     2273public:
     2274
     2275    /** Constructs action passing @a pParent to the base-class. */
     2276    UIActionSimpleManagerExtensionPerformUninstall(UIActionPool *pParent)
     2277        : UIActionSimple(pParent,
     2278//                         ":/extension_pack_uninstall_32px.png",          ":/extension_pack_uninstall_16px.png",
     2279//                         ":/extension_pack_uninstall_disabled_32px.png", ":/extension_pack_uninstall_disabled_16px.png"
     2280                         ":/extension_pack_32px.png", ":/extension_pack_16px.png",
     2281                         ":/extension_pack_disabled_32px.png", ":/extension_pack_disabled_16px.png")
     2282    {
     2283        setShortcutContext(Qt::WidgetWithChildrenShortcut);
     2284    }
     2285
     2286protected:
     2287
     2288    /** Returns shortcut extra-data ID. */
     2289    virtual QString shortcutExtraDataID() const /* override */
     2290    {
     2291        return QString("UninstallExtension");
     2292    }
     2293
     2294    /** Returns default shortcut. */
     2295    virtual QKeySequence defaultShortcut(UIActionPoolType) const /* override */
     2296    {
     2297        return QKeySequence("Ctrl+Shift+U");
     2298    }
     2299
     2300    /** Handles translation event. */
     2301    virtual void retranslateUi() /* override */
     2302    {
     2303        setName(QApplication::translate("UIActionPool", "&Uninstall..."));
     2304        setShortcutScope(QApplication::translate("UIActionPool", "Extension Pack Manager"));
     2305        setStatusTip(QApplication::translate("UIActionPool", "Uninstall selected extension pack"));
     2306        setToolTip(  QApplication::translate("UIActionPool", "Uninstall Extension Pack")
    21352307                   + (shortcut().isEmpty() ? QString() : QString(" (%1)").arg(shortcut().toString())));
    21362308    }
     
    33833555    /* 'File' actions: */
    33843556    m_pool[UIActionIndexMN_M_File] = new UIActionMenuManagerFile(this);
     3557    m_pool[UIActionIndexMN_M_File_S_ShowExtensionPackManager] = new UIActionSimpleManagerFileShowExtensionPackManager(this);
    33853558    m_pool[UIActionIndexMN_M_File_S_ShowVirtualMediumManager] = new UIActionSimpleManagerFileShowVirtualMediaManager(this);
    33863559    m_pool[UIActionIndexMN_M_File_S_ShowHostNetworkManager] = new UIActionSimpleManagerFileShowHostNetworkManager(this);
     
    34813654    /* Global Tools actions: */
    34823655    m_pool[UIActionIndexMN_M_Tools_M_Global] = new UIActionMenuManagerToolsGlobal(this);
     3656    m_pool[UIActionIndexMN_M_Tools_M_Global_S_ExtensionPackManager] = new UIActionSimpleManagerToolsGlobalShowExtensionPackManager(this);
    34833657    m_pool[UIActionIndexMN_M_Tools_M_Global_S_VirtualMediaManager] = new UIActionSimpleManagerToolsGlobalShowVirtualMediaManager(this);
    34843658    m_pool[UIActionIndexMN_M_Tools_M_Global_S_HostNetworkManager] = new UIActionSimpleManagerToolsGlobalShowHostNetworkManager(this);
     
    34933667    m_pool[UIActionIndexMN_M_Snapshot_T_Properties] = new UIActionMenuManagerSnapshotToggleProperties(this);
    34943668    m_pool[UIActionIndexMN_M_Snapshot_S_Clone] = new UIActionMenuManagerSnapshotPerformClone(this);
     3669
     3670    /* Extension Pack Manager actions: */
     3671    m_pool[UIActionIndexMN_M_ExtensionWindow] = new UIActionMenuManagerExtension(this);
     3672    m_pool[UIActionIndexMN_M_Extension] = new UIActionMenuManagerExtension(this);
     3673    m_pool[UIActionIndexMN_M_Extension_S_Install] = new UIActionSimpleManagerExtensionPerformInstall(this);
     3674    m_pool[UIActionIndexMN_M_Extension_S_Uninstall] = new UIActionSimpleManagerExtensionPerformUninstall(this);
    34953675
    34963676    /* Virtual Medium Manager actions: */
     
    35683748    m_menuUpdateHandlers[UIActionIndexMN_M_Group_M_Tools].ptfm =         &UIActionPoolManager::updateMenuGroupTools;
    35693749    m_menuUpdateHandlers[UIActionIndexMN_M_Machine_M_Tools].ptfm =       &UIActionPoolManager::updateMenuMachineTools;
     3750    m_menuUpdateHandlers[UIActionIndexMN_M_ExtensionWindow].ptfm =       &UIActionPoolManager::updateMenuExtensionWindow;
     3751    m_menuUpdateHandlers[UIActionIndexMN_M_Extension].ptfm =             &UIActionPoolManager::updateMenuExtension;
    35703752    m_menuUpdateHandlers[UIActionIndexMN_M_MediumWindow].ptfm =          &UIActionPoolManager::updateMenuMediumWindow;
    35713753    m_menuUpdateHandlers[UIActionIndexMN_M_Medium].ptfm =                &UIActionPoolManager::updateMenuMedium;
     
    36413823    updateMenuMachineTools();
    36423824
     3825    /* 'Extension Pack Manager' menu: */
     3826    addMenu(m_mainMenus, action(UIActionIndexMN_M_Extension));
     3827    updateMenuExtensionWindow();
     3828    updateMenuExtension();
    36433829    /* 'Virtual Media Manager' menu: */
    36443830    addMenu(m_mainMenus, action(UIActionIndexMN_M_Medium));
     
    38204006    pMenu->addAction(action(UIActionIndexMN_M_File_S_ShowExtraDataManager));
    38214007# endif
     4008    /* 'Show Extension Pack Manager' action goes to 'File' menu: */
     4009    pMenu->addAction(action(UIActionIndexMN_M_File_S_ShowExtensionPackManager));
    38224010    /* 'Show Virtual Medium Manager' action goes to 'File' menu: */
    38234011    pMenu->addAction(action(UIActionIndexMN_M_File_S_ShowVirtualMediumManager));
     
    38434031    pMenu->addAction(action(UIActionIndexMN_M_File_S_ShowExtraDataManager));
    38444032# endif
     4033    /* 'Show Extension Pack Manager' action goes to 'File' menu: */
     4034    pMenu->addAction(action(UIActionIndexMN_M_File_S_ShowExtensionPackManager));
    38454035    /* 'Show Virtual Medium Manager' action goes to 'File' menu: */
    38464036    pMenu->addAction(action(UIActionIndexMN_M_File_S_ShowVirtualMediumManager));
     
    40804270}
    40814271
     4272void UIActionPoolManager::updateMenuExtensionWindow()
     4273{
     4274    /* Update corresponding menu: */
     4275    updateMenuExtensionWrapper(action(UIActionIndexMN_M_ExtensionWindow)->menu());
     4276
     4277    /* Mark menu as valid: */
     4278    m_invalidations.remove(UIActionIndexMN_M_ExtensionWindow);
     4279}
     4280
     4281void UIActionPoolManager::updateMenuExtension()
     4282{
     4283    /* Update corresponding menu: */
     4284    updateMenuExtensionWrapper(action(UIActionIndexMN_M_Extension)->menu());
     4285
     4286    /* Mark menu as valid: */
     4287    m_invalidations.remove(UIActionIndexMN_M_Extension);
     4288}
     4289
     4290void UIActionPoolManager::updateMenuExtensionWrapper(UIMenu *pMenu)
     4291{
     4292    /* Clear contents: */
     4293    pMenu->clear();
     4294
     4295    /* 'Add' action: */
     4296    addAction(pMenu, action(UIActionIndexMN_M_Extension_S_Install));
     4297    /* 'Remove' action: */
     4298    addAction(pMenu, action(UIActionIndexMN_M_Extension_S_Uninstall));
     4299}
     4300
    40824301void UIActionPoolManager::updateMenuMediumWindow()
    40834302{
  • trunk/src/VBox/Frontends/VirtualBox/src/globals/UIActionPoolManager.h

    r87342 r87354  
    3737    /* 'File' menu actions: */
    3838    UIActionIndexMN_M_File = UIActionIndex_Max + 1,
     39    UIActionIndexMN_M_File_S_ShowExtensionPackManager,
    3940    UIActionIndexMN_M_File_S_ShowVirtualMediumManager,
    4041    UIActionIndexMN_M_File_S_ShowHostNetworkManager,
     
    134135    /* Global Tools actions: */
    135136    UIActionIndexMN_M_Tools_M_Global,
     137    UIActionIndexMN_M_Tools_M_Global_S_ExtensionPackManager,
    136138    UIActionIndexMN_M_Tools_M_Global_S_VirtualMediaManager,
    137139    UIActionIndexMN_M_Tools_M_Global_S_HostNetworkManager,
     
    146148    UIActionIndexMN_M_Snapshot_T_Properties,
    147149    UIActionIndexMN_M_Snapshot_S_Clone,
     150
     151    /* Extension Pack Manager actions: */
     152    UIActionIndexMN_M_ExtensionWindow,
     153    UIActionIndexMN_M_Extension,
     154    UIActionIndexMN_M_Extension_S_Install,
     155    UIActionIndexMN_M_Extension_S_Uninstall,
    148156
    149157    /* Virtual Media Manager actions: */
     
    258266    void updateMenuMachineTools();
    259267
     268    /** Updates 'Extension Pack' window menu. */
     269    void updateMenuExtensionWindow();
     270    /** Updates 'Extension Pack' menu. */
     271    void updateMenuExtension();
     272    /** Updates 'Extension Pack' @a pMenu. */
     273    void updateMenuExtensionWrapper(UIMenu *pMenu);
     274
    260275    /** Updates 'Medium' window menu. */
    261276    void updateMenuMediumWindow();
  • trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.cpp

    r87312 r87354  
    8282#include "CMediumFormat.h"
    8383#include "CAppliance.h"
     84#include "CExtPack.h"
    8485#include "CExtPackManager.h"
    8586#include "CExtPackFile.h"
     
    31723173}
    31733174
     3175void UIMessageCenter::cannotAcquireExtensionPackManager(const CVirtualBox &comVBox, QWidget *pParent /* = 0 */) const
     3176{
     3177    error(pParent, MessageType_Error,
     3178          tr("Failed to acquire Extension Pack Manager."),
     3179          UIErrorString::formatErrorInfo(comVBox));
     3180}
     3181
     3182void UIMessageCenter::cannotAcquireExtensionPacks(const CExtPackManager &comEPManager, QWidget *pParent /* = 0 */) const
     3183{
     3184    error(pParent, MessageType_Error,
     3185          tr("Failed to acquire extension packs."),
     3186          UIErrorString::formatErrorInfo(comEPManager));
     3187}
     3188
     3189void UIMessageCenter::cannotAcquireExtensionPackParameter(const CExtPack &comPackage, QWidget *pParent /* = 0 */) const
     3190{
     3191    error(pParent, MessageType_Error,
     3192          tr("Failed to acquire parameter of the Extension Pack <b>%1</b>.")
     3193             .arg(CExtPack(comPackage).GetName()),
     3194          UIErrorString::formatErrorInfo(comPackage));
     3195}
     3196
    31743197#ifdef VBOX_WITH_DRAG_AND_DROP
    31753198void UIMessageCenter::cannotDropDataToGuest(const CDnDTarget &dndTarget, QWidget *pParent /* = 0 */) const
  • trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMessageCenter.h

    r87312 r87354  
    541541    void cannotUninstallExtPack(const CProgress &progress, const QString &strPackName, QWidget *pParent = 0) const;
    542542    void warnAboutExtPackInstalled(const QString &strPackName, QWidget *pParent = 0) const;
     543    void cannotAcquireExtensionPackManager(const CVirtualBox &comVBox, QWidget *pParent = 0) const;
     544    void cannotAcquireExtensionPacks(const CExtPackManager &comEPManager, QWidget *pParent = 0) const;
     545    void cannotAcquireExtensionPackParameter(const CExtPack &comPackage, QWidget *pParent = 0) const;
    543546
    544547#ifdef VBOX_WITH_DRAG_AND_DROP
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/UIToolPaneGlobal.cpp

    r87342 r87354  
    2727#include "UICommon.h"
    2828#include "UICloudProfileManager.h"
     29#include "UIExtensionPackManager.h"
    2930#include "UIMediumManager.h"
    3031#include "UINetworkManager.h"
     
    4243    , m_pLayout(0)
    4344    , m_pPaneWelcome(0)
     45    , m_pPaneExtensions(0)
    4446    , m_pPaneMedia(0)
    4547    , m_pPaneNetwork(0)
     
    121123                break;
    122124            }
     125            case UIToolType_Extensions:
     126            {
     127                /* Create Extension Pack Manager: */
     128                m_pPaneExtensions = new UIExtensionPackManagerWidget(EmbedTo_Stack, m_pActionPool, false /* show toolbar */);
     129                AssertPtrReturnVoid(m_pPaneExtensions);
     130                {
     131#ifndef VBOX_WS_MAC
     132                    const int iMargin = qApp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin) / 4;
     133                    m_pPaneExtensions->setContentsMargins(iMargin, 0, iMargin, 0);
     134#endif
     135
     136                    /* Configure pane: */
     137                    m_pPaneExtensions->setProperty("ToolType", QVariant::fromValue(UIToolType_Extensions));
     138
     139                    /* Add into layout: */
     140                    m_pLayout->addWidget(m_pPaneExtensions);
     141                    m_pLayout->setCurrentWidget(m_pPaneExtensions);
     142                }
     143                break;
     144            }
    123145            case UIToolType_Media:
    124146            {
     
    227249        switch (enmType)
    228250        {
    229             case UIToolType_Welcome: m_pPaneWelcome = 0; break;
    230             case UIToolType_Media:   m_pPaneMedia = 0; break;
    231             case UIToolType_Network: m_pPaneNetwork = 0; break;
    232             case UIToolType_Cloud:   m_pPaneCloud = 0; break;
     251            case UIToolType_Welcome:    m_pPaneWelcome = 0; break;
     252            case UIToolType_Extensions: m_pPaneExtensions = 0; break;
     253            case UIToolType_Media:      m_pPaneMedia = 0; break;
     254            case UIToolType_Network:    m_pPaneNetwork = 0; break;
     255            case UIToolType_Cloud:      m_pPaneCloud = 0; break;
    233256            default: break;
    234257        }
     
    252275            pCurrentToolWidget = m_pPaneWelcome;
    253276            break;
     277        case UIToolType_Extensions:
     278            pCurrentToolWidget = m_pPaneExtensions;
     279            break;
    254280        case UIToolType_Media:
    255281            pCurrentToolWidget = m_pPaneMedia;
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/UIToolPaneGlobal.h

    r87342 r87354  
    3434class UIActionPool;
    3535class UICloudProfileManagerWidget;
     36class UIExtensionPackManagerWidget;
    3637class UIMediumManagerWidget;
    3738class UINetworkManagerWidget;
     
    9192
    9293    /** Holds the stacked-layout instance. */
    93     QStackedLayout              *m_pLayout;
     94    QStackedLayout               *m_pLayout;
    9495    /** Holds the Welcome pane instance. */
    95     UIWelcomePane               *m_pPaneWelcome;
     96    UIWelcomePane                *m_pPaneWelcome;
     97    /** Holds the Extension Pack Manager instance. */
     98    UIExtensionPackManagerWidget *m_pPaneExtensions;
    9699    /** Holds the Virtual Media Manager instance. */
    97     UIMediumManagerWidget       *m_pPaneMedia;
     100    UIMediumManagerWidget        *m_pPaneMedia;
    98101    /** Holds the Network Manager instance. */
    99     UINetworkManagerWidget      *m_pPaneNetwork;
     102    UINetworkManagerWidget       *m_pPaneNetwork;
    100103    /** Holds the Cloud Profile Manager instance. */
    101     UICloudProfileManagerWidget *m_pPaneCloud;
     104    UICloudProfileManagerWidget  *m_pPaneCloud;
    102105    /** Holds the VM Resource Monitor instance. */
    103     UIResourceMonitorWidget     *m_pPaneResourceMonitor;
     106    UIResourceMonitorWidget      *m_pPaneResourceMonitor;
    104107
    105108    /** Holds whether this pane is active. */
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/UIVirtualBoxManager.cpp

    r87342 r87354  
    4444#include "UIDesktopWidgetWatchdog.h"
    4545#include "UIErrorString.h"
     46#include "UIExtensionPackManager.h"
    4647#include "UIExtraDataManager.h"
    4748#include "UIIconPool.h"
     
    466467    , m_fFirstMediumEnumerationHandled(false)
    467468    , m_pActionPool(0)
     469    , m_pManagerExtensionPack(0)
    468470    , m_pManagerVirtualMedia(0)
    469471    , m_pManagerHostNetwork(0)
     
    703705    switch (m_pWidget->toolsType())
    704706    {
     707        case UIToolType_Extensions:  sltCloseExtensionPackManagerWindow(); break;
    705708        case UIToolType_Media:       sltCloseVirtualMediumManagerWindow(); break;
    706709        case UIToolType_Network:     sltCloseNetworkManagerWindow(); break;
     
    732735    if (m_menuUpdateHandlers.contains(iIndex))
    733736        (this->*(m_menuUpdateHandlers.value(iIndex)))(pMenu);
     737}
     738
     739void UIVirtualBoxManager::sltOpenExtensionPackManagerWindow()
     740{
     741    /* First check if instance of widget opened the embedded way: */
     742    if (m_pWidget->isGlobalToolOpened(UIToolType_Extensions))
     743    {
     744        m_pWidget->setToolsType(UIToolType_Welcome);
     745        m_pWidget->closeGlobalTool(UIToolType_Extensions);
     746    }
     747
     748    /* Create instance if not yet created: */
     749    if (!m_pManagerExtensionPack)
     750    {
     751        UIExtensionPackManagerFactory(m_pActionPool).prepare(m_pManagerExtensionPack, this);
     752        connect(m_pManagerExtensionPack, &QIManagerDialog::sigClose,
     753                this, &UIVirtualBoxManager::sltCloseExtensionPackManagerWindow);
     754    }
     755
     756    /* Show instance: */
     757    m_pManagerExtensionPack->show();
     758    m_pManagerExtensionPack->setWindowState(m_pManagerExtensionPack->windowState() & ~Qt::WindowMinimized);
     759    m_pManagerExtensionPack->activateWindow();
     760}
     761
     762void UIVirtualBoxManager::sltCloseExtensionPackManagerWindow()
     763{
     764    /* Destroy instance if still exists: */
     765    if (m_pManagerExtensionPack)
     766        UIExtensionPackManagerFactory().cleanup(m_pManagerExtensionPack);
    734767}
    735768
     
    23132346
    23142347    /* 'File' menu connections: */
     2348    connect(actionPool()->action(UIActionIndexMN_M_File_S_ShowExtensionPackManager), &UIAction::triggered,
     2349            this, &UIVirtualBoxManager::sltOpenExtensionPackManagerWindow);
    23152350    connect(actionPool()->action(UIActionIndexMN_M_File_S_ShowVirtualMediumManager), &UIAction::triggered,
    23162351            this, &UIVirtualBoxManager::sltOpenVirtualMediumManagerWindow);
     
    25412576{
    25422577    /* Close the sub-dialogs first: */
     2578    sltCloseExtensionPackManagerWindow();
    25432579    sltCloseVirtualMediumManagerWindow();
    25442580    sltCloseNetworkManagerWindow();
     
    31263162    actionPool()->action(UIActionIndexMN_M_Machine)->setVisible(fMachineMenuShown);
    31273163
     3164    /* Determine whether Extensions menu should be visible: */
     3165    const bool fExtensionsMenuShown = fGlobalMenuShown && m_pWidget->currentGlobalTool() == UIToolType_Extensions;
     3166    actionPool()->action(UIActionIndexMN_M_Extension)->setVisible(fExtensionsMenuShown);
    31283167    /* Determine whether Media menu should be visible: */
    31293168    const bool fMediumMenuShown = fGlobalMenuShown && m_pWidget->currentGlobalTool() == UIToolType_Media;
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/UIVirtualBoxManager.h

    r87342 r87354  
    155155    /** @name File menu stuff.
    156156      * @{ */
     157        /** Handles call to open Extension Pack Manager window. */
     158        void sltOpenExtensionPackManagerWindow();
     159        /** Handles call to close Extension Pack Manager window. */
     160        void sltCloseExtensionPackManagerWindow();
     161
    157162        /** Handles call to open Virtual Medium Manager window. */
    158163        void sltOpenVirtualMediumManagerWindow();
     
    464469    QMap<int, MenuUpdateHandler> m_menuUpdateHandlers;
    465470
     471    /** Holds the Extension Pack window instance. */
     472    QIManagerDialog *m_pManagerExtensionPack;
    466473    /** Holds the Virtual Media Manager window instance. */
    467474    QIManagerDialog *m_pManagerVirtualMedia;
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/UIVirtualBoxManagerWidget.cpp

    r87103 r87354  
    791791                    m_pToolBar->addAction(actionPool()->action(UIActionIndexMN_M_Welcome_S_New));
    792792                    m_pToolBar->addAction(actionPool()->action(UIActionIndexMN_M_Welcome_S_Add));
     793                    break;
     794                }
     795                case UIToolType_Extensions:
     796                {
     797                    m_pToolBar->addAction(actionPool()->action(UIActionIndexMN_M_Extension_S_Install));
     798                    m_pToolBar->addAction(actionPool()->action(UIActionIndexMN_M_Extension_S_Uninstall));
    793799                    break;
    794800                }
  • trunk/src/VBox/Frontends/VirtualBox/src/manager/tools/UIToolsModel.cpp

    r86668 r87354  
    441441        {
    442442            case UIToolType_Welcome:     pItem->reconfigure(tr("Welcome")); break;
     443            case UIToolType_Extensions:  pItem->reconfigure(tr("Extensions")); break;
    443444            case UIToolType_Media:       pItem->reconfigure(tr("Media")); break;
    444445            case UIToolType_Network:     pItem->reconfigure(tr("Network")); break;
     
    490491                               UIIconPool::iconSet(":/welcome_screen_24px.png", ":/welcome_screen_24px.png"));
    491492
     493    /* Extensions: */
     494    m_items << new UIToolsItem(scene(), UIToolClass_Global, UIToolType_Extensions, QString(),
     495                               UIIconPool::iconSet(":/extension_pack_manager_24px.png", ":/extension_pack_manager_disabled_24px.png"));
     496
    492497    /* Media: */
    493498    m_items << new UIToolsItem(scene(), UIToolClass_Global, UIToolType_Media, QString(),
Note: See TracChangeset for help on using the changeset viewer.

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