VirtualBox

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


Ignore:
Timestamp:
Dec 7, 2011 12:19:44 PM (13 years ago)
Author:
vboxsync
Message:

FE/Qt: 5804: Allow one operation on several VMs: VM details support for choosing several VMs, step 4: Dynamic content building for the VM details divided into even more small steps, event-loop handles user-interaction events after every section of every block populated.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/UIVMDesktop.cpp

    r39399 r39546  
    4545#include "VBoxUtils.h"
    4646
    47 /*
    48  * Todo:
    49  * - dynamically change size of preview window!
    50  */
     47/* Forward declarations: */
     48class UIDetails;
     49class UIDetailsBlock;
     50class UIDetailsPagePrivate;
    5151
    5252//#ifdef Q_WS_MAC
     
    7272#endif /* !Q_WS_MAC */
    7373
    74 class UIEventForBlockUpdate : public QEvent
     74class UIEventDetailsPrepareStart : public QEvent
    7575{
    7676public:
    7777
    7878    enum { Type = QEvent::User + 1 };
    79 
    80     UIEventForBlockUpdate(const QUuid &requestId, int iBlockNumber, bool fNewBlock)
    81         : QEvent((QEvent::Type)Type), m_requestId(requestId), m_iBlockNumber(iBlockNumber), m_fNewBlock(fNewBlock)
    82     {
    83     }
    84 
    85     QUuid requestId() const { return m_requestId; }
     79    UIEventDetailsPrepareStart() : QEvent((QEvent::Type)Type) {}
     80};
     81
     82class UIEventDetailsPrepareBlockStart : public QEvent
     83{
     84public:
     85
     86    enum { Type = QEvent::User + 2 };
     87    UIEventDetailsPrepareBlockStart(int iBlockNumber) : QEvent((QEvent::Type)Type), m_iBlockNumber(iBlockNumber) {}
    8688    int blockNumber() const { return m_iBlockNumber; }
    87     bool newBlock() const { return m_fNewBlock; }
    8889
    8990private:
    9091
    91     QUuid m_requestId;
    9292    int m_iBlockNumber;
    93     bool m_fNewBlock;
     93};
     94
     95class UIEventDetailsPrepareBlockFinish : public QEvent
     96{
     97public:
     98
     99    enum { Type = QEvent::User + 3 };
     100    UIEventDetailsPrepareBlockFinish(int iBlockNumber) : QEvent((QEvent::Type)Type), m_iBlockNumber(iBlockNumber) {}
     101    int blockNumber() const { return m_iBlockNumber; }
     102
     103private:
     104
     105    int m_iBlockNumber;
     106};
     107
     108class UIEventDetailsBlockPrepareStart : public QEvent
     109{
     110public:
     111
     112    enum { Type = QEvent::User + 1 };
     113    UIEventDetailsBlockPrepareStart() : QEvent((QEvent::Type)Type) {}
     114};
     115
     116class UIEventDetailsBlockPrepareSectionStart : public QEvent
     117{
     118public:
     119
     120    enum { Type = QEvent::User + 2 };
     121    UIEventDetailsBlockPrepareSectionStart(int iSectionNumber) : QEvent((QEvent::Type)Type), m_iSectionNumber(iSectionNumber) {}
     122    int sectionNumber() const { return m_iSectionNumber; }
     123
     124private:
     125
     126    int m_iSectionNumber;
     127};
     128
     129class UIEventDetailsBlockPrepareSectionFinish : public QEvent
     130{
     131public:
     132
     133    enum { Type = QEvent::User + 3 };
     134    UIEventDetailsBlockPrepareSectionFinish(int iSectionNumber) : QEvent((QEvent::Type)Type), m_iSectionNumber(iSectionNumber) {}
     135    int sectionNumber() const { return m_iSectionNumber; }
     136
     137private:
     138
     139    int m_iSectionNumber;
    94140};
    95141
     
    115161
    116162/**
     163 *  UIDetails class.
     164 *  QWidget container to store UIDetailsBlock(s).
     165 */
     166class UIDetails : public QWidget
     167{
     168    Q_OBJECT;
     169
     170public:
     171
     172    /* Constructor: */
     173    UIDetails(UIDetailsPagePrivate *pDetailsPage);
     174
     175    /* Operator: */
     176    UIDetailsBlock*& operator[](int i) { return m_details[i]; }
     177
     178    /* Machine list setter: */
     179    void setMachines(const QList<CMachine> &machines);
     180
     181    /* Own wrappers: */
     182    UIDetailsPagePrivate* detailsPage() const { return m_pUIDetailsPage; }
     183    const QList<Section>& sections() const { return m_sections; }
     184    bool accessibility(int iBlockNumber) const { return m_accessibilities[iBlockNumber]; }
     185    void setUSBAvailable(bool fAvailable) { m_fUSBAvailable = fAvailable; }
     186
     187    /* Parent wrappers: */
     188    bool sectionOpened(Section section) const;
     189    void setSectionOpened(Section section, bool fOpened);
     190    QAction* action(Section section) const;
     191
     192private slots:
     193
     194    /* Details pane context menu handler: */
     195    void sltContextMenuRequested(const QPoint &pos);
     196
     197    /* Details pane popup  widget toggle handler: */
     198    void sltPopupToggled(bool fPopupOpened);
     199
     200private:
     201
     202    /* Main event handler: */
     203    bool event(QEvent *pEvent);
     204
     205    /* Block preparation delegate(s): */
     206    void createBlock(int iBlockNumber);
     207    void layoutBlock(int iBlockNumber);
     208
     209    /* Variables: */
     210    UIDetailsPagePrivate *m_pUIDetailsPage;
     211    int m_cBlockCount;
     212    QVector<CMachine> m_machines;
     213    QVector<bool> m_accessibilities;
     214    QList<Section> m_sections;
     215    QMap<int, UIDetailsBlock*> m_details;
     216    bool m_fUSBAvailable;
     217};
     218
     219/**
    117220 *  UIDetailsBlock class.
    118  *  QWidget container to store UIPopupBox sections.
     221 *  QWidget container to store UIPopupBox(s).
    119222 */
    120223class UIDetailsBlock : public QWidget
     
    124227public:
    125228
    126     UIDetailsBlock(QWidget *pParent)
    127         : QWidget(pParent)
    128     {
    129     }
    130 
    131     UIPopupBox*& operator[](Section section)
    132     {
    133         return m_sections[section];
    134     }
    135 
    136 private:
    137 
    138     QMap<Section, UIPopupBox*> m_sections;
    139 };
    140 typedef QVector<UIDetailsBlock*> UIDetailsSet;
    141 
    142 /**
    143  *  UIDescriptionPagePrivate
    144  */
    145 class UIDetailsPagePrivate : public QIWithRetranslateUI<QStackedWidget>
    146 {
    147     Q_OBJECT;
    148 
    149 public:
    150 
    151     UIDetailsPagePrivate(QWidget *pParent, QAction *pRefreshAction = 0);
    152     ~UIDetailsPagePrivate();
    153 
    154     void setMachines(const QList<CMachine> &machines);
    155     void setText(const QString &aText);
    156     void setErrorText(const QString &aText);
    157 
    158 signals:
    159 
    160     void linkClicked(const QString &url);
    161 
    162 protected:
    163 
    164     void retranslateUi();
    165     bool event(QEvent *pEvent);
     229    /* Constructor: */
     230    UIDetailsBlock(UIDetails *pParent, const QList<Section> &sections, int iBlockNumber);
     231
     232    /* Operator: */
     233    UIPopupBox*& operator[](Section section) { return m_block[section]; }
     234
     235    /* Machine setter: */
     236    void setMachine(const CMachine &machine);
     237
     238    /* Own wrappers: */
     239    UIDetails* details() const { return m_pUIDetails; }
     240
     241    /* Parent wrappers: */
     242    bool accessibility() const;
     243    bool sectionOpened(Section section) const;
     244    void setUSBAvailable(bool fAvailable);
    166245
    167246private slots:
    168247
     248    /* Popup preparation handlers: */
    169249    void sltUpdateGeneral();
     250    void sltUpdateSystem();
    170251    void sltUpdatePreview();
    171     void sltUpdateSystem();
    172252    void sltUpdateDisplay();
    173253    void sltUpdateStorage();
     
    182262    void sltUpdateDescription();
    183263
    184     void sltContextMenuRequested(const QPoint &pos);
     264private:
     265
     266    /* Main event handler: */
     267    bool event(QEvent *pEvent);
     268
     269    /* Section preparation delegate: */
     270    void createSection(int iSectionNumber);
     271
     272    /* Static stuff: */
     273    static QString summarizeGenericProperties(const CNetworkAdapter &adapter);
     274
     275    /* Variables: */
     276    CVirtualBox m_vbox;
     277    UIDetails *m_pUIDetails;
     278    int m_iBlockNumber;
     279    int m_cSectionCount;
     280    CMachine m_machine;
     281    QList<Section> m_sections;
     282    QMap<Section, UIPopupBox*> m_block;
     283};
     284
     285/**
     286 *  UIDetailsPagePrivate class.
     287 *  QWidget container to store UIDetails.
     288 */
     289class UIDetailsPagePrivate : public QIWithRetranslateUI<QStackedWidget>
     290{
     291    Q_OBJECT;
     292
     293public:
     294
     295    /* Constructor/destructor: */
     296    UIDetailsPagePrivate(QWidget *pParent, QAction *pRefreshAction = 0);
     297    ~UIDetailsPagePrivate();
     298
     299    /* Setters: */
     300    void setMachines(const QList<CMachine> &machines);
     301    void setText(const QString &aText);
     302    void setErrorText(const QString &aText);
     303
     304    /* Own wrappers: */
     305    bool sectionOpened(Section section) const { return m_sectionOpened[section]; }
     306    void setSectionOpened(Section section, bool fOpened) { m_sectionOpened[section] = fOpened; }
     307    QAction* action(Section section) { return m_actions[section]; }
     308
     309signals:
     310
     311    void linkClicked(const QString &url);
     312
     313protected:
     314
     315    void retranslateUi();
     316
     317private slots:
    185318
    186319    void sltLinkClicked(const QUrl &url) { emit linkClicked(url.toString()); }
    187320
    188     void sltPopupToggled(bool fPopupOpened);
    189 
    190321private:
    191322
    192     void prepareDetails();
    193     void cleanupDetails();
     323    void prepareDetailsPage();
     324    void cleanupDetailsPage();
    194325
    195326    void prepareTextPage();
     
    197328    void prepareErrorPage();
    198329
    199     void prepareSet(bool fNewSet);
    200     void prepareBlock(int iBlockNumber, bool fNewBlock);
    201     void prepareSection(UIDetailsBlock &block, int iBlockNumber, Section section);
     330    void prepareDetails(const QList<CMachine> &machines);
    202331
    203332    void saveSectionSetting();
    204333
    205     static QString summarizeGenericProperties(const CNetworkAdapter &adapter);
    206 
    207     /* Common variables: */
    208     CVirtualBox m_vbox;
     334    /* Details-view variables: */
    209335    int m_cMachineCount;
    210     QVector<CMachine> m_machines;
    211     QVector<bool> m_changeable;
    212 
    213     /* Details-view variables: */
    214336    QScrollArea *m_pScrollArea;
    215     QWidget *m_pDetails;
     337    UIDetails *m_pDetails;
    216338    QMap<Section, QString> m_sectionSettings;
    217339    QMap<Section, QString> m_sectionNames;
    218340    QMap<Section, bool> m_sectionOpened;
    219341    QMap<Section, QAction*> m_actions;
    220     QList<Section> m_sections;
    221     UIDetailsSet m_set;
    222     bool m_fUSBAvailable;
    223     QUuid m_currentRequestId;
    224342
    225343    /* Free text: */
     
    234352};
    235353
    236 UIDetailsPagePrivate::UIDetailsPagePrivate(QWidget *pParent, QAction *pRefreshAction /* = 0 */)
    237     : QIWithRetranslateUI<QStackedWidget>(pParent)
    238     , m_vbox(vboxGlobal().virtualBox())
    239     , m_cMachineCount(0)
    240     , m_pScrollArea(0)
    241     , m_pDetails(0)
     354UIDetails::UIDetails(UIDetailsPagePrivate *pDetailsPage)
     355    : QWidget(pDetailsPage)
     356    , m_pUIDetailsPage(pDetailsPage)
     357    , m_cBlockCount(0)
    242358    , m_fUSBAvailable(true)
    243     , m_pText(0)
    244     , m_pErrBox(0), m_pErrLabel(0), m_pErrText(0)
    245     , m_pRefreshButton(0), m_pRefreshAction(pRefreshAction)
    246 {
    247     /* Check that refresh action was passed: */
    248     Assert(m_pRefreshAction);
    249 }
    250 
    251 UIDetailsPagePrivate::~UIDetailsPagePrivate()
    252 {
    253     /* Cleanup details: */
    254     cleanupDetails();
    255 }
    256 
    257 void UIDetailsPagePrivate::setMachines(const QList<CMachine> &machines)
    258 {
    259     /* Prepare variables: */
    260     bool fCountChanged = machines.size() != m_cMachineCount;
    261     m_cMachineCount = machines.size();
    262     /* Recreate corresponding vectors: */
    263     m_machines.clear();
    264     m_machines.resize(m_cMachineCount);
    265     m_changeable.clear();
    266     m_changeable.resize(m_cMachineCount);
    267     /* Fetch passed VMs: */
    268     for (int i = 0; i < machines.size(); ++i)
    269     {
    270         /* Get current VM: */
    271         const CMachine &machine = machines[i];
    272         /* Assign corresponding vector values: */
    273         m_machines[i] = machine;
    274         m_changeable[i] = machine.isNull() || !machine.GetAccessible() ? false :
    275                           machine.GetState() != KMachineState_Stuck &&
    276                           machine.GetState() != KMachineState_Saved /* for now! */;
    277     }
    278 
    279     /* Prepare machine details page if necessary: */
    280     prepareDetails();
    281 
    282     /* Prepare set of blocks: */
    283     prepareSet(fCountChanged /* new set? */);
    284 
    285     /* Select corresponding widget: */
    286     setCurrentIndex(indexOf(m_pScrollArea));
    287 }
    288 
    289 void UIDetailsPagePrivate::setText(const QString &aText)
    290 {
    291     /* Clear machine maps: */
    292     m_machines.clear();
    293     m_machines.resize(0);
    294     m_changeable.clear();
    295     m_changeable.resize(0);
    296 
    297     /* Prepare text page if necessary: */
    298     prepareTextPage();
    299 
    300     /* Assign corresponding text: */
    301     m_pText->setText(aText);
    302 
    303     /* Select corresponding widget: */
    304     setCurrentIndex(indexOf(m_pText));
    305 }
    306 
    307 void UIDetailsPagePrivate::setErrorText(const QString &aText)
    308 {
    309     /* Clear machine maps: */
    310     m_machines.clear();
    311     m_machines.resize(0);
    312     m_changeable.clear();
    313     m_changeable.resize(0);
    314 
    315     /* Prepare error page if necessary: */
    316     prepareErrorPage();
    317 
    318     /* Assign corresponding error: */
    319     m_pErrText->setText(aText);
    320 
    321     /* Select corresponding widget: */
    322     setCurrentIndex(indexOf(m_pErrBox));
    323 }
    324 
    325 void UIDetailsPagePrivate::retranslateUi()
    326 {
    327     /* Translate context menu actions: */
    328     {
    329         if (m_actions.contains(Section_General))
    330             m_actions[Section_General]->setText(tr("General", "details report"));
    331         if (m_actions.contains(Section_System))
    332             m_actions[Section_System]->setText(tr("System", "details report"));
    333         if (m_actions.contains(Section_Preview))
    334             m_actions[Section_Preview]->setText(tr("Preview", "details report"));
    335         if (m_actions.contains(Section_Display))
    336             m_actions[Section_Display]->setText(tr("Display", "details report"));
    337         if (m_actions.contains(Section_Storage))
    338             m_actions[Section_Storage]->setText(tr("Storage", "details report"));
    339         if (m_actions.contains(Section_Audio))
    340             m_actions[Section_Audio]->setText(tr("Audio", "details report"));
    341         if (m_actions.contains(Section_Network))
    342             m_actions[Section_Network]->setText(tr("Network", "details report"));
    343         if (m_actions.contains(Section_Serial))
    344             m_actions[Section_Serial]->setText(tr("Serial Ports", "details report"));
    345 #ifdef VBOX_WITH_PARALLEL_PORTS
    346         if (m_actions.contains(Section_Parallel))
    347             m_actions[Section_Parallel]->setText(tr("Parallel Ports", "details report"));
    348 #endif /* VBOX_WITH_PARALLEL_PORTS */
    349         if (m_actions.contains(Section_USB))
    350             m_actions[Section_USB]->setText(tr("USB", "details report"));
    351         if (m_actions.contains(Section_SharedFolders))
    352             m_actions[Section_SharedFolders]->setText(tr("Shared Folders", "details report"));
    353         if (m_actions.contains(Section_Description))
    354             m_actions[Section_Description]->setText(tr("Description", "details report"));
    355     }
    356 
    357     /* Translate error-label text: */
    358     if (m_pErrLabel)
    359         m_pErrLabel->setText(tr("The selected virtual machine is <i>inaccessible</i>. "
    360                                 "Please inspect the error message shown below and press the "
    361                                 "<b>Refresh</b> button if you want to repeat the accessibility check:"));
    362 
    363     /* Translate refresh button & action text: */
    364     if (m_pRefreshAction && m_pRefreshButton)
    365     {
    366         m_pRefreshButton->setText(m_pRefreshAction->text());
    367         m_pRefreshButton->setIcon(m_pRefreshAction->icon());
    368         m_pRefreshButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    369     }
    370 }
    371 
    372 bool UIDetailsPagePrivate::event(QEvent *pEvent)
    373 {
    374     /* Handle special cases: */
    375     switch (pEvent->type())
    376     {
    377         case UIEventForBlockUpdate::Type:
    378         {
    379             /* Cast and accept event: */
    380             UIEventForBlockUpdate *pEventForBlockUpdate = static_cast<UIEventForBlockUpdate*>(pEvent);
    381             pEventForBlockUpdate->accept();
    382             /* Check that request is NOT outdated: */
    383             if (pEventForBlockUpdate->requestId() == m_currentRequestId)
    384             {
    385                 /* Process current request: */
    386                 prepareBlock(pEventForBlockUpdate->blockNumber(), pEventForBlockUpdate->newBlock());
    387                 /* Create next request: */
    388                 if (pEventForBlockUpdate->blockNumber() < m_cMachineCount - 1)
    389                     QCoreApplication::postEvent(this, new UIEventForBlockUpdate(pEventForBlockUpdate->requestId(),
    390                                                                                 pEventForBlockUpdate->blockNumber() + 1,
    391                                                                                 pEventForBlockUpdate->newBlock()));
    392             }
    393             return true;
    394         }
    395         default:
    396             break;
    397     }
    398     /* Call to base-class: */
    399     return QIWithRetranslateUI<QStackedWidget>::event(pEvent);
    400 }
    401 
    402 void UIDetailsPagePrivate::sltUpdateGeneral()
    403 {
    404     /* Get current sender: */
    405     UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
    406     AssertMsg(pSender, ("Sender should be valid!\n"));
    407     /* Get current block number: */
    408     int iBlockNumber = pSender->property("block-number").toInt();
    409     /* Get current machine: */
    410     CMachine &machine = m_machines[iBlockNumber];
    411     AssertMsg(!machine.isNull(), ("Machine should be valid!\n"));
    412     /* Get details block: */
    413     UIDetailsBlock &block = *m_set[iBlockNumber];
    414     /* Get corresponding content widget: */
    415     QILabel *pLabel = qobject_cast<QILabel*>(block[Section_General]->contentWidget());
    416     AssertMsg(pLabel, ("Content widget should be valid!"));
    417 
    418     /* Enable link: */
    419     block[Section_General]->setTitleLinkEnabled(m_changeable[iBlockNumber]);
    420 
    421     /* Update if content widget is visible: */
    422     if (pSender->isOpen())
    423     {
    424         if (!machine.isNull())
    425         {
    426             QString item;
    427             if (machine.GetAccessible())
    428             {
    429                 item = sSectionItemTpl2.arg(tr("Name", "details report"), machine.GetName())
    430                      + sSectionItemTpl2.arg(tr("OS Type", "details report"), vboxGlobal().vmGuestOSTypeDescription(machine.GetOSTypeId()));
    431             }
    432             else
    433             {
    434                 item = QString(sSectionItemTpl1).arg(tr("Information inaccessible", "details report"));
    435             }
    436             pLabel->setText(sTableTpl.arg(item));
    437         }
    438         else
    439             pLabel->clear();
    440     }
    441 }
    442 
    443 void UIDetailsPagePrivate::sltUpdateSystem()
    444 {
    445     /* Get current sender: */
    446     UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
    447     AssertMsg(pSender, ("Sender should be valid!\n"));
    448     /* Get current block number: */
    449     int iBlockNumber = pSender->property("block-number").toInt();
    450     /* Get current machine: */
    451     CMachine &machine = m_machines[iBlockNumber];
    452     AssertMsg(!machine.isNull(), ("Machine should be valid!\n"));
    453     /* Get details block: */
    454     UIDetailsBlock &block = *m_set[iBlockNumber];
    455     /* Get corresponding content widget: */
    456     QILabel *pLabel = qobject_cast<QILabel*>(block[Section_System]->contentWidget());
    457     AssertMsg(pLabel, ("Content widget should be valid!"));
    458 
    459     /* Enable link: */
    460     block[Section_System]->setTitleLinkEnabled(m_changeable[iBlockNumber]);
    461 
    462     /* Update if content widget is visible: */
    463     if (pSender->isOpen())
    464     {
    465         if (!machine.isNull())
    466         {
    467             QString item;
    468             if (machine.GetAccessible())
    469             {
    470                 item = sSectionItemTpl2.arg(tr("Base Memory", "details report"), tr("<nobr>%1 MB</nobr>", "details report"))
    471                                        .arg(machine.GetMemorySize());
    472 
    473                 int cCPU = machine.GetCPUCount();
    474                 if (cCPU > 1)
    475                     item += sSectionItemTpl2.arg(tr("Processors", "details report"), tr("<nobr>%1</nobr>", "details report"))
    476                                             .arg(cCPU);
    477 
    478                 int iCPUExecCap = machine.GetCPUExecutionCap();
    479                 if (iCPUExecCap < 100)
    480                     item += sSectionItemTpl2.arg(tr("Execution Cap", "details report"), tr("<nobr>%1%</nobr>", "details report"))
    481                                             .arg(iCPUExecCap);
    482 
    483                 /* Boot order: */
    484                 QStringList bootOrder;
    485                 for (ulong i = 1; i <= m_vbox.GetSystemProperties().GetMaxBootPosition(); ++i)
    486                 {
    487                     KDeviceType device = machine.GetBootOrder(i);
    488                     if (device == KDeviceType_Null)
    489                         continue;
    490                     bootOrder << vboxGlobal().toString(device);
    491                 }
    492                 if (bootOrder.isEmpty())
    493                     bootOrder << vboxGlobal().toString(KDeviceType_Null);
    494 
    495                 item += sSectionItemTpl2.arg(tr("Boot Order", "details report"), bootOrder.join(", "));
    496 
    497 #ifdef VBOX_WITH_FULL_DETAILS_REPORT
    498                 /* BIOS Settings holder: */
    499                 const CBIOSSettings &biosSettings = machine.GetBIOSSettings();
    500                 QStringList bios;
    501 
    502                 /* ACPI: */
    503                 if (biosSettings.GetACPIEnabled())
    504                     bios << tr("ACPI", "details report");
    505 
    506                 /* IO APIC: */
    507                 if (biosSettings.GetIOAPICEnabled())
    508                     bios << tr("IO APIC", "details report");
    509 
    510                 if (!bios.isEmpty())
    511                     item += sSectionItemTpl2.arg(tr("BIOS", "details report"), bios.join(", "));
    512 #endif /* VBOX_WITH_FULL_DETAILS_REPORT */
    513 
    514                 QStringList accel;
    515                 if (m_vbox.GetHost().GetProcessorFeature(KProcessorFeature_HWVirtEx))
    516                 {
    517                     /* VT-x/AMD-V: */
    518                     if (machine.GetHWVirtExProperty(KHWVirtExPropertyType_Enabled))
    519                     {
    520                         accel << tr("VT-x/AMD-V", "details report");
    521 
    522                         /* Nested Paging (only when hw virt is enabled): */
    523                         if (machine.GetHWVirtExProperty(KHWVirtExPropertyType_NestedPaging))
    524                             accel << tr("Nested Paging", "details report");
    525                     }
    526                 }
    527 
    528                 /* PAE/NX: */
    529                 if (machine.GetCPUProperty(KCPUPropertyType_PAE))
    530                     accel << tr("PAE/NX", "details report");
    531 
    532                 if (!accel.isEmpty())
    533                     item += sSectionItemTpl2.arg(tr("Acceleration", "details report"), accel.join(", "));
    534             }
    535             else
    536             {
    537                 item = QString(sSectionItemTpl1).arg(tr("Information inaccessible", "details report"));
    538             }
    539             pLabel->setText(sTableTpl.arg(item));
    540         }
    541         else
    542             pLabel->clear();
    543     }
    544 }
    545 
    546 void UIDetailsPagePrivate::sltUpdatePreview()
    547 {
    548     /* Get current sender: */
    549     UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
    550     AssertMsg(pSender, ("Sender should be valid!\n"));
    551     /* Get current block number: */
    552     int iBlockNumber = pSender->property("block-number").toInt();
    553     /* Get current machine: */
    554     CMachine &machine = m_machines[iBlockNumber];
    555     AssertMsg(!machine.isNull(), ("Machine should be valid!\n"));
    556     /* Get details block: */
    557     UIDetailsBlock &block = *m_set[iBlockNumber];
    558     /* Get corresponding content widget: */
    559     UIVMPreviewWindow *pPreview = qobject_cast<UIVMPreviewWindow*>(block[Section_Preview]->contentWidget());
    560     AssertMsg(pPreview, ("Content widget should be valid!"));
    561 
    562     /* Update if content widget is visible: */
    563     if (pSender->isOpen())
    564     {
    565         /* Update preview widget: */
    566         pPreview->setMachine(machine);
    567     }
    568 }
    569 
    570 void UIDetailsPagePrivate::sltUpdateDisplay()
    571 {
    572     /* Get current sender: */
    573     UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
    574     AssertMsg(pSender, ("Sender should be valid!\n"));
    575     /* Get current block number: */
    576     int iBlockNumber = pSender->property("block-number").toInt();
    577     /* Get current machine: */
    578     CMachine &machine = m_machines[iBlockNumber];
    579     AssertMsg(!machine.isNull(), ("Machine should be valid!\n"));
    580     /* Get details block: */
    581     UIDetailsBlock &block = *m_set[iBlockNumber];
    582     /* Get corresponding content widget: */
    583     QILabel *pLabel = qobject_cast<QILabel*>(block[Section_Display]->contentWidget());
    584     AssertMsg(pLabel, ("Content widget should be valid!"));
    585 
    586     /* Enable link: */
    587     block[Section_Display]->setTitleLinkEnabled(m_changeable[iBlockNumber]);
    588 
    589     /* Update if content widget is visible: */
    590     if (pSender->isOpen())
    591     {
    592         if (!machine.isNull())
    593         {
    594             /* Video tab: */
    595             QString item = QString(sSectionItemTpl2).arg(tr("Video Memory", "details report"), tr("<nobr>%1 MB</nobr>", "details report"))
    596                                                     .arg(machine.GetVRAMSize());
    597 
    598             int cGuestScreens = machine.GetMonitorCount();
    599             if (cGuestScreens > 1)
    600                 item += QString(sSectionItemTpl2).arg(tr("Screens", "details report")).arg(cGuestScreens);
    601 
    602             QStringList accel;
    603 #ifdef VBOX_WITH_VIDEOHWACCEL
    604             if (machine.GetAccelerate2DVideoEnabled())
    605                 accel << tr("2D Video", "details report");
    606 #endif /* VBOX_WITH_VIDEOHWACCEL */
    607             if (machine.GetAccelerate3DEnabled())
    608                 accel << tr("3D", "details report");
    609 
    610             if (!accel.isEmpty())
    611                 item += sSectionItemTpl2.arg(tr("Acceleration", "details report"), accel.join(", "));
    612 
    613             /* VRDE tab: */
    614             CVRDEServer srv = machine.GetVRDEServer();
    615             if (!srv.isNull())
    616             {
    617                 if (srv.GetEnabled())
    618                     item += QString(sSectionItemTpl2).arg(tr("Remote Desktop Server Port", "details report (VRDE Server)"))
    619                                                      .arg(srv.GetVRDEProperty("TCP/Ports"));
    620                 else
    621                     item += QString(sSectionItemTpl2).arg(tr("Remote Desktop Server", "details report (VRDE Server)"))
    622                                                      .arg(tr("Disabled", "details report (VRDE Server)"));
    623             }
    624 
    625             pLabel->setText(sTableTpl.arg(item));
    626         }
    627         else
    628             pLabel->clear();
    629     }
    630 }
    631 
    632 void UIDetailsPagePrivate::sltUpdateStorage()
    633 {
    634     /* Get current sender: */
    635     UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
    636     AssertMsg(pSender, ("Sender should be valid!\n"));
    637     /* Get current block number: */
    638     int iBlockNumber = pSender->property("block-number").toInt();
    639     /* Get current machine: */
    640     CMachine &machine = m_machines[iBlockNumber];
    641     AssertMsg(!machine.isNull(), ("Machine should be valid!\n"));
    642     /* Get details block: */
    643     UIDetailsBlock &block = *m_set[iBlockNumber];
    644     /* Get corresponding content widget: */
    645     QILabel *pLabel = qobject_cast<QILabel*>(block[Section_Storage]->contentWidget());
    646     AssertMsg(pLabel, ("Content widget should be valid!"));
    647 
    648     /* Enable link: */
    649     block[Section_Storage]->setTitleLinkEnabled(m_changeable[iBlockNumber]);
    650 
    651     /* Update if content widget is visible: */
    652     if (pSender->isOpen())
    653     {
    654         if (!machine.isNull())
    655         {
    656             QString item;
    657             /* Iterate over the all machine controllers: */
    658             const CStorageControllerVector &controllers = machine.GetStorageControllers();
    659             for (int i = 0; i < controllers.size(); ++i)
    660             {
    661                 /* Get current controller: */
    662                 const CStorageController &controller = controllers[i];
    663                 /* Add controller information: */
    664                 item += QString(sSectionItemTpl3).arg(controller.GetName());
    665 
    666                 /* Populate sorted map with attachments information: */
    667                 QMap<StorageSlot,QString> attachmentsMap;
    668                 const CMediumAttachmentVector &attachments = machine.GetMediumAttachmentsOfController(controller.GetName());
    669                 for (int j = 0; j < attachments.size(); ++j)
    670                 {
    671                     /* Get current attachment: */
    672                     const CMediumAttachment &attachment = attachments[j];
    673                     /* Prepare current storage slot: */
    674                     StorageSlot attachmentSlot(controller.GetBus(), attachment.GetPort(), attachment.GetDevice());
    675                     /* Append 'device slot name' with 'device type name' for CD/DVD devices only: */
    676                     QString strDeviceType = attachment.GetType() == KDeviceType_DVD ? tr("(CD/DVD)") : QString();
    677                     if (!strDeviceType.isNull())
    678                         strDeviceType.prepend(' ');
    679                     /* Prepare current medium object: */
    680                     const CMedium &medium = attachment.GetMedium();
    681                     /* Prepare information about current medium & attachment: */
    682                     QString strAttachmentInfo = !attachment.isOk() ? QString() :
    683                                                 QString(sSectionItemTpl2)
    684                                                 .arg(QString("&nbsp;&nbsp;") +
    685                                                      vboxGlobal().toString(StorageSlot(controller.GetBus(),
    686                                                                                        attachment.GetPort(),
    687                                                                                        attachment.GetDevice())) +
    688                                                      strDeviceType)
    689                                                 .arg(vboxGlobal().details(medium, false));
    690                     /* Insert that attachment into map: */
    691                     if (!strAttachmentInfo.isNull())
    692                         attachmentsMap.insert(attachmentSlot, strAttachmentInfo);
    693                 }
    694 
    695                 /* Iterate over the sorted map with attachments information: */
    696                 QMapIterator<StorageSlot,QString> it(attachmentsMap);
    697                 while (it.hasNext())
    698                 {
    699                     /* Add controller information: */
    700                     it.next();
    701                     item += it.value();
    702                 }
    703             }
    704 
    705             if (item.isNull())
    706                 item = QString(sSectionItemTpl1).arg(tr("Not Attached", "details report (Storage)"));
    707 
    708             pLabel->setText(sTableTpl.arg(item));
    709         }
    710         else
    711             pLabel->clear();
    712     }
    713 }
    714 
    715 void UIDetailsPagePrivate::sltUpdateAudio()
    716 {
    717     /* Get current sender: */
    718     UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
    719     AssertMsg(pSender, ("Sender should be valid!\n"));
    720     /* Get current block number: */
    721     int iBlockNumber = pSender->property("block-number").toInt();
    722     /* Get current machine: */
    723     CMachine &machine = m_machines[iBlockNumber];
    724     AssertMsg(!machine.isNull(), ("Machine should be valid!\n"));
    725     /* Get details block: */
    726     UIDetailsBlock &block = *m_set[iBlockNumber];
    727     /* Get corresponding content widget: */
    728     QILabel *pLabel = qobject_cast<QILabel*>(block[Section_Audio]->contentWidget());
    729     AssertMsg(pLabel, ("Content widget should be valid!"));
    730 
    731     /* Enable link: */
    732     block[Section_Audio]->setTitleLinkEnabled(m_changeable[iBlockNumber]);
    733 
    734     /* Update if content widget is visible: */
    735     if (pSender->isOpen())
    736     {
    737         if (!machine.isNull())
    738         {
    739             QString item;
    740 
    741             const CAudioAdapter &audio = machine.GetAudioAdapter();
    742             if (audio.GetEnabled())
    743                 item = QString(sSectionItemTpl2).arg(tr("Host Driver", "details report (audio)"),
    744                                                      vboxGlobal().toString(audio.GetAudioDriver())) +
    745                        QString(sSectionItemTpl2).arg(tr("Controller", "details report (audio)"),
    746                                                      vboxGlobal().toString(audio.GetAudioController()));
    747             else
    748                 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (audio)"));
    749 
    750             pLabel->setText(sTableTpl.arg(item));
    751         }
    752         else
    753             pLabel->clear();
    754     }
    755 }
    756 
    757 void UIDetailsPagePrivate::sltUpdateNetwork()
    758 {
    759     /* Get current sender: */
    760     UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
    761     AssertMsg(pSender, ("Sender should be valid!\n"));
    762     /* Get current block number: */
    763     int iBlockNumber = pSender->property("block-number").toInt();
    764     /* Get current machine: */
    765     CMachine &machine = m_machines[iBlockNumber];
    766     AssertMsg(!machine.isNull(), ("Machine should be valid!\n"));
    767     /* Get details block: */
    768     UIDetailsBlock &block = *m_set[iBlockNumber];
    769     /* Get corresponding content widget: */
    770     QILabel *pLabel = qobject_cast<QILabel*>(block[Section_Network]->contentWidget());
    771     AssertMsg(pLabel, ("Content widget should be valid!"));
    772 
    773     /* Enable link: */
    774     block[Section_Network]->setTitleLinkEnabled(m_changeable[iBlockNumber]);
    775 
    776     /* Update if content widget is visible: */
    777     if (pSender->isOpen())
    778     {
    779         if (!machine.isNull())
    780         {
    781             QString item;
    782 
    783             ulong count = m_vbox.GetSystemProperties().GetMaxNetworkAdapters(KChipsetType_PIIX3);
    784             for (ulong slot = 0; slot < count; slot ++)
    785             {
    786                 const CNetworkAdapter &adapter = machine.GetNetworkAdapter(slot);
    787                 if (adapter.GetEnabled())
    788                 {
    789                     KNetworkAttachmentType type = adapter.GetAttachmentType();
    790                     QString attType = vboxGlobal().toString(adapter.GetAdapterType())
    791                                       .replace(QRegExp("\\s\\(.+\\)"), " (%1)");
    792                     /* Don't use the adapter type string for types that have
    793                      * an additional symbolic network/interface name field,
    794                      * use this name instead: */
    795                     if (type == KNetworkAttachmentType_Bridged)
    796                         attType = attType.arg(tr("Bridged adapter, %1", "details report (network)").arg(adapter.GetBridgedInterface()));
    797                     else if (type == KNetworkAttachmentType_Internal)
    798                         attType = attType.arg(tr("Internal network, '%1'", "details report (network)").arg(adapter.GetInternalNetwork()));
    799                     else if (type == KNetworkAttachmentType_HostOnly)
    800                         attType = attType.arg(tr("Host-only adapter, '%1'", "details report (network)").arg(adapter.GetHostOnlyInterface()));
    801                     else if (type == KNetworkAttachmentType_Generic)
    802                     {
    803                         QString strGenericDriverProperties(summarizeGenericProperties(adapter));
    804                         attType = strGenericDriverProperties.isNull() ?
    805                                   attType.arg(tr("Generic driver, '%1'", "details report (network)").arg(adapter.GetGenericDriver())) :
    806                                   attType.arg(tr("Generic driver, '%1' {&nbsp;%2&nbsp;}", "details report (network)")
    807                                               .arg(adapter.GetGenericDriver(), strGenericDriverProperties));
    808                     }
    809                     else
    810                         attType = attType.arg(vboxGlobal().toString(type));
    811 
    812                     item += QString(sSectionItemTpl2).arg(tr("Adapter %1", "details report (network)").arg(adapter.GetSlot() + 1))
    813                                                      .arg(attType);
    814                 }
    815             }
    816             if (item.isNull())
    817                 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (network)"));
    818 
    819             pLabel->setText(sTableTpl.arg(item));
    820         }
    821         else
    822             pLabel->clear();
    823     }
    824 }
    825 
    826 void UIDetailsPagePrivate::sltUpdateSerialPorts()
    827 {
    828     /* Get current sender: */
    829     UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
    830     AssertMsg(pSender, ("Sender should be valid!\n"));
    831     /* Get current block number: */
    832     int iBlockNumber = pSender->property("block-number").toInt();
    833     /* Get current machine: */
    834     CMachine &machine = m_machines[iBlockNumber];
    835     AssertMsg(!machine.isNull(), ("Machine should be valid!\n"));
    836     /* Get details block: */
    837     UIDetailsBlock &block = *m_set[iBlockNumber];
    838     /* Get corresponding content widget: */
    839     QILabel *pLabel = qobject_cast<QILabel*>(block[Section_Serial]->contentWidget());
    840     AssertMsg(pLabel, ("Content widget should be valid!"));
    841 
    842     /* Enable link: */
    843     block[Section_Serial]->setTitleLinkEnabled(m_changeable[iBlockNumber]);
    844 
    845     /* Update if content widget is visible: */
    846     if (pSender->isOpen())
    847     {
    848         if (!machine.isNull())
    849         {
    850             QString item;
    851 
    852             ulong count = m_vbox.GetSystemProperties().GetSerialPortCount();
    853             for (ulong slot = 0; slot < count; slot ++)
    854             {
    855                 const CSerialPort &port = machine.GetSerialPort(slot);
    856                 if (port.GetEnabled())
    857                 {
    858                     KPortMode mode = port.GetHostMode();
    859                     QString data = vboxGlobal().toCOMPortName(port.GetIRQ(), port.GetIOBase()) + ", ";
    860                     if (mode == KPortMode_HostPipe || mode == KPortMode_HostDevice || mode == KPortMode_RawFile)
    861                         data += QString("%1 (<nobr>%2</nobr>)").arg(vboxGlobal().toString(mode)).arg(QDir::toNativeSeparators(port.GetPath()));
    862                     else
    863                         data += vboxGlobal().toString(mode);
    864 
    865                     item += QString(sSectionItemTpl2).arg(tr("Port %1", "details report (serial ports)").arg(port.GetSlot() + 1))
    866                                                      .arg(data);
    867                 }
    868             }
    869             if (item.isNull())
    870                 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (serial ports)"));
    871 
    872             pLabel->setText(sTableTpl.arg(item));
    873         }
    874         else
    875             pLabel->clear();
    876     }
    877 }
    878 
    879 #ifdef VBOX_WITH_PARALLEL_PORTS
    880 void UIDetailsPagePrivate::sltUpdateParallelPorts()
    881 {
    882     /* Get current sender: */
    883     UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
    884     AssertMsg(pSender, ("Sender should be valid!\n"));
    885     /* Get current block number: */
    886     int iBlockNumber = pSender->property("block-number").toInt();
    887     /* Get current machine: */
    888     CMachine &machine = m_machines[iBlockNumber];
    889     AssertMsg(!machine.isNull(), ("Machine should be valid!\n"));
    890     /* Get details block: */
    891     UIDetailsBlock &block = *m_set[iBlockNumber];
    892     /* Get corresponding content widget: */
    893     QILabel *pLabel = qobject_cast<QILabel*>(block[Section_Parallel]->contentWidget());
    894     AssertMsg(pLabel, ("Content widget should be valid!"));
    895 
    896     /* Enable link: */
    897     block[Section_Parallel]->setTitleLinkEnabled(m_changeable[iBlockNumber]);
    898 
    899     /* Update if content widget is visible: */
    900     if (pSender->isOpen())
    901     {
    902         if (!machine.isNull())
    903         {
    904             QString item;
    905 
    906             ulong count = m_vbox.GetSystemProperties().GetParallelPortCount();
    907             for (ulong slot = 0; slot < count; slot ++)
    908             {
    909                 const CParallelPort &port = machine.GetParallelPort(slot);
    910                 if (port.GetEnabled())
    911                 {
    912                     QString data = vboxGlobal().toLPTPortName(port.GetIRQ(), port.GetIOBase()) +
    913                                    QString(" (<nobr>%1</nobr>)").arg(QDir::toNativeSeparators(port.GetPath()));
    914 
    915                     item += QString(sSectionItemTpl2).arg(tr("Port %1", "details report (parallel ports)").arg(port.GetSlot() + 1))
    916                                                      .arg(data);
    917                 }
    918             }
    919             if (item.isNull())
    920                 item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (parallel ports)"));
    921 
    922             pLabel->setText(sTableTpl.arg(item));
    923         }
    924         else
    925             pLabel->clear();
    926     }
    927 }
    928 #endif /* VBOX_WITH_PARALLEL_PORTS */
    929 
    930 void UIDetailsPagePrivate::sltUpdateUSB()
    931 {
    932     /* Get current sender: */
    933     UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
    934     AssertMsg(pSender, ("Sender should be valid!\n"));
    935     /* Get current block number: */
    936     int iBlockNumber = pSender->property("block-number").toInt();
    937     /* Get current machine: */
    938     CMachine &machine = m_machines[iBlockNumber];
    939     AssertMsg(!machine.isNull(), ("Machine should be valid!\n"));
    940     /* Get details block: */
    941     UIDetailsBlock &block = *m_set[iBlockNumber];
    942     /* Get corresponding content widget: */
    943     QILabel *pLabel = qobject_cast<QILabel*>(block[Section_USB]->contentWidget());
    944     AssertMsg(pLabel, ("Content widget should be valid!"));
    945 
    946     /* Enable link: */
    947     block[Section_USB]->setTitleLinkEnabled(m_changeable[iBlockNumber]);
    948 
    949     /* Update if content widget is visible: */
    950     if (pSender->isOpen())
    951     {
    952         if (!machine.isNull())
    953         {
    954             QString item;
    955 
    956             const CUSBController &ctl = machine.GetUSBController();
    957             if (!ctl.isNull() && ctl.GetProxyAvailable())
    958             {
    959                 m_fUSBAvailable = true;
    960                 /* The USB controller may be unavailable (i.e. in VirtualBox OSE): */
    961                 if (ctl.GetEnabled())
    962                 {
    963                     const CUSBDeviceFilterVector &coll = ctl.GetDeviceFilters();
    964                     uint active = 0;
    965                     for (int i = 0; i < coll.size(); ++i)
    966                         if (coll[i].GetActive())
    967                             ++active;
    968 
    969                     item = QString(sSectionItemTpl2).arg(tr("Device Filters", "details report (USB)"),
    970                                                          tr("%1 (%2 active)", "details report (USB)").arg(coll.size()).arg(active));
    971                 }
    972                 else
    973                     item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (USB)"));
    974 
    975                 pLabel->setText(sTableTpl.arg(item));
    976             }
    977             else
    978             {
    979                 m_fUSBAvailable = false;
    980                 /* Fully hide when USB is not available: */
    981                 block[Section_USB]->hide();
    982             }
    983         }
    984         else
    985             pLabel->clear();
    986     }
    987 }
    988 
    989 void UIDetailsPagePrivate::sltUpdateSharedFolders()
    990 {
    991     /* Get current sender: */
    992     UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
    993     AssertMsg(pSender, ("Sender should be valid!\n"));
    994     /* Get current block number: */
    995     int iBlockNumber = pSender->property("block-number").toInt();
    996     /* Get current machine: */
    997     CMachine &machine = m_machines[iBlockNumber];
    998     AssertMsg(!machine.isNull(), ("Machine should be valid!\n"));
    999     /* Get details block: */
    1000     UIDetailsBlock &block = *m_set[iBlockNumber];
    1001     /* Get corresponding content widget: */
    1002     QILabel *pLabel = qobject_cast<QILabel*>(block[Section_SharedFolders]->contentWidget());
    1003     AssertMsg(pLabel, ("Content widget should be valid!"));
    1004 
    1005     /* Enable link: */
    1006     block[Section_SharedFolders]->setTitleLinkEnabled(m_changeable[iBlockNumber]);
    1007 
    1008     /* Update if content widget is visible: */
    1009     if (pSender->isOpen())
    1010     {
    1011         if (!machine.isNull())
    1012         {
    1013             QString item;
    1014 
    1015             ulong count = machine.GetSharedFolders().size();
    1016             if (count > 0)
    1017             {
    1018                 item = QString(sSectionItemTpl2).arg(tr("Shared Folders", "details report (shared folders)")).arg(count);
    1019             }
    1020             else
    1021                 item = QString(sSectionItemTpl1).arg(tr("None", "details report (shared folders)"));
    1022 
    1023             pLabel->setText(sTableTpl.arg(item));
    1024         }
    1025         else
    1026             pLabel->clear();
    1027     }
    1028 }
    1029 
    1030 void UIDetailsPagePrivate::sltUpdateDescription()
    1031 {
    1032     /* Get current sender: */
    1033     UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
    1034     AssertMsg(pSender, ("Sender should be valid!\n"));
    1035     /* Get current block number: */
    1036     int iBlockNumber = pSender->property("block-number").toInt();
    1037     /* Get current machine: */
    1038     CMachine &machine = m_machines[iBlockNumber];
    1039     AssertMsg(!machine.isNull(), ("Machine should be valid!\n"));
    1040     /* Get details block: */
    1041     UIDetailsBlock &block = *m_set[iBlockNumber];
    1042     /* Get corresponding content widget: */
    1043     QILabel *pLabel = qobject_cast<QILabel*>(block[Section_Description]->contentWidget());
    1044     AssertMsg(pLabel, ("Content widget should be valid!"));
    1045 
    1046     /* Enable link: */
    1047     block[Section_Description]->setTitleLinkEnabled(m_changeable[iBlockNumber]);
    1048 
    1049     /* Update if content widget is visible: */
    1050     if (pSender->isOpen())
    1051     {
    1052         if (!machine.isNull())
    1053         {
    1054             QString item;
    1055             const QString &strDesc = machine.GetDescription();
    1056             if (!strDesc.isEmpty())
    1057                 item = QString(sSectionItemTpl4).arg(strDesc);
    1058             else
    1059                 item = QString(sSectionItemTpl1).arg(tr("None", "details report (description)"));
    1060 
    1061             pLabel->setText(sTableTpl.arg(item));
    1062         }
    1063         else
    1064             pLabel->clear();
    1065     }
    1066 }
    1067 
    1068 void UIDetailsPagePrivate::sltContextMenuRequested(const QPoint &pos)
    1069 {
    1070     /* Populate list of allowed actions: */
    1071     QList<QAction*> actions;
    1072     for (int i = 0; i < m_sections.size(); ++i)
    1073         actions << m_actions[m_sections[i]];
    1074     /* Restrict USB action if USB is NOT available: */
    1075     if (!m_fUSBAvailable)
    1076         actions.removeOne(m_actions[Section_USB]);
    1077     /* Popup menu to show/hide sections: */
    1078     QAction *pReturn = QMenu::exec(actions, m_pDetails->mapToGlobal(pos), 0);
    1079     /* If some action was toggled: */
    1080     if (pReturn)
    1081     {
    1082         /* Get corresponding section type: */
    1083         Section section = static_cast<Section>(pReturn->data().toInt());
    1084         /* Enumerate all the available blocks: */
    1085         for (int i = 0; i < m_cMachineCount; ++i)
    1086         {
    1087             /* Get current popup: */
    1088             UIPopupBox *pPopup = (*m_set[i])[section];
    1089             /* Show/hide popup if necessary: */
    1090             if (pReturn->isChecked())
    1091                 pPopup->show();
    1092             else
    1093                 pPopup->hide();
    1094         }
    1095     }
    1096 }
    1097 
    1098 void UIDetailsPagePrivate::sltPopupToggled(bool fPopupOpened)
    1099 {
    1100     /* Get current sender: */
    1101     UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
    1102     AssertMsg(pSender, ("Sender should be valid!\n"));
    1103     /* Get section type: */
    1104     Section section = static_cast<Section>(pSender->property("section-type").toInt());
    1105     /* Update the state of corresponding map: */
    1106     m_sectionOpened[section] = fPopupOpened;
    1107     /* Open/Close all the blocks: */
    1108     for (int i = 0; i < m_cMachineCount; ++i)
    1109         (*m_set[i])[section]->setOpen(fPopupOpened);
    1110 }
    1111 
    1112 void UIDetailsPagePrivate::prepareSet(bool fNew)
    1113 {
    1114     /* Do we need to create new set? */
    1115     if (fNew)
    1116     {
    1117         /* Which sections should be available: */
    1118         m_sections.clear();
    1119         if (m_cMachineCount == 1)
     359{
     360    /* Configure context menu policy: */
     361    setContextMenuPolicy(Qt::CustomContextMenu);
     362    connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(sltContextMenuRequested(const QPoint&)));
     363
     364    /* Create and configure main layout: */
     365    QVBoxLayout *pMainLayout = new QVBoxLayout(this);
     366    pMainLayout->setContentsMargins(gsLeftMargin, gsTopMargin, gsRightMargin, gsBottomMargin);
     367    pMainLayout->addStretch(1);
     368}
     369
     370void UIDetails::setMachines(const QList<CMachine> &machines)
     371{
     372    /* If details preparing is NOT yet started: */
     373    if (m_cBlockCount != machines.size())
     374    {
     375        /* Get new machine count: */
     376        m_cBlockCount = machines.size();
     377
     378        /* Populate list of available sections: */
     379        if (m_cBlockCount == 1)
    1120380        {
    1121381            m_sections << Section_General
     
    1127387                       << Section_Network
    1128388                       << Section_Serial
    1129     #ifdef VBOX_WITH_PARALLEL_PORTS
     389#ifdef VBOX_WITH_PARALLEL_PORTS
    1130390                       << Section_Parallel
    1131     #endif /* VBOX_WITH_PARALLEL_PORTS */
     391#endif /* VBOX_WITH_PARALLEL_PORTS */
    1132392                       << Section_USB
    1133393                       << Section_SharedFolders
     
    1140400                       << Section_Preview;
    1141401        }
    1142 
    1143         /* Recreate details set: */
    1144         m_set.clear();
    1145         m_set.resize(m_cMachineCount);
    1146 
    1147         /* Re-create details widget: */
    1148         if (m_pDetails)
    1149             delete m_pDetails;
    1150         m_pDetails = new QWidget(m_pScrollArea);
    1151         m_pScrollArea->setWidget(m_pDetails);
    1152         m_pDetails->setContextMenuPolicy(Qt::CustomContextMenu);
    1153         connect(m_pDetails, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(sltContextMenuRequested(const QPoint&)));
    1154         QVBoxLayout *pMainLayout = new QVBoxLayout(m_pDetails);
    1155         pMainLayout->setContentsMargins(gsLeftMargin, gsTopMargin, gsRightMargin, gsBottomMargin);
    1156         pMainLayout->addStretch(1);
    1157 
    1158         /* Generate new set id: */
    1159         m_currentRequestId = QUuid::createUuid();
    1160     }
    1161 
    1162     /* Prepare set content (blocks): */
    1163     QCoreApplication::postEvent(this, new UIEventForBlockUpdate(m_currentRequestId, 0, fNew /* recreate block? */));
    1164 }
    1165 
    1166 void UIDetailsPagePrivate::prepareBlock(int iBlockNumber, bool fNew)
    1167 {
    1168     /* Prepare block pointer: */
    1169     UIDetailsBlock *pBlock = 0;
    1170 
    1171     /* Do we need to create new block? */
    1172     if (fNew)
     402    }
     403
     404    /* Reset variables: */
     405    m_machines.clear();
     406    m_machines.resize(m_cBlockCount);
     407    m_accessibilities.clear();
     408    m_accessibilities.resize(m_cBlockCount);
     409    m_fUSBAvailable = true;
     410
     411    /* Fetch passed VMs: */
     412    for (int i = 0; i < machines.size(); ++i)
     413    {
     414        /* Get current VM: */
     415        const CMachine &machine = machines[i];
     416        /* Assign corresponding vector values: */
     417        m_machines[i] = machine;
     418        m_accessibilities[i] = machine.isNull() || !machine.GetAccessible() ? false :
     419                               machine.GetState() != KMachineState_Stuck &&
     420                               machine.GetState() != KMachineState_Saved /* for now! */;
     421    }
     422
     423    /* Start preparing details content (blocks): */
     424    QCoreApplication::postEvent(this, new UIEventDetailsPrepareStart);
     425}
     426
     427QAction* UIDetails::action(Section section) const
     428{
     429    return m_pUIDetailsPage->action(section);
     430}
     431
     432bool UIDetails::sectionOpened(Section section) const
     433{
     434    return m_pUIDetailsPage->sectionOpened(section);
     435}
     436
     437void UIDetails::setSectionOpened(Section section, bool fOpened)
     438{
     439    m_pUIDetailsPage->setSectionOpened(section, fOpened);
     440}
     441
     442void UIDetails::sltContextMenuRequested(const QPoint &pos)
     443{
     444    /* Populate list of allowed actions: */
     445    QList<QAction*> actions;
     446    for (int i = 0; i < m_sections.size(); ++i)
     447        actions << action(m_sections[i]);
     448    /* Restrict USB action if USB is NOT available: */
     449    if (!m_fUSBAvailable)
     450        actions.removeOne(action(Section_USB));
     451    /* Popup menu to show/hide sections: */
     452    QAction *pReturn = QMenu::exec(actions, mapToGlobal(pos), 0);
     453    /* If some action was toggled: */
     454    if (pReturn)
     455    {
     456        /* Get corresponding section type: */
     457        Section section = static_cast<Section>(pReturn->data().toInt());
     458        /* Enumerate all the available blocks: */
     459        for (int i = 0; i < m_cBlockCount; ++i)
     460        {
     461            /* Get current popup: */
     462            UIPopupBox *pPopup = (*m_details[i])[section];
     463            /* Show/hide popup if necessary: */
     464            if (pReturn->isChecked())
     465                pPopup->show();
     466            else
     467                pPopup->hide();
     468        }
     469    }
     470}
     471
     472void UIDetails::sltPopupToggled(bool fPopupOpened)
     473{
     474    /* Get current sender: */
     475    UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
     476    AssertMsg(pSender, ("Sender should be valid!\n"));
     477    /* Get section type: */
     478    Section section = static_cast<Section>(pSender->property("section-type").toInt());
     479    /* Update the state of corresponding map: */
     480    setSectionOpened(section, fPopupOpened);
     481    /* Open/Close all the blocks: */
     482    for (int i = 0; i < m_cBlockCount; ++i)
     483        (*m_details[i])[section]->setOpen(fPopupOpened);
     484}
     485
     486bool UIDetails::event(QEvent *pEvent)
     487{
     488    /* Handle special events: */
     489    switch (pEvent->type())
     490    {
     491        /* Handle details-prepare-start event: */
     492        case UIEventDetailsPrepareStart::Type:
     493        {
     494            /* Cast and accept event: */
     495            UIEventDetailsPrepareStart *pEventDetailsPrepareStart = static_cast<UIEventDetailsPrepareStart*>(pEvent);
     496            pEventDetailsPrepareStart->accept();
     497            /* Create request for the first block: */
     498            QCoreApplication::postEvent(this, new UIEventDetailsPrepareBlockStart(0));
     499            /* Finish processing: */
     500            return true;
     501        }
     502        /* Handle details-block-prepare-start event: */
     503        case UIEventDetailsPrepareBlockStart::Type:
     504        {
     505            /* Cast and accept event: */
     506            UIEventDetailsPrepareBlockStart *pEventDetailsBlockPrepareStart = static_cast<UIEventDetailsPrepareBlockStart*>(pEvent);
     507            pEventDetailsBlockPrepareStart->accept();
     508            /* Start preparing block: */
     509            createBlock(pEventDetailsBlockPrepareStart->blockNumber());
     510            /* Finish processing: */
     511            return true;
     512        }
     513        /* Handle details-block-prepare-finish event: */
     514        case UIEventDetailsPrepareBlockFinish::Type:
     515        {
     516            /* Cast and accept event: */
     517            UIEventDetailsPrepareBlockFinish *pEventDetailsBlockPrepareFinish = static_cast<UIEventDetailsPrepareBlockFinish*>(pEvent);
     518            pEventDetailsBlockPrepareFinish->accept();
     519            /* Finish preparing block: */
     520            layoutBlock(pEventDetailsBlockPrepareFinish->blockNumber());
     521            /* Create request for the next block if possible: */
     522            if (pEventDetailsBlockPrepareFinish->blockNumber() < m_cBlockCount - 1)
     523                QCoreApplication::postEvent(this, new UIEventDetailsPrepareBlockStart(pEventDetailsBlockPrepareFinish->blockNumber() + 1));
     524            /* Finish processing: */
     525            return true;
     526        }
     527        default:
     528            break;
     529    }
     530    /* Propagate to base-class: */
     531    return QWidget::event(pEvent);
     532}
     533
     534void UIDetails::createBlock(int iBlockNumber)
     535{
     536    /* If block creation is NOT yet started: */
     537    if (!m_details.contains(iBlockNumber))
    1173538    {
    1174539        /* Create new block: */
    1175         pBlock = m_set[iBlockNumber] = new UIDetailsBlock(m_pDetails);
     540        m_details[iBlockNumber] = new UIDetailsBlock(this, m_sections, iBlockNumber);
     541    }
     542
     543    /* Assign block with corresponding machine: */
     544    m_details[iBlockNumber]->setMachine(m_machines[iBlockNumber]);
     545}
     546
     547void UIDetails::layoutBlock(int iBlockNumber)
     548{
     549    /* Get current block: */
     550    UIDetailsBlock *pBlock = m_details[iBlockNumber];
     551
     552    /* If block layouting is NOT yet started: */
     553    if (!pBlock->layout())
     554    {
     555        /* Declare variables: */
    1176556        UIDetailsBlock &block = *pBlock;
    1177 
    1178         /* Prepare block content (sections): */
    1179         for(int i = 0; i < m_sections.size(); ++i)
    1180             prepareSection(block, iBlockNumber, m_sections[i]);
    1181557
    1182558        /* Layout block content: */
     
    1207583        if (m_sections.contains(Section_Serial))
    1208584            pContainerLayout->addWidget(block[Section_Serial]);
    1209     #ifdef VBOX_WITH_PARALLEL_PORTS
     585#ifdef VBOX_WITH_PARALLEL_PORTS
    1210586        if (m_sections.contains(Section_Parallel))
    1211587            pContainerLayout->addWidget(block[Section_Parallel]);
    1212     #endif /* VBOX_WITH_PARALLEL_PORTS */
     588#endif /* VBOX_WITH_PARALLEL_PORTS */
    1213589        if (m_sections.contains(Section_USB))
    1214590            pContainerLayout->addWidget(block[Section_USB]);
     
    1217593        if (m_sections.contains(Section_Description))
    1218594            pContainerLayout->addWidget(block[Section_Description]);
    1219         QVBoxLayout *pMainLayout = qobject_cast<QVBoxLayout*>(m_pDetails->layout());
     595        QVBoxLayout *pMainLayout = qobject_cast<QVBoxLayout*>(layout());
    1220596        pMainLayout->insertWidget(pMainLayout->count() - 1, pBlock);
    1221597
    1222         /* Configure created block: */
     598        /* Configure block content: */
    1223599        for (int i = 0; i < m_sections.size(); ++i)
    1224600        {
    1225601            /* Assign corresponding action text as section title: */
    1226             block[m_sections[i]]->setTitle(m_actions[m_sections[i]]->text());
     602            block[m_sections[i]]->setTitle(action(m_sections[i])->text());
    1227603
    1228604            /* If corresponding action is checked: */
    1229             if (m_actions[m_sections[i]]->isChecked())
     605            if (action(m_sections[i])->isChecked())
    1230606            {
    1231607                /* Unhide corresponding section: */
     
    1237613        block.show();
    1238614
    1239         /* Send and process layout request for the scroll-area: */
     615        /* Layout parent scroll-area: */
    1240616        QEvent layoutEvent(QEvent::LayoutRequest);
    1241         QCoreApplication::sendEvent(m_pScrollArea, &layoutEvent);
    1242     }
    1243     else
    1244     {
    1245         /* Get existing block: */
    1246         pBlock = m_set[iBlockNumber];
    1247         UIDetailsBlock &block = *pBlock;
    1248 
    1249         /* For every section of block: */
    1250         for (int i = 0; i < m_sections.size(); ++i)
    1251         {
    1252             /* Call for update: */
    1253             block[m_sections[i]]->callForUpdateContentWidget();
    1254         }
     617        QCoreApplication::sendEvent(parent(), &layoutEvent);
    1255618    }
    1256619
     
    1259622}
    1260623
    1261 void UIDetailsPagePrivate::prepareSection(UIDetailsBlock &block, int iBlockNumber, Section section)
    1262 {
    1263     /* Prepare new section (popup box): */
    1264     UIPopupBox *pPopup = block[section] = new UIPopupBox(&block);
    1265     pPopup->hide();
    1266     connect(pPopup, SIGNAL(titleClicked(const QString &)), this, SIGNAL(linkClicked(const QString &)));
    1267     connect(pPopup, SIGNAL(toggled(bool)), this, SLOT(sltPopupToggled(bool)));
    1268     pPopup->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    1269     pPopup->setProperty("block-number", iBlockNumber);
    1270     pPopup->setProperty("section-type", static_cast<int>(section));
    1271     if (!m_machines[iBlockNumber].GetAccessible())
    1272         pPopup->setWarningIcon(UIIconPool::iconSet(":/state_aborted_16px.png"));
    1273 
    1274     /* Configure the popup box: */
    1275     switch (section)
    1276     {
    1277         case Section_General:
    1278         {
    1279             QILabel *pLabel = new QILabel(pPopup);
    1280             pLabel->setWordWrap(true);
    1281             pPopup->setTitleIcon(UIIconPool::iconSet(":/machine_16px.png"));
    1282             pPopup->setTitleLink("#general");
    1283             pPopup->setContentWidget(pLabel);
    1284             connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateGeneral()));
    1285             break;
    1286         }
    1287         case Section_System:
    1288         {
    1289             QILabel *pLabel = new QILabel(pPopup);
    1290             pLabel->setWordWrap(true);
    1291             pPopup->setTitleIcon(UIIconPool::iconSet(":/chipset_16px.png"));
    1292             pPopup->setTitleLink("#system");
    1293             pPopup->setContentWidget(pLabel);
    1294             connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateSystem()));
    1295             break;
    1296         }
    1297         case Section_Preview:
    1298         {
    1299             UIVMPreviewWindow *pWidget = new UIVMPreviewWindow(pPopup);
    1300             pPopup->setTitleIcon(UIIconPool::iconSet(":/machine_16px.png"));
    1301             pPopup->setContentWidget(pWidget);
    1302             pPopup->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    1303             /* Make sure the width is always the same, regardless if the preview is shown or not: */
    1304             pPopup->setFixedWidth(pPopup->sizeHint().width());
    1305             pWidget->updateGeometry();
    1306             connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdatePreview()));
    1307             break;
    1308         }
    1309         case Section_Display:
    1310         {
    1311             QILabel *pLabel = new QILabel(pPopup);
    1312             pLabel->setWordWrap(true);
    1313             pPopup->setTitleIcon(UIIconPool::iconSet(":/vrdp_16px.png"));
    1314             pPopup->setTitleLink("#display");
    1315             pPopup->setContentWidget(pLabel);
    1316             connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateDisplay()));
    1317             break;
    1318         }
    1319         case Section_Storage:
    1320         {
    1321             QILabel *pLabel = new QILabel(pPopup);
    1322             pLabel->setWordWrap(true);
    1323             pPopup->setTitleIcon(UIIconPool::iconSet(":/attachment_16px.png"));
    1324             pPopup->setTitleLink("#storage");
    1325             pPopup->setContentWidget(pLabel);
    1326             connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateStorage()));
    1327             break;
    1328         }
    1329         case Section_Audio:
    1330         {
    1331             QILabel *pLabel = new QILabel(pPopup);
    1332             pLabel->setWordWrap(true);
    1333             pPopup->setTitleIcon(UIIconPool::iconSet(":/sound_16px.png"));
    1334             pPopup->setTitleLink("#audio");
    1335             pPopup->setContentWidget(pLabel);
    1336             connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateAudio()));
    1337             break;
    1338         }
    1339         case Section_Network:
    1340         {
    1341             QILabel *pLabel = new QILabel(pPopup);
    1342             pLabel->setWordWrap(true);
    1343             pPopup->setTitleIcon(UIIconPool::iconSet(":/nw_16px.png"));
    1344             pPopup->setTitleLink("#network");
    1345             pPopup->setContentWidget(pLabel);
    1346             connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateNetwork()));
    1347             break;
    1348         }
    1349         case Section_Serial:
    1350         {
    1351             QILabel *pLabel = new QILabel(pPopup);
    1352             pLabel->setWordWrap(true);
    1353             pPopup->setTitleIcon(UIIconPool::iconSet(":/serial_port_16px.png"));
    1354             pPopup->setTitleLink("#serialPorts");
    1355             pPopup->setContentWidget(pLabel);
    1356             connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateSerialPorts()));
    1357             break;
    1358         }
     624UIDetailsBlock::UIDetailsBlock(UIDetails *pParent, const QList<Section> &sections, int iBlockNumber)
     625    : QWidget(pParent)
     626    , m_vbox(vboxGlobal().virtualBox())
     627    , m_pUIDetails(pParent)
     628    , m_iBlockNumber(iBlockNumber)
     629    , m_cSectionCount(0)
     630    , m_sections(sections)
     631{
     632}
     633
     634void UIDetailsBlock::setMachine(const CMachine &machine)
     635{
     636    /* If block preparing is NOT yet started: */
     637    if (m_cSectionCount != m_sections.size())
     638    {
     639        /* Get new section count: */
     640        m_cSectionCount = m_sections.size();
     641    }
     642
     643    /* Set passed VM: */
     644    m_machine = machine;
     645
     646    /* Start preparing details block content (sections): */
     647    QCoreApplication::postEvent(this, new UIEventDetailsBlockPrepareStart);
     648}
     649
     650bool UIDetailsBlock::accessibility() const
     651{
     652    return m_pUIDetails->accessibility(m_iBlockNumber);
     653}
     654
     655bool UIDetailsBlock::sectionOpened(Section section) const
     656{
     657    return m_pUIDetails->sectionOpened(section);
     658}
     659
     660void UIDetailsBlock::setUSBAvailable(bool fAvailable)
     661{
     662    m_pUIDetails->setUSBAvailable(fAvailable);
     663}
     664
     665void UIDetailsBlock::sltUpdateGeneral()
     666{
     667    /* Get current sender: */
     668    UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
     669    AssertMsg(pSender, ("Sender should be valid!\n"));
     670    /* Get corresponding content widget: */
     671    QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_General]->contentWidget());
     672    AssertMsg(pLabel, ("Content widget should be valid!"));
     673
     674    /* Enable link: */
     675    m_block[Section_General]->setTitleLinkEnabled(accessibility());
     676
     677    /* Update if content widget is visible: */
     678    if (pSender->isOpen())
     679    {
     680        if (!m_machine.isNull())
     681        {
     682            QString item;
     683            if (m_machine.GetAccessible())
     684            {
     685                item = sSectionItemTpl2.arg(tr("Name", "details report"), m_machine.GetName())
     686                     + sSectionItemTpl2.arg(tr("OS Type", "details report"), vboxGlobal().vmGuestOSTypeDescription(m_machine.GetOSTypeId()));
     687            }
     688            else
     689            {
     690                item = QString(sSectionItemTpl1).arg(tr("Information inaccessible", "details report"));
     691            }
     692            pLabel->setText(sTableTpl.arg(item));
     693        }
     694        else
     695            pLabel->clear();
     696    }
     697}
     698
     699void UIDetailsBlock::sltUpdateSystem()
     700{
     701    /* Get current sender: */
     702    UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
     703    AssertMsg(pSender, ("Sender should be valid!\n"));
     704    /* Get corresponding content widget: */
     705    QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_System]->contentWidget());
     706    AssertMsg(pLabel, ("Content widget should be valid!"));
     707
     708    /* Enable link: */
     709    m_block[Section_System]->setTitleLinkEnabled(accessibility());
     710
     711    /* Update if content widget is visible: */
     712    if (pSender->isOpen())
     713    {
     714        if (!m_machine.isNull())
     715        {
     716            QString item;
     717            if (m_machine.GetAccessible())
     718            {
     719                item = sSectionItemTpl2.arg(tr("Base Memory", "details report"), tr("<nobr>%1 MB</nobr>", "details report"))
     720                                       .arg(m_machine.GetMemorySize());
     721
     722                int cCPU = m_machine.GetCPUCount();
     723                if (cCPU > 1)
     724                    item += sSectionItemTpl2.arg(tr("Processors", "details report"), tr("<nobr>%1</nobr>", "details report"))
     725                                            .arg(cCPU);
     726
     727                int iCPUExecCap = m_machine.GetCPUExecutionCap();
     728                if (iCPUExecCap < 100)
     729                    item += sSectionItemTpl2.arg(tr("Execution Cap", "details report"), tr("<nobr>%1%</nobr>", "details report"))
     730                                            .arg(iCPUExecCap);
     731
     732                /* Boot order: */
     733                QStringList bootOrder;
     734                for (ulong i = 1; i <= m_vbox.GetSystemProperties().GetMaxBootPosition(); ++i)
     735                {
     736                    KDeviceType device = m_machine.GetBootOrder(i);
     737                    if (device == KDeviceType_Null)
     738                        continue;
     739                    bootOrder << vboxGlobal().toString(device);
     740                }
     741                if (bootOrder.isEmpty())
     742                    bootOrder << vboxGlobal().toString(KDeviceType_Null);
     743
     744                item += sSectionItemTpl2.arg(tr("Boot Order", "details report"), bootOrder.join(", "));
     745
     746#ifdef VBOX_WITH_FULL_DETAILS_REPORT
     747                /* BIOS Settings holder: */
     748                const CBIOSSettings &biosSettings = m_machine.GetBIOSSettings();
     749                QStringList bios;
     750
     751                /* ACPI: */
     752                if (biosSettings.GetACPIEnabled())
     753                    bios << tr("ACPI", "details report");
     754
     755                /* IO APIC: */
     756                if (biosSettings.GetIOAPICEnabled())
     757                    bios << tr("IO APIC", "details report");
     758
     759                if (!bios.isEmpty())
     760                    item += sSectionItemTpl2.arg(tr("BIOS", "details report"), bios.join(", "));
     761#endif /* VBOX_WITH_FULL_DETAILS_REPORT */
     762
     763                QStringList accel;
     764                if (m_vbox.GetHost().GetProcessorFeature(KProcessorFeature_HWVirtEx))
     765                {
     766                    /* VT-x/AMD-V: */
     767                    if (m_machine.GetHWVirtExProperty(KHWVirtExPropertyType_Enabled))
     768                    {
     769                        accel << tr("VT-x/AMD-V", "details report");
     770
     771                        /* Nested Paging (only when hw virt is enabled): */
     772                        if (m_machine.GetHWVirtExProperty(KHWVirtExPropertyType_NestedPaging))
     773                            accel << tr("Nested Paging", "details report");
     774                    }
     775                }
     776
     777                /* PAE/NX: */
     778                if (m_machine.GetCPUProperty(KCPUPropertyType_PAE))
     779                    accel << tr("PAE/NX", "details report");
     780
     781                if (!accel.isEmpty())
     782                    item += sSectionItemTpl2.arg(tr("Acceleration", "details report"), accel.join(", "));
     783            }
     784            else
     785            {
     786                item = QString(sSectionItemTpl1).arg(tr("Information inaccessible", "details report"));
     787            }
     788            pLabel->setText(sTableTpl.arg(item));
     789        }
     790        else
     791            pLabel->clear();
     792    }
     793}
     794
     795void UIDetailsBlock::sltUpdatePreview()
     796{
     797    /* Get current sender: */
     798    UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
     799    AssertMsg(pSender, ("Sender should be valid!\n"));
     800    /* Get corresponding content widget: */
     801    UIVMPreviewWindow *pPreview = qobject_cast<UIVMPreviewWindow*>(m_block[Section_Preview]->contentWidget());
     802    AssertMsg(pPreview, ("Content widget should be valid!"));
     803
     804    /* Update if content widget is visible: */
     805    if (pSender->isOpen())
     806    {
     807        /* Update preview widget: */
     808        pPreview->setMachine(m_machine);
     809    }
     810}
     811
     812void UIDetailsBlock::sltUpdateDisplay()
     813{
     814    /* Get current sender: */
     815    UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
     816    AssertMsg(pSender, ("Sender should be valid!\n"));
     817    /* Get corresponding content widget: */
     818    QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Display]->contentWidget());
     819    AssertMsg(pLabel, ("Content widget should be valid!"));
     820
     821    /* Enable link: */
     822    m_block[Section_Display]->setTitleLinkEnabled(accessibility());
     823
     824    /* Update if content widget is visible: */
     825    if (pSender->isOpen())
     826    {
     827        if (!m_machine.isNull())
     828        {
     829            /* Video tab: */
     830            QString item = QString(sSectionItemTpl2).arg(tr("Video Memory", "details report"), tr("<nobr>%1 MB</nobr>", "details report"))
     831                                                    .arg(m_machine.GetVRAMSize());
     832
     833            int cGuestScreens = m_machine.GetMonitorCount();
     834            if (cGuestScreens > 1)
     835                item += QString(sSectionItemTpl2).arg(tr("Screens", "details report")).arg(cGuestScreens);
     836
     837            QStringList accel;
     838#ifdef VBOX_WITH_VIDEOHWACCEL
     839            if (m_machine.GetAccelerate2DVideoEnabled())
     840                accel << tr("2D Video", "details report");
     841#endif /* VBOX_WITH_VIDEOHWACCEL */
     842            if (m_machine.GetAccelerate3DEnabled())
     843                accel << tr("3D", "details report");
     844
     845            if (!accel.isEmpty())
     846                item += sSectionItemTpl2.arg(tr("Acceleration", "details report"), accel.join(", "));
     847
     848            /* VRDE tab: */
     849            CVRDEServer srv = m_machine.GetVRDEServer();
     850            if (!srv.isNull())
     851            {
     852                if (srv.GetEnabled())
     853                    item += QString(sSectionItemTpl2).arg(tr("Remote Desktop Server Port", "details report (VRDE Server)"))
     854                                                     .arg(srv.GetVRDEProperty("TCP/Ports"));
     855                else
     856                    item += QString(sSectionItemTpl2).arg(tr("Remote Desktop Server", "details report (VRDE Server)"))
     857                                                     .arg(tr("Disabled", "details report (VRDE Server)"));
     858            }
     859
     860            pLabel->setText(sTableTpl.arg(item));
     861        }
     862        else
     863            pLabel->clear();
     864    }
     865}
     866
     867void UIDetailsBlock::sltUpdateStorage()
     868{
     869    /* Get current sender: */
     870    UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
     871    AssertMsg(pSender, ("Sender should be valid!\n"));
     872    /* Get corresponding content widget: */
     873    QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Storage]->contentWidget());
     874    AssertMsg(pLabel, ("Content widget should be valid!"));
     875
     876    /* Enable link: */
     877    m_block[Section_Storage]->setTitleLinkEnabled(accessibility());
     878
     879    /* Update if content widget is visible: */
     880    if (pSender->isOpen())
     881    {
     882        if (!m_machine.isNull())
     883        {
     884            QString item;
     885            /* Iterate over the all m_machine controllers: */
     886            const CStorageControllerVector &controllers = m_machine.GetStorageControllers();
     887            for (int i = 0; i < controllers.size(); ++i)
     888            {
     889                /* Get current controller: */
     890                const CStorageController &controller = controllers[i];
     891                /* Add controller information: */
     892                item += QString(sSectionItemTpl3).arg(controller.GetName());
     893
     894                /* Populate sorted map with attachments information: */
     895                QMap<StorageSlot,QString> attachmentsMap;
     896                const CMediumAttachmentVector &attachments = m_machine.GetMediumAttachmentsOfController(controller.GetName());
     897                for (int j = 0; j < attachments.size(); ++j)
     898                {
     899                    /* Get current attachment: */
     900                    const CMediumAttachment &attachment = attachments[j];
     901                    /* Prepare current storage slot: */
     902                    StorageSlot attachmentSlot(controller.GetBus(), attachment.GetPort(), attachment.GetDevice());
     903                    /* Append 'device slot name' with 'device type name' for CD/DVD devices only: */
     904                    QString strDeviceType = attachment.GetType() == KDeviceType_DVD ? tr("(CD/DVD)") : QString();
     905                    if (!strDeviceType.isNull())
     906                        strDeviceType.prepend(' ');
     907                    /* Prepare current medium object: */
     908                    const CMedium &medium = attachment.GetMedium();
     909                    /* Prepare information about current medium & attachment: */
     910                    QString strAttachmentInfo = !attachment.isOk() ? QString() :
     911                                                QString(sSectionItemTpl2)
     912                                                .arg(QString("&nbsp;&nbsp;") +
     913                                                     vboxGlobal().toString(StorageSlot(controller.GetBus(),
     914                                                                                       attachment.GetPort(),
     915                                                                                       attachment.GetDevice())) +
     916                                                     strDeviceType)
     917                                                .arg(vboxGlobal().details(medium, false));
     918                    /* Insert that attachment into map: */
     919                    if (!strAttachmentInfo.isNull())
     920                        attachmentsMap.insert(attachmentSlot, strAttachmentInfo);
     921                }
     922
     923                /* Iterate over the sorted map with attachments information: */
     924                QMapIterator<StorageSlot,QString> it(attachmentsMap);
     925                while (it.hasNext())
     926                {
     927                    /* Add controller information: */
     928                    it.next();
     929                    item += it.value();
     930                }
     931            }
     932
     933            if (item.isNull())
     934                item = QString(sSectionItemTpl1).arg(tr("Not Attached", "details report (Storage)"));
     935
     936            pLabel->setText(sTableTpl.arg(item));
     937        }
     938        else
     939            pLabel->clear();
     940    }
     941}
     942
     943void UIDetailsBlock::sltUpdateAudio()
     944{
     945    /* Get current sender: */
     946    UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
     947    AssertMsg(pSender, ("Sender should be valid!\n"));
     948    /* Get corresponding content widget: */
     949    QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Audio]->contentWidget());
     950    AssertMsg(pLabel, ("Content widget should be valid!"));
     951
     952    /* Enable link: */
     953    m_block[Section_Audio]->setTitleLinkEnabled(accessibility());
     954
     955    /* Update if content widget is visible: */
     956    if (pSender->isOpen())
     957    {
     958        if (!m_machine.isNull())
     959        {
     960            QString item;
     961
     962            const CAudioAdapter &audio = m_machine.GetAudioAdapter();
     963            if (audio.GetEnabled())
     964                item = QString(sSectionItemTpl2).arg(tr("Host Driver", "details report (audio)"),
     965                                                     vboxGlobal().toString(audio.GetAudioDriver())) +
     966                       QString(sSectionItemTpl2).arg(tr("Controller", "details report (audio)"),
     967                                                     vboxGlobal().toString(audio.GetAudioController()));
     968            else
     969                item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (audio)"));
     970
     971            pLabel->setText(sTableTpl.arg(item));
     972        }
     973        else
     974            pLabel->clear();
     975    }
     976}
     977
     978void UIDetailsBlock::sltUpdateNetwork()
     979{
     980    /* Get current sender: */
     981    UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
     982    AssertMsg(pSender, ("Sender should be valid!\n"));
     983    /* Get corresponding content widget: */
     984    QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Network]->contentWidget());
     985    AssertMsg(pLabel, ("Content widget should be valid!"));
     986
     987    /* Enable link: */
     988    m_block[Section_Network]->setTitleLinkEnabled(accessibility());
     989
     990    /* Update if content widget is visible: */
     991    if (pSender->isOpen())
     992    {
     993        if (!m_machine.isNull())
     994        {
     995            QString item;
     996
     997            ulong count = m_vbox.GetSystemProperties().GetMaxNetworkAdapters(KChipsetType_PIIX3);
     998            for (ulong slot = 0; slot < count; slot ++)
     999            {
     1000                const CNetworkAdapter &adapter = m_machine.GetNetworkAdapter(slot);
     1001                if (adapter.GetEnabled())
     1002                {
     1003                    KNetworkAttachmentType type = adapter.GetAttachmentType();
     1004                    QString attType = vboxGlobal().toString(adapter.GetAdapterType())
     1005                                      .replace(QRegExp("\\s\\(.+\\)"), " (%1)");
     1006                    /* Don't use the adapter type string for types that have
     1007                     * an additional symbolic network/interface name field,
     1008                     * use this name instead: */
     1009                    if (type == KNetworkAttachmentType_Bridged)
     1010                        attType = attType.arg(tr("Bridged adapter, %1", "details report (network)").arg(adapter.GetBridgedInterface()));
     1011                    else if (type == KNetworkAttachmentType_Internal)
     1012                        attType = attType.arg(tr("Internal network, '%1'", "details report (network)").arg(adapter.GetInternalNetwork()));
     1013                    else if (type == KNetworkAttachmentType_HostOnly)
     1014                        attType = attType.arg(tr("Host-only adapter, '%1'", "details report (network)").arg(adapter.GetHostOnlyInterface()));
     1015                    else if (type == KNetworkAttachmentType_Generic)
     1016                    {
     1017                        QString strGenericDriverProperties(summarizeGenericProperties(adapter));
     1018                        attType = strGenericDriverProperties.isNull() ?
     1019                                  attType.arg(tr("Generic driver, '%1'", "details report (network)").arg(adapter.GetGenericDriver())) :
     1020                                  attType.arg(tr("Generic driver, '%1' {&nbsp;%2&nbsp;}", "details report (network)")
     1021                                              .arg(adapter.GetGenericDriver(), strGenericDriverProperties));
     1022                    }
     1023                    else
     1024                        attType = attType.arg(vboxGlobal().toString(type));
     1025
     1026                    item += QString(sSectionItemTpl2).arg(tr("Adapter %1", "details report (network)").arg(adapter.GetSlot() + 1))
     1027                                                     .arg(attType);
     1028                }
     1029            }
     1030            if (item.isNull())
     1031                item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (network)"));
     1032
     1033            pLabel->setText(sTableTpl.arg(item));
     1034        }
     1035        else
     1036            pLabel->clear();
     1037    }
     1038}
     1039
     1040void UIDetailsBlock::sltUpdateSerialPorts()
     1041{
     1042    /* Get current sender: */
     1043    UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
     1044    AssertMsg(pSender, ("Sender should be valid!\n"));
     1045    /* Get corresponding content widget: */
     1046    QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Serial]->contentWidget());
     1047    AssertMsg(pLabel, ("Content widget should be valid!"));
     1048
     1049    /* Enable link: */
     1050    m_block[Section_Serial]->setTitleLinkEnabled(accessibility());
     1051
     1052    /* Update if content widget is visible: */
     1053    if (pSender->isOpen())
     1054    {
     1055        if (!m_machine.isNull())
     1056        {
     1057            QString item;
     1058
     1059            ulong count = m_vbox.GetSystemProperties().GetSerialPortCount();
     1060            for (ulong slot = 0; slot < count; slot ++)
     1061            {
     1062                const CSerialPort &port = m_machine.GetSerialPort(slot);
     1063                if (port.GetEnabled())
     1064                {
     1065                    KPortMode mode = port.GetHostMode();
     1066                    QString data = vboxGlobal().toCOMPortName(port.GetIRQ(), port.GetIOBase()) + ", ";
     1067                    if (mode == KPortMode_HostPipe || mode == KPortMode_HostDevice || mode == KPortMode_RawFile)
     1068                        data += QString("%1 (<nobr>%2</nobr>)").arg(vboxGlobal().toString(mode)).arg(QDir::toNativeSeparators(port.GetPath()));
     1069                    else
     1070                        data += vboxGlobal().toString(mode);
     1071
     1072                    item += QString(sSectionItemTpl2).arg(tr("Port %1", "details report (serial ports)").arg(port.GetSlot() + 1))
     1073                                                     .arg(data);
     1074                }
     1075            }
     1076            if (item.isNull())
     1077                item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (serial ports)"));
     1078
     1079            pLabel->setText(sTableTpl.arg(item));
     1080        }
     1081        else
     1082            pLabel->clear();
     1083    }
     1084}
     1085
    13591086#ifdef VBOX_WITH_PARALLEL_PORTS
    1360         case Section_Parallel:
    1361         {
    1362             QILabel *pLabel = new QILabel(pPopup);
    1363             pLabel->setWordWrap(true);
    1364             pPopup->setTitleIcon(UIIconPool::iconSet(":/parallel_port_16px.png"));
    1365             pPopup->setTitleLink("#parallelPorts");
    1366             pPopup->setContentWidget(pLabel);
    1367             connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateParallelPorts()));
    1368             break;
    1369         }
     1087void UIDetailsBlock::sltUpdateParallelPorts()
     1088{
     1089    /* Get current sender: */
     1090    UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
     1091    AssertMsg(pSender, ("Sender should be valid!\n"));
     1092    /* Get corresponding content widget: */
     1093    QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Parallel]->contentWidget());
     1094    AssertMsg(pLabel, ("Content widget should be valid!"));
     1095
     1096    /* Enable link: */
     1097    m_block[Section_Parallel]->setTitleLinkEnabled(accessibility());
     1098
     1099    /* Update if content widget is visible: */
     1100    if (pSender->isOpen())
     1101    {
     1102        if (!m_machine.isNull())
     1103        {
     1104            QString item;
     1105
     1106            ulong count = m_vbox.GetSystemProperties().GetParallelPortCount();
     1107            for (ulong slot = 0; slot < count; slot ++)
     1108            {
     1109                const CParallelPort &port = m_machine.GetParallelPort(slot);
     1110                if (port.GetEnabled())
     1111                {
     1112                    QString data = vboxGlobal().toLPTPortName(port.GetIRQ(), port.GetIOBase()) +
     1113                                   QString(" (<nobr>%1</nobr>)").arg(QDir::toNativeSeparators(port.GetPath()));
     1114
     1115                    item += QString(sSectionItemTpl2).arg(tr("Port %1", "details report (parallel ports)").arg(port.GetSlot() + 1))
     1116                                                     .arg(data);
     1117                }
     1118            }
     1119            if (item.isNull())
     1120                item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (parallel ports)"));
     1121
     1122            pLabel->setText(sTableTpl.arg(item));
     1123        }
     1124        else
     1125            pLabel->clear();
     1126    }
     1127}
    13701128#endif /* VBOX_WITH_PARALLEL_PORTS */
    1371         case Section_USB:
    1372         {
    1373             QILabel *pLabel = new QILabel(pPopup);
    1374             pLabel->setWordWrap(true);
    1375             pPopup->setTitleIcon(UIIconPool::iconSet(":/usb_16px.png"));
    1376             pPopup->setTitleLink("#usb");
    1377             pPopup->setContentWidget(pLabel);
    1378             connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateUSB()));
    1379             break;
    1380         }
    1381         case Section_SharedFolders:
    1382         {
    1383             QILabel *pLabel = new QILabel(pPopup);
    1384             pLabel->setWordWrap(true);
    1385             pPopup->setTitleIcon(UIIconPool::iconSet(":/shared_folder_16px.png"));
    1386             pPopup->setTitleLink("#sfolders");
    1387             pPopup->setContentWidget(pLabel);
    1388             connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateSharedFolders()));
    1389             break;
    1390         }
    1391         case Section_Description:
    1392         {
    1393             QILabel *pLabel = new QILabel(pPopup);
    1394             pLabel->setWordWrap(true);
    1395             pPopup->setTitleIcon(UIIconPool::iconSet(":/description_16px.png"));
    1396             pPopup->setTitleLink("#general%%mTeDescription");
    1397             pPopup->setContentWidget(pLabel);
    1398             connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateDescription()));
    1399             break;
     1129
     1130void UIDetailsBlock::sltUpdateUSB()
     1131{
     1132    /* Get current sender: */
     1133    UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
     1134    AssertMsg(pSender, ("Sender should be valid!\n"));
     1135    /* Get corresponding content widget: */
     1136    QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_USB]->contentWidget());
     1137    AssertMsg(pLabel, ("Content widget should be valid!"));
     1138
     1139    /* Enable link: */
     1140    m_block[Section_USB]->setTitleLinkEnabled(accessibility());
     1141
     1142    /* Update if content widget is visible: */
     1143    if (pSender->isOpen())
     1144    {
     1145        if (!m_machine.isNull())
     1146        {
     1147            QString item;
     1148
     1149            const CUSBController &ctl = m_machine.GetUSBController();
     1150            if (!ctl.isNull() && ctl.GetProxyAvailable())
     1151            {
     1152                setUSBAvailable(true);
     1153                /* The USB controller may be unavailable (i.e. in VirtualBox OSE): */
     1154                if (ctl.GetEnabled())
     1155                {
     1156                    const CUSBDeviceFilterVector &coll = ctl.GetDeviceFilters();
     1157                    uint active = 0;
     1158                    for (int i = 0; i < coll.size(); ++i)
     1159                        if (coll[i].GetActive())
     1160                            ++active;
     1161
     1162                    item = QString(sSectionItemTpl2).arg(tr("Device Filters", "details report (USB)"),
     1163                                                         tr("%1 (%2 active)", "details report (USB)").arg(coll.size()).arg(active));
     1164                }
     1165                else
     1166                    item = QString(sSectionItemTpl1).arg(tr("Disabled", "details report (USB)"));
     1167
     1168                pLabel->setText(sTableTpl.arg(item));
     1169            }
     1170            else
     1171            {
     1172                setUSBAvailable(false);
     1173                /* Fully hide when USB is not available: */
     1174                m_block[Section_USB]->hide();
     1175            }
     1176        }
     1177        else
     1178            pLabel->clear();
     1179    }
     1180}
     1181
     1182void UIDetailsBlock::sltUpdateSharedFolders()
     1183{
     1184    /* Get current sender: */
     1185    UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
     1186    AssertMsg(pSender, ("Sender should be valid!\n"));
     1187    /* Get corresponding content widget: */
     1188    QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_SharedFolders]->contentWidget());
     1189    AssertMsg(pLabel, ("Content widget should be valid!"));
     1190
     1191    /* Enable link: */
     1192    m_block[Section_SharedFolders]->setTitleLinkEnabled(accessibility());
     1193
     1194    /* Update if content widget is visible: */
     1195    if (pSender->isOpen())
     1196    {
     1197        if (!m_machine.isNull())
     1198        {
     1199            QString item;
     1200
     1201            ulong count = m_machine.GetSharedFolders().size();
     1202            if (count > 0)
     1203            {
     1204                item = QString(sSectionItemTpl2).arg(tr("Shared Folders", "details report (shared folders)")).arg(count);
     1205            }
     1206            else
     1207                item = QString(sSectionItemTpl1).arg(tr("None", "details report (shared folders)"));
     1208
     1209            pLabel->setText(sTableTpl.arg(item));
     1210        }
     1211        else
     1212            pLabel->clear();
     1213    }
     1214}
     1215
     1216void UIDetailsBlock::sltUpdateDescription()
     1217{
     1218    /* Get current sender: */
     1219    UIPopupBox *pSender = sender() && sender()->inherits("UIPopupBox") ? qobject_cast<UIPopupBox*>(sender()) : 0;
     1220    AssertMsg(pSender, ("Sender should be valid!\n"));
     1221    /* Get corresponding content widget: */
     1222    QILabel *pLabel = qobject_cast<QILabel*>(m_block[Section_Description]->contentWidget());
     1223    AssertMsg(pLabel, ("Content widget should be valid!"));
     1224
     1225    /* Enable link: */
     1226    m_block[Section_Description]->setTitleLinkEnabled(accessibility());
     1227
     1228    /* Update if content widget is visible: */
     1229    if (pSender->isOpen())
     1230    {
     1231        if (!m_machine.isNull())
     1232        {
     1233            QString item;
     1234            const QString &strDesc = m_machine.GetDescription();
     1235            if (!strDesc.isEmpty())
     1236                item = QString(sSectionItemTpl4).arg(strDesc);
     1237            else
     1238                item = QString(sSectionItemTpl1).arg(tr("None", "details report (description)"));
     1239
     1240            pLabel->setText(sTableTpl.arg(item));
     1241        }
     1242        else
     1243            pLabel->clear();
     1244    }
     1245}
     1246
     1247bool UIDetailsBlock::event(QEvent *pEvent)
     1248{
     1249    /* Handle special events: */
     1250    switch (pEvent->type())
     1251    {
     1252        /* Handle details-block-prepare-start event: */
     1253        case UIEventDetailsBlockPrepareStart::Type:
     1254        {
     1255            /* Cast and accept event: */
     1256            UIEventDetailsBlockPrepareStart *pEventDetailsBlockPrepareStart = static_cast<UIEventDetailsBlockPrepareStart*>(pEvent);
     1257            pEventDetailsBlockPrepareStart->accept();
     1258            /* Create request for the first section: */
     1259            QCoreApplication::postEvent(this, new UIEventDetailsBlockPrepareSectionStart(0));
     1260            /* Finish processing: */
     1261            return true;
     1262        }
     1263        /* Handle details-block-section-prepare-start event: */
     1264        case UIEventDetailsBlockPrepareSectionStart::Type:
     1265        {
     1266            /* Cast and accept event: */
     1267            UIEventDetailsBlockPrepareSectionStart *pEventDetailsBlockPrepareSectionStart = static_cast<UIEventDetailsBlockPrepareSectionStart*>(pEvent);
     1268            pEventDetailsBlockPrepareSectionStart->accept();
     1269            /* Preparing section: */
     1270            createSection(pEventDetailsBlockPrepareSectionStart->sectionNumber());
     1271            /* Create request to finish current section: */
     1272            QCoreApplication::postEvent(this, new UIEventDetailsBlockPrepareSectionFinish(pEventDetailsBlockPrepareSectionStart->sectionNumber()));
     1273            /* Finish processing: */
     1274            return true;
     1275        }
     1276        /* Handle details-block-section-prepare-finish event: */
     1277        case UIEventDetailsBlockPrepareSectionFinish::Type:
     1278        {
     1279            /* Cast and accept event: */
     1280            UIEventDetailsBlockPrepareSectionFinish *pEventDetailsBlockPrepareSectionFinish = static_cast<UIEventDetailsBlockPrepareSectionFinish*>(pEvent);
     1281            pEventDetailsBlockPrepareSectionFinish->accept();
     1282            if (pEventDetailsBlockPrepareSectionFinish->sectionNumber() < m_sections.size() - 1)
     1283            {
     1284                /* Create request for the next section: */
     1285                QCoreApplication::postEvent(this, new UIEventDetailsBlockPrepareSectionStart(pEventDetailsBlockPrepareSectionFinish->sectionNumber() + 1));
     1286            }
     1287            else
     1288            {
     1289                /* Create reply for the current block: */
     1290                QCoreApplication::postEvent(parent(), new UIEventDetailsPrepareBlockFinish(m_iBlockNumber));
     1291            }
     1292            /* Finish processing: */
     1293            return true;
    14001294        }
    14011295        default:
    14021296            break;
    14031297    }
    1404 
    1405     /* Open/close section if necessary: */
    1406     pPopup->setOpen(m_sectionOpened[section]);
     1298    /* Propagate to base-class: */
     1299    return QWidget::event(pEvent);
     1300}
     1301
     1302void UIDetailsBlock::createSection(int iSectionNumber)
     1303{
     1304    /* If section creation is NOT yet started: */
     1305    Section section = m_sections[iSectionNumber];
     1306    if (!m_block.contains(section))
     1307    {
     1308        /* Prepare new section (popup box): */
     1309        UIPopupBox *pPopup = m_block[section] = new UIPopupBox(this);
     1310        pPopup->hide();
     1311        connect(pPopup, SIGNAL(titleClicked(const QString &)), details()->detailsPage(), SIGNAL(linkClicked(const QString &)));
     1312        connect(pPopup, SIGNAL(toggled(bool)), parent(), SLOT(sltPopupToggled(bool)));
     1313        pPopup->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
     1314        pPopup->setProperty("section-type", static_cast<int>(section));
     1315        if (!m_machine.GetAccessible())
     1316            pPopup->setWarningIcon(UIIconPool::iconSet(":/state_aborted_16px.png"));
     1317
     1318        /* Configure the popup box: */
     1319        switch (section)
     1320        {
     1321            case Section_General:
     1322            {
     1323                QILabel *pLabel = new QILabel(pPopup);
     1324                pLabel->setWordWrap(true);
     1325                pPopup->setTitleIcon(UIIconPool::iconSet(":/machine_16px.png"));
     1326                pPopup->setTitleLink("#general");
     1327                pPopup->setContentWidget(pLabel);
     1328                connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateGeneral()));
     1329                break;
     1330            }
     1331            case Section_System:
     1332            {
     1333                QILabel *pLabel = new QILabel(pPopup);
     1334                pLabel->setWordWrap(true);
     1335                pPopup->setTitleIcon(UIIconPool::iconSet(":/chipset_16px.png"));
     1336                pPopup->setTitleLink("#system");
     1337                pPopup->setContentWidget(pLabel);
     1338                connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateSystem()));
     1339                break;
     1340            }
     1341            case Section_Preview:
     1342            {
     1343                UIVMPreviewWindow *pWidget = new UIVMPreviewWindow(pPopup);
     1344                pPopup->setTitleIcon(UIIconPool::iconSet(":/machine_16px.png"));
     1345                pPopup->setContentWidget(pWidget);
     1346                pPopup->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
     1347                /* Make sure the width is always the same, regardless if the preview is shown or not: */
     1348                pPopup->setFixedWidth(pPopup->sizeHint().width());
     1349                pWidget->updateGeometry();
     1350                connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdatePreview()));
     1351                break;
     1352            }
     1353            case Section_Display:
     1354            {
     1355                QILabel *pLabel = new QILabel(pPopup);
     1356                pLabel->setWordWrap(true);
     1357                pPopup->setTitleIcon(UIIconPool::iconSet(":/vrdp_16px.png"));
     1358                pPopup->setTitleLink("#display");
     1359                pPopup->setContentWidget(pLabel);
     1360                connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateDisplay()));
     1361                break;
     1362            }
     1363            case Section_Storage:
     1364            {
     1365                QILabel *pLabel = new QILabel(pPopup);
     1366                pLabel->setWordWrap(true);
     1367                pPopup->setTitleIcon(UIIconPool::iconSet(":/attachment_16px.png"));
     1368                pPopup->setTitleLink("#storage");
     1369                pPopup->setContentWidget(pLabel);
     1370                connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateStorage()));
     1371                break;
     1372            }
     1373            case Section_Audio:
     1374            {
     1375                QILabel *pLabel = new QILabel(pPopup);
     1376                pLabel->setWordWrap(true);
     1377                pPopup->setTitleIcon(UIIconPool::iconSet(":/sound_16px.png"));
     1378                pPopup->setTitleLink("#audio");
     1379                pPopup->setContentWidget(pLabel);
     1380                connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateAudio()));
     1381                break;
     1382            }
     1383            case Section_Network:
     1384            {
     1385                QILabel *pLabel = new QILabel(pPopup);
     1386                pLabel->setWordWrap(true);
     1387                pPopup->setTitleIcon(UIIconPool::iconSet(":/nw_16px.png"));
     1388                pPopup->setTitleLink("#network");
     1389                pPopup->setContentWidget(pLabel);
     1390                connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateNetwork()));
     1391                break;
     1392            }
     1393            case Section_Serial:
     1394            {
     1395                QILabel *pLabel = new QILabel(pPopup);
     1396                pLabel->setWordWrap(true);
     1397                pPopup->setTitleIcon(UIIconPool::iconSet(":/serial_port_16px.png"));
     1398                pPopup->setTitleLink("#serialPorts");
     1399                pPopup->setContentWidget(pLabel);
     1400                connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateSerialPorts()));
     1401                break;
     1402            }
     1403#ifdef VBOX_WITH_PARALLEL_PORTS
     1404            case Section_Parallel:
     1405            {
     1406                QILabel *pLabel = new QILabel(pPopup);
     1407                pLabel->setWordWrap(true);
     1408                pPopup->setTitleIcon(UIIconPool::iconSet(":/parallel_port_16px.png"));
     1409                pPopup->setTitleLink("#parallelPorts");
     1410                pPopup->setContentWidget(pLabel);
     1411                connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateParallelPorts()));
     1412                break;
     1413            }
     1414#endif /* VBOX_WITH_PARALLEL_PORTS */
     1415            case Section_USB:
     1416            {
     1417                QILabel *pLabel = new QILabel(pPopup);
     1418                pLabel->setWordWrap(true);
     1419                pPopup->setTitleIcon(UIIconPool::iconSet(":/usb_16px.png"));
     1420                pPopup->setTitleLink("#usb");
     1421                pPopup->setContentWidget(pLabel);
     1422                connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateUSB()));
     1423                break;
     1424            }
     1425            case Section_SharedFolders:
     1426            {
     1427                QILabel *pLabel = new QILabel(pPopup);
     1428                pLabel->setWordWrap(true);
     1429                pPopup->setTitleIcon(UIIconPool::iconSet(":/shared_folder_16px.png"));
     1430                pPopup->setTitleLink("#sfolders");
     1431                pPopup->setContentWidget(pLabel);
     1432                connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateSharedFolders()));
     1433                break;
     1434            }
     1435            case Section_Description:
     1436            {
     1437                QILabel *pLabel = new QILabel(pPopup);
     1438                pLabel->setWordWrap(true);
     1439                pPopup->setTitleIcon(UIIconPool::iconSet(":/description_16px.png"));
     1440                pPopup->setTitleLink("#general%%mTeDescription");
     1441                pPopup->setContentWidget(pLabel);
     1442                connect(pPopup, SIGNAL(sigUpdateContentWidget()), this, SLOT(sltUpdateDescription()));
     1443                break;
     1444            }
     1445            default:
     1446                break;
     1447        }
     1448
     1449        /* Open/close section if necessary: */
     1450        pPopup->setOpen(sectionOpened(section));
     1451    }
    14071452
    14081453    /* Call for update: */
    1409     pPopup->callForUpdateContentWidget();
    1410 }
    1411 
    1412 void UIDetailsPagePrivate::prepareDetails()
     1454    m_block[section]->callForUpdateContentWidget();
     1455}
     1456
     1457/* static */
     1458QString UIDetailsBlock::summarizeGenericProperties(const CNetworkAdapter &adapter)
     1459{
     1460    QVector<QString> names;
     1461    QVector<QString> props;
     1462    props = adapter.GetProperties(QString(), names);
     1463    QString strResult;
     1464    for (int i = 0; i < names.size(); ++i)
     1465    {
     1466        strResult += names[i] + "=" + props[i];
     1467        if (i < names.size() - 1)
     1468            strResult += ", ";
     1469    }
     1470    return strResult;
     1471}
     1472
     1473UIDetailsPagePrivate::UIDetailsPagePrivate(QWidget *pParent, QAction *pRefreshAction /* = 0 */)
     1474    : QIWithRetranslateUI<QStackedWidget>(pParent)
     1475    , m_cMachineCount(0)
     1476    , m_pScrollArea(0)
     1477    , m_pDetails(0)
     1478    , m_pText(0)
     1479    , m_pErrBox(0), m_pErrLabel(0), m_pErrText(0)
     1480    , m_pRefreshButton(0), m_pRefreshAction(pRefreshAction)
     1481{
     1482    /* Check that refresh action was passed: */
     1483    Assert(m_pRefreshAction);
     1484}
     1485
     1486UIDetailsPagePrivate::~UIDetailsPagePrivate()
     1487{
     1488    /* Cleanup details: */
     1489    cleanupDetailsPage();
     1490}
     1491
     1492void UIDetailsPagePrivate::setMachines(const QList<CMachine> &machines)
     1493{
     1494    /* Prepare machine details page if necessary: */
     1495    prepareDetailsPage();
     1496
     1497    /* Prepare machine details: */
     1498    prepareDetails(machines);
     1499
     1500    /* Select corresponding widget: */
     1501    setCurrentIndex(indexOf(m_pScrollArea));
     1502}
     1503
     1504void UIDetailsPagePrivate::setText(const QString &aText)
     1505{
     1506    /* Prepare text page if necessary: */
     1507    prepareTextPage();
     1508
     1509    /* Assign corresponding text: */
     1510    m_pText->setText(aText);
     1511
     1512    /* Select corresponding widget: */
     1513    setCurrentIndex(indexOf(m_pText));
     1514}
     1515
     1516void UIDetailsPagePrivate::setErrorText(const QString &aText)
     1517{
     1518    /* Prepare error page if necessary: */
     1519    prepareErrorPage();
     1520
     1521    /* Assign corresponding error: */
     1522    m_pErrText->setText(aText);
     1523
     1524    /* Select corresponding widget: */
     1525    setCurrentIndex(indexOf(m_pErrBox));
     1526}
     1527
     1528void UIDetailsPagePrivate::retranslateUi()
     1529{
     1530    /* Translate context menu actions: */
     1531    {
     1532        if (m_actions.contains(Section_General))
     1533            m_actions[Section_General]->setText(tr("General", "details report"));
     1534        if (m_actions.contains(Section_System))
     1535            m_actions[Section_System]->setText(tr("System", "details report"));
     1536        if (m_actions.contains(Section_Preview))
     1537            m_actions[Section_Preview]->setText(tr("Preview", "details report"));
     1538        if (m_actions.contains(Section_Display))
     1539            m_actions[Section_Display]->setText(tr("Display", "details report"));
     1540        if (m_actions.contains(Section_Storage))
     1541            m_actions[Section_Storage]->setText(tr("Storage", "details report"));
     1542        if (m_actions.contains(Section_Audio))
     1543            m_actions[Section_Audio]->setText(tr("Audio", "details report"));
     1544        if (m_actions.contains(Section_Network))
     1545            m_actions[Section_Network]->setText(tr("Network", "details report"));
     1546        if (m_actions.contains(Section_Serial))
     1547            m_actions[Section_Serial]->setText(tr("Serial Ports", "details report"));
     1548#ifdef VBOX_WITH_PARALLEL_PORTS
     1549        if (m_actions.contains(Section_Parallel))
     1550            m_actions[Section_Parallel]->setText(tr("Parallel Ports", "details report"));
     1551#endif /* VBOX_WITH_PARALLEL_PORTS */
     1552        if (m_actions.contains(Section_USB))
     1553            m_actions[Section_USB]->setText(tr("USB", "details report"));
     1554        if (m_actions.contains(Section_SharedFolders))
     1555            m_actions[Section_SharedFolders]->setText(tr("Shared Folders", "details report"));
     1556        if (m_actions.contains(Section_Description))
     1557            m_actions[Section_Description]->setText(tr("Description", "details report"));
     1558    }
     1559
     1560    /* Translate error-label text: */
     1561    if (m_pErrLabel)
     1562        m_pErrLabel->setText(tr("The selected virtual machine is <i>inaccessible</i>. "
     1563                                "Please inspect the error message shown below and press the "
     1564                                "<b>Refresh</b> button if you want to repeat the accessibility check:"));
     1565
     1566    /* Translate refresh button & action text: */
     1567    if (m_pRefreshAction && m_pRefreshButton)
     1568    {
     1569        m_pRefreshButton->setText(m_pRefreshAction->text());
     1570        m_pRefreshButton->setIcon(m_pRefreshAction->icon());
     1571        m_pRefreshButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
     1572    }
     1573}
     1574
     1575void UIDetailsPagePrivate::prepareDetails(const QList<CMachine> &machines)
     1576{
     1577    /* Was machine count changed? */
     1578    bool fCountChanged = m_cMachineCount != machines.size();
     1579
     1580    /* Do we need to recreate details? */
     1581    if (fCountChanged)
     1582    {
     1583        /* Get new machine count: */
     1584        m_cMachineCount = machines.size();
     1585
     1586        /* Delete current details if exists:*/
     1587        if (m_pDetails)
     1588            delete m_pDetails;
     1589
     1590        /* Create and configure new details: */
     1591        m_pDetails = new UIDetails(this);
     1592        m_pScrollArea->setWidget(m_pDetails);
     1593    }
     1594
     1595    /* Assign new machine array for the details: */
     1596    m_pDetails->setMachines(machines);
     1597}
     1598
     1599void UIDetailsPagePrivate::prepareDetailsPage()
    14131600{
    14141601    if (m_pScrollArea)
     
    14861673}
    14871674
    1488 void UIDetailsPagePrivate::cleanupDetails()
     1675void UIDetailsPagePrivate::cleanupDetailsPage()
    14891676{
    14901677    if (!m_pScrollArea)
     
    14981685
    14991686        /* Process only existing sections: */
    1500         if (!m_sections.contains(section))
     1687        if (!m_pDetails->sections().contains(section))
    15011688            continue;
    15021689
     
    15751762
    15761763    retranslateUi();
    1577 }
    1578 
    1579 /**
    1580  *  Return a text summary of the properties of a generic network adapter
    1581  */
    1582 /* static */
    1583 QString UIDetailsPagePrivate::summarizeGenericProperties(const CNetworkAdapter &adapter)
    1584 {
    1585     QVector<QString> names;
    1586     QVector<QString> props;
    1587     props = adapter.GetProperties(QString(), names);
    1588     QString strResult;
    1589     for (int i = 0; i < names.size(); ++i)
    1590     {
    1591         strResult += names[i] + "=" + props[i];
    1592         if (i < names.size() - 1)
    1593             strResult += ", ";
    1594     }
    1595     return strResult;
    15961764}
    15971765
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