Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformation.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformation.cpp	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformation.cpp	(revision 58611)
@@ -0,0 +1,115 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformation class implementation.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifdef VBOX_WITH_PRECOMPILED_HEADERS
+# include <precomp.h>
+#else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+/* Qt includes: */
+# include <QApplication>
+# include <QVBoxLayout>
+
+/* GUI includes: */
+# include "UIGInformation.h"
+# include "UIGInformationModel.h"
+# include "UIGInformationView.h"
+
+#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+
+UIGInformation::UIGInformation(QWidget *pParent)
+    : QWidget(pParent)
+    , m_pMainLayout(0)
+    , m_pDetailsModel(0)
+    , m_pDetailsView(0)
+{
+    /* Prepare palette: */
+    preparePalette();
+
+    /* Prepare layout: */
+    prepareLayout();
+
+    /* Prepare model: */
+    prepareModel();
+
+    /* Prepare view: */
+    prepareView();
+
+    /* Prepare connections: */
+    prepareConnections();
+}
+
+void UIGInformation::setItems(const QList<UIVMItem*> &items)
+{
+    /* Propagate to details-model: */
+    m_pDetailsModel->setItems(items);
+}
+
+void UIGInformation::preparePalette()
+{
+    /* Setup palette: */
+    setAutoFillBackground(true);
+    QPalette pal = qApp->palette();
+    pal.setColor(QPalette::Window, pal.color(QPalette::Active, QPalette::Window));
+    setPalette(pal);
+}
+
+void UIGInformation::prepareLayout()
+{
+    /* Setup main-layout: */
+    m_pMainLayout = new QVBoxLayout(this);
+    m_pMainLayout->setContentsMargins(2, 0, 0, 0);
+    m_pMainLayout->setSpacing(0);
+}
+
+void UIGInformation::prepareModel()
+{
+    /* Setup details-model: */
+    m_pDetailsModel = new UIGInformationModel(this);
+}
+
+void UIGInformation::prepareView()
+{
+    /* Setup details-view: */
+    m_pDetailsView = new UIGInformationView(this);
+    m_pDetailsView->setScene(m_pDetailsModel->scene());
+    m_pDetailsView->show();
+    setFocusProxy(m_pDetailsView);
+    m_pMainLayout->addWidget(m_pDetailsView);
+}
+
+void UIGInformation::prepareConnections()
+{
+    /* Setup details-model connections: */
+    connect(m_pDetailsModel, SIGNAL(sigRootItemMinimumWidthHintChanged(int)),
+            m_pDetailsView, SLOT(sltMinimumWidthHintChanged(int)));
+    connect(m_pDetailsModel, SIGNAL(sigRootItemMinimumHeightHintChanged(int)),
+            m_pDetailsView, SLOT(sltMinimumHeightHintChanged(int)));
+    connect(m_pDetailsModel, SIGNAL(sigLinkClicked(const QString&, const QString&, const QString&)),
+            this, SIGNAL(sigLinkClicked(const QString&, const QString&, const QString&)));
+    connect(this, SIGNAL(sigSlidingStarted()),
+            m_pDetailsModel, SLOT(sltHandleSlidingStarted()));
+    connect(this, SIGNAL(sigToggleStarted()),
+            m_pDetailsModel, SLOT(sltHandleToggleStarted()));
+    connect(this, SIGNAL(sigToggleFinished()),
+            m_pDetailsModel, SLOT(sltHandleToggleFinished()));
+
+    /* Setup details-view connections: */
+    connect(m_pDetailsView, SIGNAL(sigResized()),
+            m_pDetailsModel, SLOT(sltHandleViewResize()));
+}
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformation.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformation.h	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformation.h	(revision 58611)
@@ -0,0 +1,71 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformation class declaration.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef __UIGInformation_h__
+#define __UIGInformation_h__
+
+/* Qt includes: */
+#include <QWidget>
+
+/* Forward declartions: */
+class QVBoxLayout;
+class UIGInformationModel;
+class UIGInformationView;
+class UIVMItem;
+
+/* Details widget: */
+class UIGInformation : public QWidget
+{
+    Q_OBJECT;
+
+signals:
+
+    /* Notifier: Link processing stuff: */
+    void sigLinkClicked(const QString &strCategory, const QString &strControl, const QString &strId);
+
+    /* Notifier: Sliding stuff: */
+    void sigSlidingStarted();
+
+    /* Notifiers: Toggle stuff: */
+    void sigToggleStarted();
+    void sigToggleFinished();
+
+public:
+
+    /* Constructor: */
+    UIGInformation(QWidget *pParent);
+
+    /* API: Current item(s) stuff: */
+    void setItems(const QList<UIVMItem*> &items);
+
+private:
+
+    /* Helpers: Prepare stuff: */
+    void preparePalette();
+    void prepareLayout();
+    void prepareModel();
+    void prepareView();
+    void prepareConnections();
+
+    /* Variables: */
+    QVBoxLayout *m_pMainLayout;
+    UIGInformationModel *m_pDetailsModel;
+    UIGInformationView *m_pDetailsView;
+};
+
+#endif /* __UIGInformation_h__ */
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationElement.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationElement.cpp	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationElement.cpp	(revision 58611)
@@ -0,0 +1,695 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformationElement class implementation.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifdef VBOX_WITH_PRECOMPILED_HEADERS
+# include <precomp.h>
+#else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+/* Qt includes: */
+# include <QGraphicsView>
+# include <QStateMachine>
+# include <QPropertyAnimation>
+# include <QSignalTransition>
+# include <QStyleOptionGraphicsItem>
+# include <QGraphicsSceneMouseEvent>
+
+/* GUI includes: */
+# include "UIGInformationElement.h"
+# include "UIGInformationSet.h"
+# include "UIGInformationModel.h"
+# include "UIGraphicsRotatorButton.h"
+# include "UIGraphicsTextPane.h"
+# include "UIActionPool.h"
+# include "UIIconPool.h"
+# include "UIConverter.h"
+# include "VBoxGlobal.h"
+
+#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+
+UIGInformationElement::UIGInformationElement(UIGInformationSet *pParent, DetailsElementType type, bool fOpened)
+    : UIGInformationItem(pParent)
+    , m_pSet(pParent)
+    , m_type(type)
+    , m_iCornerRadius(10)
+    , m_iMinimumHeaderWidth(0)
+    , m_iMinimumHeaderHeight(0)
+    , m_pButton(0)
+    , m_fClosed(!fOpened)
+    , m_iAdditionalHeight(0)
+    , m_fAnimationRunning(false)
+    , m_pTextPane(0)
+    , m_fHovered(false)
+    , m_fNameHovered(false)
+    , m_pHighlightMachine(0)
+    , m_pForwardAnimation(0)
+    , m_pBackwardAnimation(0)
+    , m_iAnimationDuration(400)
+    , m_iDefaultDarkness(100)
+    , m_iHighlightDarkness(90)
+    , m_iAnimationDarkness(m_iDefaultDarkness)
+{
+    /* Prepare element: */
+    prepareElement();
+    /* Prepare button: */
+    prepareButton();
+    /* Prepare text-pane: */
+    prepareTextPane();
+
+    /* Setup size-policy: */
+    setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
+
+    /* Add item to the parent: */
+    AssertMsg(parentItem(), ("No parent set for details element!"));
+    parentItem()->addItem(this);
+}
+
+UIGInformationElement::~UIGInformationElement()
+{
+    /* Remove item from the parent: */
+    AssertMsg(parentItem(), ("No parent set for details element!"));
+    parentItem()->removeItem(this);
+}
+
+void UIGInformationElement::close(bool fAnimated /* = true */)
+{
+    m_pButton->setToggled(false, fAnimated);
+}
+
+void UIGInformationElement::open(bool fAnimated /* = true */)
+{
+    m_pButton->setToggled(true, fAnimated);
+}
+
+void UIGInformationElement::updateAppearance()
+{
+    /* Reset name hover state: */
+    m_fNameHovered = false;
+    updateNameHoverLink();
+
+    /* Update anchor role restrictions: */
+    ConfigurationAccessLevel cal = m_pSet->configurationAccessLevel();
+    m_pTextPane->setAnchorRoleRestricted("#mount", cal == ConfigurationAccessLevel_Null);
+    m_pTextPane->setAnchorRoleRestricted("#attach", cal != ConfigurationAccessLevel_Full);
+}
+
+void UIGInformationElement::markAnimationFinished()
+{
+    /* Mark animation as non-running: */
+    m_fAnimationRunning = false;
+
+    /* Recursively update size-hint: */
+    updateGeometry();
+    /* Repaint: */
+    update();
+}
+
+void UIGInformationElement::sltToggleButtonClicked()
+{
+    emit sigToggleElement(m_type, closed());
+}
+
+void UIGInformationElement::sltElementToggleStart()
+{
+    /* Mark animation running: */
+    m_fAnimationRunning = true;
+
+    /* Setup animation: */
+    updateAnimationParameters();
+
+    /* Invert toggle-state: */
+    m_fClosed = !m_fClosed;
+}
+
+void UIGInformationElement::sltElementToggleFinish(bool fToggled)
+{
+    /* Update toggle-state: */
+    m_fClosed = !fToggled;
+
+    /* Notify about finishing: */
+    emit sigToggleElementFinished();
+}
+
+void UIGInformationElement::sltHandleAnchorClicked(const QString &strAnchor)
+{
+    /* Current anchor role: */
+    const QString strRole = strAnchor.section(',', 0, 0);
+    const QString strData = strAnchor.section(',', 1);
+
+    /* Handle known anchor roles: */
+    if (   strRole == "#mount"  // Optical and floppy attachments..
+        || strRole == "#attach" // Hard-drive attachments..
+        )
+    {
+        /* Prepare storage-menu: */
+        UIMenu menu;
+        menu.setShowToolTip(true);
+
+        /* Storage-controller name: */
+        QString strControllerName = strData.section(',', 0, 0);
+        /* Storage-slot: */
+        StorageSlot storageSlot = gpConverter->fromString<StorageSlot>(strData.section(',', 1));
+
+        /* Fill storage-menu: */
+        vboxGlobal().prepareStorageMenu(menu, this, SLOT(sltMountStorageMedium()),
+                                        machine(), strControllerName, storageSlot);
+
+        /* Exec menu: */
+        menu.exec(QCursor::pos());
+    }
+}
+
+void UIGInformationElement::sltMountStorageMedium()
+{
+    /* Sender action: */
+    QAction *pAction = qobject_cast<QAction*>(sender());
+    AssertMsgReturnVoid(pAction, ("This slot should only be called by menu action!\n"));
+
+    /* Current mount-target: */
+    const UIMediumTarget target = pAction->data().value<UIMediumTarget>();
+
+    /* Update current machine mount-target: */
+    vboxGlobal().updateMachineStorage(machine(), target);
+}
+
+void UIGInformationElement::resizeEvent(QGraphicsSceneResizeEvent*)
+{
+    /* Update layout: */
+    updateLayout();
+}
+
+QVariant UIGInformationElement::data(int iKey) const
+{
+    /* Provide other members with required data: */
+    switch (iKey)
+    {
+        /* Hints: */
+        case ElementData_Margin: return 5;
+        case ElementData_Spacing: return 10;
+        case ElementData_MinimumTextColumnWidth: return 100;
+        /* Default: */
+        default: break;
+    }
+    return QVariant();
+}
+
+void UIGInformationElement::updateMinimumHeaderWidth()
+{
+    /* Prepare variables: */
+    int iSpacing = data(ElementData_Spacing).toInt();
+
+    /* Update minimum-header-width: */
+    m_iMinimumHeaderWidth = m_pixmapSize.width() +
+                            iSpacing + m_nameSize.width() +
+                            iSpacing + m_buttonSize.width();
+}
+
+void UIGInformationElement::updateMinimumHeaderHeight()
+{
+    /* Update minimum-header-height: */
+    m_iMinimumHeaderHeight = qMax(m_pixmapSize.height(), m_nameSize.height());
+    m_iMinimumHeaderHeight = qMax(m_iMinimumHeaderHeight, m_buttonSize.height());
+}
+
+void UIGInformationElement::setIcon(const QIcon &icon)
+{
+    /* Cache icon: */
+    if (icon.isNull())
+    {
+        /* No icon provided: */
+        m_pixmapSize = QSize();
+        m_pixmap = QPixmap();
+    }
+    else
+    {
+        /* Determine default the icon size: */
+        const QStyle *pStyle = QApplication::style();
+        const int iIconMetric = pStyle->pixelMetric(QStyle::PM_SmallIconSize);
+        m_pixmapSize = QSize(iIconMetric, iIconMetric);
+        /* Acquire the icon of the corresponding size: */
+        m_pixmap = icon.pixmap(m_pixmapSize);
+    }
+
+    /* Update linked values: */
+    updateMinimumHeaderWidth();
+    updateMinimumHeaderHeight();
+}
+
+void UIGInformationElement::setName(const QString &strName)
+{
+    /* Cache name: */
+    m_strName = strName;
+    QFontMetrics fm(m_nameFont, model()->paintDevice());
+    m_nameSize = QSize(fm.width(m_strName), fm.height());
+
+    /* Update linked values: */
+    updateMinimumHeaderWidth();
+    updateMinimumHeaderHeight();
+}
+
+const UITextTable& UIGInformationElement::text() const
+{
+    /* Retrieve text from text-pane: */
+    return m_pTextPane->text();
+}
+
+void UIGInformationElement::setText(const UITextTable &text)
+{
+    /* Pass text to text-pane: */
+    m_pTextPane->setText(text);
+}
+
+const CMachine& UIGInformationElement::machine()
+{
+    return m_pSet->machine();
+}
+
+int UIGInformationElement::minimumWidthHint() const
+{
+    /* Prepare variables: */
+    int iMargin = data(ElementData_Margin).toInt();
+    int iMinimumWidthHint = 0;
+
+    /* Maximum width: */
+    iMinimumWidthHint = qMax(m_iMinimumHeaderWidth, (int)m_pTextPane->minimumSizeHint().width());
+
+    /* And 4 margins: 2 left and 2 right: */
+    iMinimumWidthHint += 4 * iMargin;
+
+    /* Return result: */
+    return iMinimumWidthHint;
+}
+
+int UIGInformationElement::minimumHeightHint(bool fClosed) const
+{
+    /* Prepare variables: */
+    int iMargin = data(ElementData_Margin).toInt();
+    int iMinimumHeightHint = 0;
+
+    /* Two margins: */
+    iMinimumHeightHint += 2 * iMargin;
+
+    /* Header height: */
+    iMinimumHeightHint += m_iMinimumHeaderHeight;
+
+    /* Element is opened? */
+    if (!fClosed)
+    {
+        /* Add text height: */
+        if (!m_pTextPane->isEmpty())
+            iMinimumHeightHint += 2 * iMargin + (int)m_pTextPane->minimumSizeHint().height();
+    }
+
+    /* Additional height during animation: */
+    if (m_fAnimationRunning)
+        iMinimumHeightHint += m_iAdditionalHeight;
+
+    /* Return value: */
+    return iMinimumHeightHint;
+}
+
+int UIGInformationElement::minimumHeightHint() const
+{
+    return minimumHeightHint(m_fClosed);
+}
+
+void UIGInformationElement::updateLayout()
+{
+    /* Prepare variables: */
+    QSize size = geometry().size().toSize();
+    int iMargin = data(ElementData_Margin).toInt();
+
+    /* Layout button: */
+    int iButtonWidth = m_buttonSize.width();
+    int iButtonHeight = m_buttonSize.height();
+    int iButtonX = size.width() - 2 * iMargin - iButtonWidth;
+    int iButtonY = iButtonHeight == m_iMinimumHeaderHeight ? iMargin :
+                   iMargin + (m_iMinimumHeaderHeight - iButtonHeight) / 2;
+    m_pButton->setPos(iButtonX, iButtonY);
+
+    /* If closed: */
+    if (closed())
+    {
+        /* Hide text-pane if still visible: */
+        if (m_pTextPane->isVisible())
+            m_pTextPane->hide();
+    }
+    /* If opened: */
+    else
+    {
+        /* Layout text-pane: */
+        int iTextPaneX = 2 * iMargin;
+        int iTextPaneY = iMargin + m_iMinimumHeaderHeight + 2 * iMargin;
+        m_pTextPane->setPos(iTextPaneX, iTextPaneY);
+        m_pTextPane->resize(size.width() - 4 * iMargin,
+                            size.height() - 4 * iMargin - m_iMinimumHeaderHeight);
+        /* Show text-pane if still invisible and animation finished: */
+        if (!m_pTextPane->isVisible() && !isAnimationRunning())
+            m_pTextPane->show();
+    }
+}
+
+void UIGInformationElement::setAdditionalHeight(int iAdditionalHeight)
+{
+    /* Cache new value: */
+    m_iAdditionalHeight = iAdditionalHeight;
+    /* Update layout: */
+    updateLayout();
+    /* Repaint: */
+    update();
+}
+
+void UIGInformationElement::addItem(UIGInformationItem*)
+{
+    AssertMsgFailed(("Details element do NOT support children!"));
+}
+
+void UIGInformationElement::removeItem(UIGInformationItem*)
+{
+    AssertMsgFailed(("Details element do NOT support children!"));
+}
+
+QList<UIGInformationItem*> UIGInformationElement::items(UIGInformationItemType) const
+{
+    AssertMsgFailed(("Details element do NOT support children!"));
+    return QList<UIGInformationItem*>();
+}
+
+bool UIGInformationElement::hasItems(UIGInformationItemType) const
+{
+    AssertMsgFailed(("Details element do NOT support children!"));
+    return false;
+}
+
+void UIGInformationElement::clearItems(UIGInformationItemType)
+{
+    AssertMsgFailed(("Details element do NOT support children!"));
+}
+
+void UIGInformationElement::prepareElement()
+{
+    /* Initialization: */
+    m_nameFont = font();
+    m_nameFont.setWeight(QFont::Bold);
+    m_textFont = font();
+
+    /* Create highlight machine: */
+    m_pHighlightMachine = new QStateMachine(this);
+    /* Create 'default' state: */
+    QState *pStateDefault = new QState(m_pHighlightMachine);
+    /* Create 'highlighted' state: */
+    QState *pStateHighlighted = new QState(m_pHighlightMachine);
+
+    /* Forward animation: */
+    m_pForwardAnimation = new QPropertyAnimation(this, "animationDarkness", this);
+    m_pForwardAnimation->setDuration(m_iAnimationDuration);
+    m_pForwardAnimation->setStartValue(m_iDefaultDarkness);
+    m_pForwardAnimation->setEndValue(m_iHighlightDarkness);
+
+    /* Backward animation: */
+    m_pBackwardAnimation = new QPropertyAnimation(this, "animationDarkness", this);
+    m_pBackwardAnimation->setDuration(m_iAnimationDuration);
+    m_pBackwardAnimation->setStartValue(m_iHighlightDarkness);
+    m_pBackwardAnimation->setEndValue(m_iDefaultDarkness);
+
+    /* Add state transitions: */
+    QSignalTransition *pDefaultToHighlighted = pStateDefault->addTransition(this, SIGNAL(sigHoverEnter()), pStateHighlighted);
+    pDefaultToHighlighted->addAnimation(m_pForwardAnimation);
+    QSignalTransition *pHighlightedToDefault = pStateHighlighted->addTransition(this, SIGNAL(sigHoverLeave()), pStateDefault);
+    pHighlightedToDefault->addAnimation(m_pBackwardAnimation);
+
+    /* Initial state is 'default': */
+    m_pHighlightMachine->setInitialState(pStateDefault);
+    /* Start state-machine: */
+    m_pHighlightMachine->start();
+
+    connect(this, SIGNAL(sigToggleElement(DetailsElementType, bool)), model(), SLOT(sltToggleElements(DetailsElementType, bool)));
+    connect(this, SIGNAL(sigLinkClicked(const QString&, const QString&, const QString&)),
+            model(), SIGNAL(sigLinkClicked(const QString&, const QString&, const QString&)));
+}
+
+void UIGInformationElement::prepareButton()
+{
+    /* Setup toggle-button: */
+    m_pButton = new UIGraphicsRotatorButton(this, "additionalHeight", !m_fClosed, true /* reflected */);
+    m_pButton->setAutoHandleButtonClick(false);
+    connect(m_pButton, SIGNAL(sigButtonClicked()), this, SLOT(sltToggleButtonClicked()));
+    connect(m_pButton, SIGNAL(sigRotationStart()), this, SLOT(sltElementToggleStart()));
+    connect(m_pButton, SIGNAL(sigRotationFinish(bool)), this, SLOT(sltElementToggleFinish(bool)));
+    m_buttonSize = m_pButton->minimumSizeHint().toSize();
+}
+
+void UIGInformationElement::prepareTextPane()
+{
+    /* Create text-pane: */
+    m_pTextPane = new UIGraphicsTextPane(this, model()->paintDevice());
+    connect(m_pTextPane, SIGNAL(sigGeometryChanged()), this, SLOT(sltUpdateGeometry()));
+    connect(m_pTextPane, SIGNAL(sigAnchorClicked(const QString&)), this, SLOT(sltHandleAnchorClicked(const QString&)));
+}
+
+void UIGInformationElement::paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption, QWidget*)
+{
+    /* Update button visibility: */
+    updateButtonVisibility();
+
+    /* Configure painter shape: */
+    configurePainterShape(pPainter, pOption, m_iCornerRadius);
+
+    /* Paint decorations: */
+    paintDecorations(pPainter, pOption);
+
+    /* Paint element info: */
+    paintElementInfo(pPainter, pOption);
+}
+
+void UIGInformationElement::paintDecorations(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption)
+{
+    /* Paint background: */
+    paintBackground(pPainter, pOption);
+}
+
+void UIGInformationElement::paintElementInfo(QPainter *pPainter, const QStyleOptionGraphicsItem*)
+{
+    /* Initialize some necessary variables: */
+    int iMargin = data(ElementData_Margin).toInt();
+    int iSpacing = data(ElementData_Spacing).toInt();
+
+    /* Calculate attributes: */
+    int iPixmapHeight = m_pixmapSize.height();
+    int iNameHeight = m_nameSize.height();
+    int iMaximumHeight = qMax(iPixmapHeight, iNameHeight);
+
+    /* Prepare color: */
+    QPalette pal = palette();
+    QColor buttonTextColor = pal.color(QPalette::Active, QPalette::ButtonText);
+    QColor linkTextColor = pal.color(QPalette::Active, QPalette::Link);
+
+    /* Paint pixmap: */
+    int iElementPixmapX = 2 * iMargin;
+    int iElementPixmapY = iPixmapHeight == iMaximumHeight ?
+                          iMargin : iMargin + (iMaximumHeight - iPixmapHeight) / 2;
+    paintPixmap(/* Painter: */
+                pPainter,
+                /* Rectangle to paint in: */
+                QRect(QPoint(iElementPixmapX, iElementPixmapY), m_pixmapSize),
+                /* Pixmap to paint: */
+                m_pixmap);
+
+    /* Paint name: */
+    int iMachineNameX = iElementPixmapX +
+                        m_pixmapSize.width() +
+                        iSpacing;
+    int iMachineNameY = iNameHeight == iMaximumHeight ?
+                        iMargin : iMargin + (iMaximumHeight - iNameHeight) / 2;
+    paintText(/* Painter: */
+              pPainter,
+              /* Rectangle to paint in: */
+              QPoint(iMachineNameX, iMachineNameY),
+              /* Font to paint text: */
+              m_nameFont,
+              /* Paint device: */
+              model()->paintDevice(),
+              /* Text to paint: */
+              m_strName,
+              /* Name hovered? */
+              m_fNameHovered ? linkTextColor : buttonTextColor);
+}
+
+void UIGInformationElement::paintBackground(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption)
+{
+    /* Save painter: */
+    pPainter->save();
+
+    /* Prepare variables: */
+    int iMargin = data(ElementData_Margin).toInt();
+    int iHeaderHeight = 2 * iMargin + m_iMinimumHeaderHeight;
+    QRect optionRect = pOption->rect;
+    QRect fullRect = !m_fAnimationRunning ? optionRect :
+                     QRect(optionRect.topLeft(), QSize(optionRect.width(), iHeaderHeight + m_iAdditionalHeight));
+    int iFullHeight = fullRect.height();
+
+    /* Prepare color: */
+    QPalette pal = palette();
+    QColor headerColor = pal.color(QPalette::Active, QPalette::Button);
+    QColor strokeColor = pal.color(QPalette::Active, QPalette::Mid);
+    QColor bodyColor = pal.color(QPalette::Active, QPalette::Base);
+
+    /* Add clipping: */
+    QPainterPath path;
+    path.moveTo(m_iCornerRadius, 0);
+    path.arcTo(QRectF(path.currentPosition(), QSizeF(2 * m_iCornerRadius, 2 * m_iCornerRadius)).translated(-m_iCornerRadius, 0), 90, 90);
+    path.lineTo(path.currentPosition().x(), iFullHeight - m_iCornerRadius);
+    path.arcTo(QRectF(path.currentPosition(), QSizeF(2 * m_iCornerRadius, 2 * m_iCornerRadius)).translated(0, -m_iCornerRadius), 180, 90);
+    path.lineTo(fullRect.width() - m_iCornerRadius, path.currentPosition().y());
+    path.arcTo(QRectF(path.currentPosition(), QSizeF(2 * m_iCornerRadius, 2 * m_iCornerRadius)).translated(-m_iCornerRadius, -2 * m_iCornerRadius), 270, 90);
+    path.lineTo(path.currentPosition().x(), m_iCornerRadius);
+    path.arcTo(QRectF(path.currentPosition(), QSizeF(2 * m_iCornerRadius, 2 * m_iCornerRadius)).translated(-2 * m_iCornerRadius, -m_iCornerRadius), 0, 90);
+    path.closeSubpath();
+    pPainter->setClipPath(path);
+
+    /* Calculate top rectangle: */
+    QRect tRect = fullRect;
+    tRect.setBottom(tRect.top() + iHeaderHeight);
+    /* Calculate bottom rectangle: */
+    QRect bRect = fullRect;
+    bRect.setTop(tRect.bottom());
+
+    /* Prepare top gradient: */
+    QLinearGradient tGradient(tRect.bottomLeft(), tRect.topLeft());
+    tGradient.setColorAt(0, headerColor.darker(110));
+    tGradient.setColorAt(1, headerColor.darker(animationDarkness()));
+
+    /* Paint all the stuff: */
+    pPainter->fillRect(tRect, tGradient);
+    pPainter->fillRect(bRect, bodyColor);
+
+    /* Stroke path: */
+    pPainter->setClipping(false);
+    pPainter->strokePath(path, strokeColor);
+
+    /* Restore painter: */
+    pPainter->restore();
+}
+
+void UIGInformationElement::hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent)
+{
+    /* Update hover state: */
+    if (!m_fHovered)
+    {
+        m_fHovered = true;
+        emit sigHoverEnter();
+    }
+
+    /* Update name-hover state: */
+    handleHoverEvent(pEvent);
+}
+
+void UIGInformationElement::hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent)
+{
+    /* Update hover state: */
+    if (m_fHovered)
+    {
+        m_fHovered = false;
+        emit sigHoverLeave();
+    }
+
+    /* Update name-hover state: */
+    handleHoverEvent(pEvent);
+}
+
+void UIGInformationElement::mousePressEvent(QGraphicsSceneMouseEvent *pEvent)
+{
+    /* Only for hovered header: */
+    if (!m_fNameHovered)
+        return;
+
+    /* Process link click: */
+    pEvent->accept();
+    QString strCategory;
+    if (m_type >= DetailsElementType_General &&
+        m_type < DetailsElementType_Description)
+        strCategory = QString("#%1").arg(gpConverter->toInternalString(m_type));
+    else if (m_type == DetailsElementType_Description)
+        strCategory = QString("#%1%%mTeDescription").arg(gpConverter->toInternalString(m_type));
+    emit sigLinkClicked(strCategory, QString(), machine().GetId());
+}
+
+void UIGInformationElement::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *pEvent)
+{
+    /* Only for left-button: */
+    if (pEvent->button() != Qt::LeftButton)
+        return;
+
+    /* Process left-button double-click: */
+    emit sigToggleElement(m_type, closed());
+}
+
+void UIGInformationElement::updateButtonVisibility()
+{
+    if (m_fHovered && !m_pButton->isVisible())
+        m_pButton->show();
+    else if (!m_fHovered && m_pButton->isVisible())
+        m_pButton->hide();
+}
+
+void UIGInformationElement::handleHoverEvent(QGraphicsSceneHoverEvent *pEvent)
+{
+    /* Not for 'preview' element type: */
+    if (m_type == DetailsElementType_Preview)
+        return;
+
+    /* Prepare variables: */
+    int iMargin = data(ElementData_Margin).toInt();
+    int iSpacing = data(ElementData_Spacing).toInt();
+    int iNameHeight = m_nameSize.height();
+    int iElementNameX = 2 * iMargin + m_pixmapSize.width() + iSpacing;
+    int iElementNameY = iNameHeight == m_iMinimumHeaderHeight ?
+                        iMargin : iMargin + (m_iMinimumHeaderHeight - iNameHeight) / 2;
+
+    /* Simulate hyperlink hovering: */
+    QPoint point = pEvent->pos().toPoint();
+    bool fNameHovered = QRect(QPoint(iElementNameX, iElementNameY), m_nameSize).contains(point);
+    if (   m_pSet->configurationAccessLevel() != ConfigurationAccessLevel_Null
+        && m_fNameHovered != fNameHovered)
+    {
+        m_fNameHovered = fNameHovered;
+        updateNameHoverLink();
+    }
+}
+
+void UIGInformationElement::updateNameHoverLink()
+{
+    if (m_fNameHovered)
+        setCursor(Qt::PointingHandCursor);
+    else
+        unsetCursor();
+    update();
+}
+
+void UIGInformationElement::updateAnimationParameters()
+{
+    /* Recalculate animation parameters: */
+    int iOpenedHeight = minimumHeightHint(false);
+    int iClosedHeight = minimumHeightHint(true);
+    int iAdditionalHeight = iOpenedHeight - iClosedHeight;
+    if (m_fClosed)
+        m_iAdditionalHeight = 0;
+    else
+        m_iAdditionalHeight = iAdditionalHeight;
+    m_pButton->setAnimationRange(0, iAdditionalHeight);
+}
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationElement.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationElement.h	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationElement.h	(revision 58611)
@@ -0,0 +1,228 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformationElement class declaration.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef __UIGInformationElement_h__
+#define __UIGInformationElement_h__
+
+/* Qt includes: */
+#include <QIcon>
+
+/* GUI includes: */
+#include "UIGInformationItem.h"
+#include "UIExtraDataDefs.h"
+
+/* Forward declarations: */
+class UIGInformationSet;
+class CMachine;
+class UIGraphicsRotatorButton;
+class UIGraphicsTextPane;
+class QTextLayout;
+class QStateMachine;
+class QPropertyAnimation;
+
+/* Typedefs: */
+typedef QPair<QString, QString> UITextTableLine;
+typedef QList<UITextTableLine> UITextTable;
+
+/* Details element
+ * for graphics details model/view architecture: */
+class UIGInformationElement : public UIGInformationItem
+{
+    Q_OBJECT;
+    Q_PROPERTY(int animationDarkness READ animationDarkness WRITE setAnimationDarkness);
+    Q_PROPERTY(int additionalHeight READ additionalHeight WRITE setAdditionalHeight);
+
+signals:
+
+    /* Notifiers: Hover stuff: */
+    void sigHoverEnter();
+    void sigHoverLeave();
+
+    /* Notifiers: Toggle stuff: */
+    void sigToggleElement(DetailsElementType type, bool fToggled);
+    void sigToggleElementFinished();
+
+    /* Notifier: Link-click stuff: */
+    void sigLinkClicked(const QString &strCategory, const QString &strControl, const QString &strId);
+
+public:
+
+    /* Graphics-item type: */
+    enum { Type = UIGInformationItemType_Element };
+    int type() const { return Type; }
+
+    /* Constructor/destructor: */
+    UIGInformationElement(UIGInformationSet *pParent, DetailsElementType type, bool fOpened);
+    ~UIGInformationElement();
+
+    /* API: Element type: */
+    DetailsElementType elementType() const { return m_type; }
+
+    /* API: Open/close stuff: */
+    bool closed() const { return m_fClosed; }
+    bool opened() const { return !m_fClosed; }
+    void close(bool fAnimated = true);
+    void open(bool fAnimated = true);
+
+    /* API: Update stuff: */
+    virtual void updateAppearance();
+
+    /* API: Animation stuff: */
+    void markAnimationFinished();
+
+protected slots:
+
+    /* Handlers: Toggle stuff: */
+    void sltToggleButtonClicked();
+    void sltElementToggleStart();
+    void sltElementToggleFinish(bool fToggled);
+
+    /** Handles children geometry changes. */
+    void sltUpdateGeometry() { updateGeometry(); }
+
+    /** Handles children anchor clicks. */
+    void sltHandleAnchorClicked(const QString &strAnchor);
+
+    /** Handles mount storage medium requests. */
+    void sltMountStorageMedium();
+
+protected:
+
+    /* Data enumerator: */
+    enum ElementData
+    {
+        /* Hints: */
+        ElementData_Margin,
+        ElementData_Spacing,
+        ElementData_MinimumTextColumnWidth
+    };
+
+    /** This event handler is delivered after the widget has been resized. */
+    void resizeEvent(QGraphicsSceneResizeEvent *pEvent);
+
+    /* Data provider: */
+    QVariant data(int iKey) const;
+
+    /* Helpers: Update stuff: */
+    void updateMinimumHeaderWidth();
+    void updateMinimumHeaderHeight();
+
+    /* API: Icon stuff: */
+    void setIcon(const QIcon &icon);
+
+    /* API: Name stuff: */
+    void setName(const QString &strName);
+
+    /* API: Text stuff: */
+    const UITextTable& text() const;
+    void setText(const UITextTable &text);
+
+    /* API: Machine stuff: */
+    const CMachine& machine();
+
+    /* Helpers: Layout stuff: */
+    int minimumHeaderWidth() const { return m_iMinimumHeaderWidth; }
+    int minimumHeaderHeight() const { return m_iMinimumHeaderHeight; }
+    int minimumWidthHint() const;
+    virtual int minimumHeightHint(bool fClosed) const;
+    int minimumHeightHint() const;
+    void updateLayout();
+
+    /* Helpers: Hover stuff: */
+    int animationDarkness() const { return m_iAnimationDarkness; }
+    void setAnimationDarkness(int iAnimationDarkness) { m_iAnimationDarkness = iAnimationDarkness; update(); }
+
+    /* Helpers: Animation stuff: */
+    void setAdditionalHeight(int iAdditionalHeight);
+    int additionalHeight() const { return m_iAdditionalHeight; }
+    UIGraphicsRotatorButton* button() const { return m_pButton; }
+    bool isAnimationRunning() const { return m_fAnimationRunning; }
+
+private:
+
+    /* API: Children stuff: */
+    void addItem(UIGInformationItem *pItem);
+    void removeItem(UIGInformationItem *pItem);
+    QList<UIGInformationItem*> items(UIGInformationItemType type) const;
+    bool hasItems(UIGInformationItemType type) const;
+    void clearItems(UIGInformationItemType type);
+
+    /* Helpers: Prepare stuff: */
+    void prepareElement();
+    void prepareButton();
+    void prepareTextPane();
+
+    /* Helpers: Paint stuff: */
+    void paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption, QWidget *pWidget = 0);
+    void paintDecorations(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption);
+    void paintElementInfo(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption);
+    void paintBackground(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption);
+
+    /* Handlers: Mouse stuff: */
+    void hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent);
+    void hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent);
+    void mousePressEvent(QGraphicsSceneMouseEvent *pEvent);
+    void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *pEvent);
+
+    /* Helpers: Mouse stuff: */
+    void updateButtonVisibility();
+    void handleHoverEvent(QGraphicsSceneHoverEvent *pEvent);
+    void updateNameHoverLink();
+
+    /* Helper: Animation stuff: */
+    void updateAnimationParameters();
+
+    /* Variables: */
+    UIGInformationSet *m_pSet;
+    DetailsElementType m_type;
+    QPixmap m_pixmap;
+    QString m_strName;
+    int m_iCornerRadius;
+    QFont m_nameFont;
+    QFont m_textFont;
+    QSize m_pixmapSize;
+    QSize m_nameSize;
+    QSize m_buttonSize;
+    int m_iMinimumHeaderWidth;
+    int m_iMinimumHeaderHeight;
+
+    /* Variables: Toggle-button stuff: */
+    UIGraphicsRotatorButton *m_pButton;
+    bool m_fClosed;
+    int m_iAdditionalHeight;
+    bool m_fAnimationRunning;
+
+    /* Variables: Text-pane stuff: */
+    UIGraphicsTextPane *m_pTextPane;
+
+    /* Variables: Hover stuff: */
+    bool m_fHovered;
+    bool m_fNameHovered;
+    QStateMachine *m_pHighlightMachine;
+    QPropertyAnimation *m_pForwardAnimation;
+    QPropertyAnimation *m_pBackwardAnimation;
+    int m_iAnimationDuration;
+    int m_iDefaultDarkness;
+    int m_iHighlightDarkness;
+    int m_iAnimationDarkness;
+
+    /* Friends: */
+    friend class UIGInformationSet;
+};
+
+#endif /* __UIGInformationElement_h__ */
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationElements.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationElements.cpp	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationElements.cpp	(revision 58611)
@@ -0,0 +1,959 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformationElement[Name] classes implementation.
+ */
+
+/*
+ * Copyright (C) 2012-2015 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifdef VBOX_WITH_PRECOMPILED_HEADERS
+# include <precomp.h>
+#else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+/* Qt includes: */
+# include <QDir>
+# include <QTimer>
+# include <QGraphicsLinearLayout>
+
+/* GUI includes: */
+# include "UIGInformationElements.h"
+# include "UIGInformationModel.h"
+# include "UIGInformationPreview.h"
+# include "UIGraphicsRotatorButton.h"
+# include "VBoxGlobal.h"
+# include "UIIconPool.h"
+# include "UIConverter.h"
+# include "UIGraphicsTextPane.h"
+# include "UIMessageCenter.h"
+
+/* COM includes: */
+# include "COMEnums.h"
+# include "CMachine.h"
+# include "CSystemProperties.h"
+# include "CVRDEServer.h"
+# include "CStorageController.h"
+# include "CMediumAttachment.h"
+# include "CAudioAdapter.h"
+# include "CNetworkAdapter.h"
+# include "CSerialPort.h"
+# include "CParallelPort.h"
+# include "CUSBController.h"
+# include "CUSBDeviceFilters.h"
+# include "CUSBDeviceFilter.h"
+# include "CSharedFolder.h"
+# include "CMedium.h"
+
+#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+
+UIGInformationUpdateTask::UIGInformationUpdateTask(const CMachine &machine)
+    : UITask(UITask::Type_DetailsPopulation)
+{
+    /* Store machine as property: */
+    setProperty("machine", QVariant::fromValue(machine));
+}
+
+UIGInformationElementInterface::UIGInformationElementInterface(UIGInformationSet *pParent, DetailsElementType type, bool fOpened)
+    : UIGInformationElement(pParent, type, fOpened)
+    , m_pTask(0)
+{
+    /* Assign corresponding icon: */
+    setIcon(gpConverter->toIcon(elementType()));
+
+    /* Listen for the global thread-pool: */
+    connect(vboxGlobal().threadPool(), SIGNAL(sigTaskComplete(UITask*)),
+            this, SLOT(sltUpdateAppearanceFinished(UITask*)));
+
+    /* Translate finally: */
+    retranslateUi();
+}
+
+void UIGInformationElementInterface::retranslateUi()
+{
+    /* Assign corresponding name: */
+    setName(gpConverter->toString(elementType()));
+}
+
+void UIGInformationElementInterface::updateAppearance()
+{
+    /* Call to base-class: */
+    UIGInformationElement::updateAppearance();
+
+    /* Prepare/start update task: */
+    if (!m_pTask)
+    {
+        /* Prepare update task: */
+        m_pTask = createUpdateTask();
+        /* Post task into global thread-pool: */
+        vboxGlobal().threadPool()->enqueueTask(m_pTask);
+    }
+}
+
+void UIGInformationElementInterface::sltUpdateAppearanceFinished(UITask *pTask)
+{
+    /* Make sure that is one of our tasks: */
+    if (pTask->type() != UITask::Type_DetailsPopulation)
+        return;
+
+    /* Skip unrelated tasks: */
+    if (m_pTask != pTask)
+        return;
+
+    /* Assign new text if changed: */
+    const UITextTable newText = pTask->property("table").value<UITextTable>();
+    if (text() != newText)
+        setText(newText);
+
+    /* Mark task processed: */
+    m_pTask = 0;
+
+    /* Notify listeners about update task complete: */
+    emit sigBuildDone();
+}
+
+
+UIGInformationElementPreview::UIGInformationElementPreview(UIGInformationSet *pParent, bool fOpened)
+    : UIGInformationElement(pParent, DetailsElementType_Preview, fOpened)
+{
+    /* Assign corresponding icon: */
+    setIcon(gpConverter->toIcon(elementType()));
+
+    /* Create layout: */
+    QGraphicsLinearLayout *pLayout = new QGraphicsLinearLayout;
+    AssertPtr(pLayout);
+    {
+        /* Prepare layout: */
+        const int iMargin = data(ElementData_Margin).toInt();
+        pLayout->setContentsMargins(iMargin, 2 * iMargin + minimumHeaderHeight(), iMargin, iMargin);
+        /* Assign layout to widget: */
+        setLayout(pLayout);
+        /* Create preview: */
+        m_pPreview = new UIGInformationPreview(this);
+        AssertPtr(m_pPreview);
+        {
+            /* Prepare preview: */
+            connect(m_pPreview, SIGNAL(sigSizeHintChanged()),
+                    this, SLOT(sltPreviewSizeHintChanged()));
+            /* Add preview into layout: */
+            pLayout->addItem(m_pPreview);
+        }
+    }
+
+    /* Set fixed size policy finally (after all content constructed): */
+    setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+
+    /* Translate finally: */
+    retranslateUi();
+}
+
+void UIGInformationElementPreview::sltPreviewSizeHintChanged()
+{
+    /* Recursively update size-hints: */
+    updateGeometry();
+    /* Update whole model layout: */
+    model()->updateLayout();
+}
+
+void UIGInformationElementPreview::retranslateUi()
+{
+    /* Assign corresponding name: */
+    setName(gpConverter->toString(elementType()));
+}
+
+int UIGInformationElementPreview::minimumWidthHint() const
+{
+    /* Prepare variables: */
+    int iMargin = data(ElementData_Margin).toInt();
+
+    /* Calculating proposed width: */
+    int iProposedWidth = 0;
+
+    /* Maximum between header width and preview width: */
+    iProposedWidth += qMax(minimumHeaderWidth(), m_pPreview->minimumSizeHint().toSize().width());
+
+    /* Two margins: */
+    iProposedWidth += 2 * iMargin;
+
+    /* Return result: */
+    return iProposedWidth;
+}
+
+int UIGInformationElementPreview::minimumHeightHint(bool fClosed) const
+{
+    /* Prepare variables: */
+    int iMargin = data(ElementData_Margin).toInt();
+
+    /* Calculating proposed height: */
+    int iProposedHeight = 0;
+
+    /* Two margins: */
+    iProposedHeight += 2 * iMargin;
+
+    /* Header height: */
+    iProposedHeight += minimumHeaderHeight();
+
+    /* Element is opened? */
+    if (!fClosed)
+    {
+        iProposedHeight += iMargin;
+        iProposedHeight += m_pPreview->minimumSizeHint().toSize().height();
+    }
+    else
+    {
+        /* Additional height during animation: */
+        if (button()->isAnimationRunning())
+            iProposedHeight += additionalHeight();
+    }
+
+    /* Return result: */
+    return iProposedHeight;
+}
+
+void UIGInformationElementPreview::updateLayout()
+{
+    /* Call to base-class: */
+    UIGInformationElement::updateLayout();
+
+    /* Show/hide preview: */
+    if (closed() && m_pPreview->isVisible())
+        m_pPreview->hide();
+    if (opened() && !m_pPreview->isVisible() && !isAnimationRunning())
+        m_pPreview->show();
+}
+
+void UIGInformationElementPreview::updateAppearance()
+{
+    /* Call to base-class: */
+    UIGInformationElement::updateAppearance();
+
+    /* Set new machine attribute directly: */
+    m_pPreview->setMachine(machine());
+    emit sigBuildDone();
+}
+
+
+void UIGInformationUpdateTaskGeneral::run()
+{
+    /* Acquire corresponding machine: */
+    CMachine machine = property("machine").value<CMachine>();
+    if (machine.isNull())
+        return;
+
+    /* Prepare table: */
+    UITextTable table;
+
+    /* Gather information: */
+    if (machine.GetAccessible())
+    {
+        /* Machine name: */
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Name", "details (general)"), machine.GetName());
+
+        /* Operating system type: */
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Operating System", "details (general)"),
+                                 vboxGlobal().vmGuestOSTypeDescription(machine.GetOSTypeId()));
+
+        /* Get groups: */
+        QStringList groups = machine.GetGroups().toList();
+        /* Do not show groups for machine which is in root group only: */
+        if (groups.size() == 1)
+            groups.removeAll("/");
+        /* If group list still not empty: */
+        if (!groups.isEmpty())
+        {
+            /* For every group: */
+            for (int i = 0; i < groups.size(); ++i)
+            {
+                /* Trim first '/' symbol: */
+                QString &strGroup = groups[i];
+                if (strGroup.startsWith("/") && strGroup != "/")
+                    strGroup.remove(0, 1);
+            }
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Groups", "details (general)"), groups.join(", "));
+        }
+    }
+    else
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Information Inaccessible", "details"), QString());
+
+    /* Save the table as property: */
+    setProperty("table", QVariant::fromValue(table));
+}
+
+
+void UIGInformationUpdateTaskSystem::run()
+{
+    /* Acquire corresponding machine: */
+    CMachine machine = property("machine").value<CMachine>();
+    if (machine.isNull())
+        return;
+
+    /* Prepare table: */
+    UITextTable table;
+
+    /* Gather information: */
+    if (machine.GetAccessible())
+    {
+        /* Base memory: */
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Base Memory", "details (system)"),
+                                 QApplication::translate("UIGInformation", "%1 MB", "details").arg(machine.GetMemorySize()));
+
+        /* CPU count: */
+        int cCPU = machine.GetCPUCount();
+        if (cCPU > 1)
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Processors", "details (system)"),
+                                     QString::number(cCPU));
+
+        /* CPU execution cap: */
+        int iCPUExecCap = machine.GetCPUExecutionCap();
+        if (iCPUExecCap < 100)
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Execution Cap", "details (system)"),
+                                     QApplication::translate("UIGInformation", "%1%", "details").arg(iCPUExecCap));
+
+        /* Boot-order: */
+        QStringList bootOrder;
+        for (ulong i = 1; i <= vboxGlobal().virtualBox().GetSystemProperties().GetMaxBootPosition(); ++i)
+        {
+            KDeviceType device = machine.GetBootOrder(i);
+            if (device == KDeviceType_Null)
+                continue;
+            bootOrder << gpConverter->toString(device);
+        }
+        if (bootOrder.isEmpty())
+            bootOrder << gpConverter->toString(KDeviceType_Null);
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Boot Order", "details (system)"), bootOrder.join(", "));
+
+        /* Acceleration: */
+        QStringList acceleration;
+        if (vboxGlobal().virtualBox().GetHost().GetProcessorFeature(KProcessorFeature_HWVirtEx))
+        {
+            /* VT-x/AMD-V: */
+            if (machine.GetHWVirtExProperty(KHWVirtExPropertyType_Enabled))
+            {
+                acceleration << QApplication::translate("UIGInformation", "VT-x/AMD-V", "details (system)");
+                /* Nested Paging (only when hw virt is enabled): */
+                if (machine.GetHWVirtExProperty(KHWVirtExPropertyType_NestedPaging))
+                    acceleration << QApplication::translate("UIGInformation", "Nested Paging", "details (system)");
+            }
+        }
+        if (machine.GetCPUProperty(KCPUPropertyType_PAE))
+            acceleration << QApplication::translate("UIGInformation", "PAE/NX", "details (system)");
+        switch (machine.GetEffectiveParavirtProvider())
+        {
+            case KParavirtProvider_Minimal: acceleration << QApplication::translate("UIGInformation", "Minimal Paravirtualization", "details (system)"); break;
+            case KParavirtProvider_HyperV:  acceleration << QApplication::translate("UIGInformation", "Hyper-V Paravirtualization", "details (system)"); break;
+            case KParavirtProvider_KVM:     acceleration << QApplication::translate("UIGInformation", "KVM Paravirtualization", "details (system)"); break;
+            default: break;
+        }
+        if (!acceleration.isEmpty())
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Acceleration", "details (system)"),
+                                     acceleration.join(", "));
+    }
+    else
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Information Inaccessible", "details"),
+                                 QString());
+
+    /* Save the table as property: */
+    setProperty("table", QVariant::fromValue(table));
+}
+
+
+void UIGInformationUpdateTaskDisplay::run()
+{
+    /* Acquire corresponding machine: */
+    CMachine machine = property("machine").value<CMachine>();
+    if (machine.isNull())
+        return;
+
+    /* Prepare table: */
+    UITextTable table;
+
+    /* Gather information: */
+    if (machine.GetAccessible())
+    {
+        /* Video memory: */
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Video Memory", "details (display)"),
+                                 QApplication::translate("UIGInformation", "%1 MB", "details").arg(machine.GetVRAMSize()));
+
+        /* Screen count: */
+        int cGuestScreens = machine.GetMonitorCount();
+        if (cGuestScreens > 1)
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Screens", "details (display)"),
+                                     QString::number(cGuestScreens));
+
+        /* Get scale-factor value: */
+        const QString strScaleFactor = machine.GetExtraData(UIExtraDataDefs::GUI_ScaleFactor);
+        {
+            /* Try to convert loaded data to double: */
+            bool fOk = false;
+            double dValue = strScaleFactor.toDouble(&fOk);
+            /* Invent the default value: */
+            if (!fOk || !dValue)
+                dValue = 1.0;
+            /* Append information: */
+            if (dValue != 1.0)
+                table << UITextTableLine(QApplication::translate("UIGInformation", "Scale-factor", "details (display)"),
+                                         QString::number(dValue, 'f', 2));
+        }
+
+#ifdef Q_WS_MAC
+        /* Get 'Unscaled HiDPI Video Output' mode value: */
+        const QString strUnscaledHiDPIMode = machine.GetExtraData(UIExtraDataDefs::GUI_HiDPI_UnscaledOutput);
+        {
+            /* Try to convert loaded data to bool: */
+            const bool fEnabled  = strUnscaledHiDPIMode.compare("true", Qt::CaseInsensitive) == 0 ||
+                                   strUnscaledHiDPIMode.compare("yes", Qt::CaseInsensitive) == 0 ||
+                                   strUnscaledHiDPIMode.compare("on", Qt::CaseInsensitive) == 0 ||
+                                   strUnscaledHiDPIMode == "1";
+            /* Append information: */
+            if (fEnabled)
+                table << UITextTableLine(QApplication::translate("UIGInformation", "Unscaled HiDPI Video Output", "details (display)"),
+                                         QApplication::translate("UIGInformation", "Enabled", "details (display/Unscaled HiDPI Video Output)"));
+        }
+#endif /* Q_WS_MAC */
+
+        QStringList acceleration;
+#ifdef VBOX_WITH_VIDEOHWACCEL
+        /* 2D acceleration: */
+        if (machine.GetAccelerate2DVideoEnabled())
+            acceleration << QApplication::translate("UIGInformation", "2D Video", "details (display)");
+#endif /* VBOX_WITH_VIDEOHWACCEL */
+        /* 3D acceleration: */
+        if (machine.GetAccelerate3DEnabled())
+            acceleration << QApplication::translate("UIGInformation", "3D", "details (display)");
+        if (!acceleration.isEmpty())
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Acceleration", "details (display)"),
+                                     acceleration.join(", "));
+
+        /* VRDE info: */
+        CVRDEServer srv = machine.GetVRDEServer();
+        if (!srv.isNull())
+        {
+            if (srv.GetEnabled())
+                table << UITextTableLine(QApplication::translate("UIGInformation", "Remote Desktop Server Port", "details (display/vrde)"),
+                                         srv.GetVRDEProperty("TCP/Ports"));
+            else
+                table << UITextTableLine(QApplication::translate("UIGInformation", "Remote Desktop Server", "details (display/vrde)"),
+                                         QApplication::translate("UIGInformation", "Disabled", "details (display/vrde/VRDE server)"));
+        }
+
+        /* Video Capture info: */
+        if (machine.GetVideoCaptureEnabled())
+        {
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Video Capture File", "details (display/video capture)"),
+                                     machine.GetVideoCaptureFile());
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Video Capture Attributes", "details (display/video capture)"),
+                                     QApplication::translate("UIGInformation", "Frame Size: %1x%2, Frame Rate: %3fps, Bit Rate: %4kbps")
+                                         .arg(machine.GetVideoCaptureWidth()).arg(machine.GetVideoCaptureHeight())
+                                         .arg(machine.GetVideoCaptureFPS()).arg(machine.GetVideoCaptureRate()));
+        }
+        else
+        {
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Video Capture", "details (display/video capture)"),
+                                     QApplication::translate("UIGInformation", "Disabled", "details (display/video capture)"));
+        }
+    }
+    else
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Information Inaccessible", "details"), QString());
+
+    /* Save the table as property: */
+    setProperty("table", QVariant::fromValue(table));
+}
+
+
+void UIGInformationUpdateTaskStorage::run()
+{
+    /* Acquire corresponding machine: */
+    CMachine machine = property("machine").value<CMachine>();
+    if (machine.isNull())
+        return;
+
+    /* Prepare table: */
+    UITextTable table;
+
+    /* Gather information: */
+    if (machine.GetAccessible())
+    {
+        /* Iterate over all the machine controllers: */
+        bool fSomeInfo = false;
+        foreach (const CStorageController &controller, machine.GetStorageControllers())
+        {
+            /* Add controller information: */
+            QString strControllerName = QApplication::translate("UIMachineSettingsStorage", "Controller: %1");
+            table << UITextTableLine(strControllerName.arg(controller.GetName()), QString());
+            fSomeInfo = true;
+            /* Populate map (its sorted!): */
+            QMap<StorageSlot, QString> attachmentsMap;
+            foreach (const CMediumAttachment &attachment, machine.GetMediumAttachmentsOfController(controller.GetName()))
+            {
+                /* Prepare current storage slot: */
+                StorageSlot attachmentSlot(controller.GetBus(), attachment.GetPort(), attachment.GetDevice());
+                AssertMsg(controller.isOk(),
+                          ("Unable to acquire controller data: %s\n",
+                           msgCenter().formatRC(controller.lastRC()).toAscii().constData()));
+                if (!controller.isOk())
+                    continue;
+                /* Prepare attachment information: */
+                QString strAttachmentInfo = vboxGlobal().details(attachment.GetMedium(), false, false);
+                /* That temporary hack makes sure 'Inaccessible' word is always bold: */
+                { // hack
+                    QString strInaccessibleString(VBoxGlobal::tr("Inaccessible", "medium"));
+                    QString strBoldInaccessibleString(QString("<b>%1</b>").arg(strInaccessibleString));
+                    strAttachmentInfo.replace(strInaccessibleString, strBoldInaccessibleString);
+                } // hack
+                /* Append 'device slot name' with 'device type name' for optical devices only: */
+                KDeviceType deviceType = attachment.GetType();
+                QString strDeviceType = deviceType == KDeviceType_DVD ?
+                            QApplication::translate("UIGInformation", "[Optical Drive]", "details (storage)") : QString();
+                if (!strDeviceType.isNull())
+                    strDeviceType.append(' ');
+                /* Insert that attachment information into the map: */
+                if (!strAttachmentInfo.isNull())
+                {
+                    /* Configure hovering anchors: */
+                    const QString strAnchorType = deviceType == KDeviceType_DVD || deviceType == KDeviceType_Floppy ? QString("mount") :
+                                                  deviceType == KDeviceType_HardDisk ? QString("attach") : QString();
+                    const CMedium medium = attachment.GetMedium();
+                    const QString strMediumLocation = medium.isNull() ? QString() : medium.GetLocation();
+                    attachmentsMap.insert(attachmentSlot,
+                                          QString("<a href=#%1,%2,%3,%4>%5</a>")
+                                                  .arg(strAnchorType,
+                                                       controller.GetName(),
+                                                       gpConverter->toString(attachmentSlot),
+                                                       strMediumLocation,
+                                                       strDeviceType + strAttachmentInfo));
+                }
+            }
+            /* Iterate over the sorted map: */
+            QList<StorageSlot> storageSlots = attachmentsMap.keys();
+            QList<QString> storageInfo = attachmentsMap.values();
+            for (int i = 0; i < storageSlots.size(); ++i)
+                table << UITextTableLine(QString("  ") + gpConverter->toString(storageSlots[i]), storageInfo[i]);
+        }
+        if (!fSomeInfo)
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Not Attached", "details (storage)"), QString());
+    }
+    else
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Information Inaccessible", "details"), QString());
+
+    /* Save the table as property: */
+    setProperty("table", QVariant::fromValue(table));
+}
+
+
+void UIGInformationUpdateTaskAudio::run()
+{
+    /* Acquire corresponding machine: */
+    CMachine machine = property("machine").value<CMachine>();
+    if (machine.isNull())
+        return;
+
+    /* Prepare table: */
+    UITextTable table;
+
+    /* Gather information: */
+    if (machine.GetAccessible())
+    {
+        const CAudioAdapter &audio = machine.GetAudioAdapter();
+        if (audio.GetEnabled())
+        {
+            /* Driver: */
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Host Driver", "details (audio)"),
+                                     gpConverter->toString(audio.GetAudioDriver()));
+
+            /* Controller: */
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Controller", "details (audio)"),
+                                     gpConverter->toString(audio.GetAudioController()));
+        }
+        else
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Disabled", "details (audio)"),
+                                     QString());
+    }
+    else
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Information Inaccessible", "details"),
+                                 QString());
+
+    /* Save the table as property: */
+    setProperty("table", QVariant::fromValue(table));
+}
+
+
+void UIGInformationUpdateTaskNetwork::run()
+{
+    /* Acquire corresponding machine: */
+    CMachine machine = property("machine").value<CMachine>();
+    if (machine.isNull())
+        return;
+
+    /* Prepare table: */
+    UITextTable table;
+
+    /* Gather information: */
+    if (machine.GetAccessible())
+    {
+        /* Iterate over all the adapters: */
+        bool fSomeInfo = false;
+        ulong uSount = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(KChipsetType_PIIX3);
+        for (ulong uSlot = 0; uSlot < uSount; ++uSlot)
+        {
+            const CNetworkAdapter &adapter = machine.GetNetworkAdapter(uSlot);
+            if (adapter.GetEnabled())
+            {
+                KNetworkAttachmentType type = adapter.GetAttachmentType();
+                QString strAttachmentType = gpConverter->toString(adapter.GetAdapterType())
+                                            .replace(QRegExp("\\s\\(.+\\)"), " (%1)");
+                switch (type)
+                {
+                    case KNetworkAttachmentType_Bridged:
+                    {
+                        strAttachmentType = strAttachmentType.arg(QApplication::translate("UIGInformation", "Bridged Adapter, %1", "details (network)")
+                                                                  .arg(adapter.GetBridgedInterface()));
+                        break;
+                    }
+                    case KNetworkAttachmentType_Internal:
+                    {
+                        strAttachmentType = strAttachmentType.arg(QApplication::translate("UIGInformation", "Internal Network, '%1'", "details (network)")
+                                                                  .arg(adapter.GetInternalNetwork()));
+                        break;
+                    }
+                    case KNetworkAttachmentType_HostOnly:
+                    {
+                        strAttachmentType = strAttachmentType.arg(QApplication::translate("UIGInformation", "Host-only Adapter, '%1'", "details (network)")
+                                                                  .arg(adapter.GetHostOnlyInterface()));
+                        break;
+                    }
+                    case KNetworkAttachmentType_Generic:
+                    {
+                        QString strGenericDriverProperties(summarizeGenericProperties(adapter));
+                        strAttachmentType = strGenericDriverProperties.isNull() ?
+                                  strAttachmentType.arg(QApplication::translate("UIGInformation", "Generic Driver, '%1'", "details (network)").arg(adapter.GetGenericDriver())) :
+                                  strAttachmentType.arg(QApplication::translate("UIGInformation", "Generic Driver, '%1' { %2 }", "details (network)")
+                                                        .arg(adapter.GetGenericDriver(), strGenericDriverProperties));
+                        break;
+                    }
+                    case KNetworkAttachmentType_NATNetwork:
+                    {
+                        strAttachmentType = strAttachmentType.arg(QApplication::translate("UIGInformation", "NAT Network, '%1'", "details (network)")
+                                                                  .arg(adapter.GetNATNetwork()));
+                        break;
+                    }
+                    default:
+                    {
+                        strAttachmentType = strAttachmentType.arg(gpConverter->toString(type));
+                        break;
+                    }
+                }
+                table << UITextTableLine(QApplication::translate("UIGInformation", "Adapter %1", "details (network)").arg(adapter.GetSlot() + 1), strAttachmentType);
+                fSomeInfo = true;
+            }
+        }
+        if (!fSomeInfo)
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Disabled", "details (network/adapter)"), QString());
+    }
+    else
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Information Inaccessible", "details"), QString());
+
+    /* Save the table as property: */
+    setProperty("table", QVariant::fromValue(table));
+}
+
+/* static */
+QString UIGInformationUpdateTaskNetwork::summarizeGenericProperties(const CNetworkAdapter &adapter)
+{
+    QVector<QString> names;
+    QVector<QString> props;
+    props = adapter.GetProperties(QString(), names);
+    QString strResult;
+    for (int i = 0; i < names.size(); ++i)
+    {
+        strResult += names[i] + "=" + props[i];
+        if (i < names.size() - 1)
+            strResult += ", ";
+    }
+    return strResult;
+}
+
+
+void UIGInformationUpdateTaskSerial::run()
+{
+    /* Acquire corresponding machine: */
+    CMachine machine = property("machine").value<CMachine>();
+    if (machine.isNull())
+        return;
+
+    /* Prepare table: */
+    UITextTable table;
+
+    /* Gather information: */
+    if (machine.GetAccessible())
+    {
+        /* Iterate over all the ports: */
+        bool fSomeInfo = false;
+        ulong uCount = vboxGlobal().virtualBox().GetSystemProperties().GetSerialPortCount();
+        for (ulong uSlot = 0; uSlot < uCount; ++uSlot)
+        {
+            const CSerialPort &port = machine.GetSerialPort(uSlot);
+            if (port.GetEnabled())
+            {
+                KPortMode mode = port.GetHostMode();
+                QString data = vboxGlobal().toCOMPortName(port.GetIRQ(), port.GetIOBase()) + ", ";
+                if (mode == KPortMode_HostPipe || mode == KPortMode_HostDevice ||
+                    mode == KPortMode_RawFile || mode == KPortMode_TCP)
+                    data += QString("%1 (%2)").arg(gpConverter->toString(mode)).arg(QDir::toNativeSeparators(port.GetPath()));
+                else
+                    data += gpConverter->toString(mode);
+                table << UITextTableLine(QApplication::translate("UIGInformation", "Port %1", "details (serial)").arg(port.GetSlot() + 1), data);
+                fSomeInfo = true;
+            }
+        }
+        if (!fSomeInfo)
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Disabled", "details (serial)"), QString());
+    }
+    else
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Information Inaccessible", "details"), QString());
+
+    /* Save the table as property: */
+    setProperty("table", QVariant::fromValue(table));
+}
+
+
+#ifdef VBOX_WITH_PARALLEL_PORTS
+void UIGInformationUpdateTaskParallel::run()
+{
+    /* Acquire corresponding machine: */
+    CMachine machine = property("machine").value<CMachine>();
+    if (machine.isNull())
+        return;
+
+    /* Prepare table: */
+    UITextTable table;
+
+    /* Gather information: */
+    if (machine.GetAccessible())
+    {
+        bool fSomeInfo = false;
+        ulong uCount = vboxGlobal().virtualBox().GetSystemProperties().GetParallelPortCount();
+        for (ulong uSlot = 0; uSlot < uCount; ++uSlot)
+        {
+            const CParallelPort &port = machine.GetParallelPort(uSlot);
+            if (port.GetEnabled())
+            {
+                QString data = vboxGlobal().toLPTPortName(port.GetIRQ(), port.GetIOBase()) +
+                               QString(" (<nobr>%1</nobr>)").arg(QDir::toNativeSeparators(port.GetPath()));
+                table << UITextTableLine(QApplication::translate("UIGInformation", "Port %1", "details (parallel)").arg(port.GetSlot() + 1), data);
+                fSomeInfo = true;
+            }
+        }
+        if (!fSomeInfo)
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Disabled", "details (parallel)"), QString());
+    }
+    else
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Information Inaccessible", "details"), QString());
+
+    /* Save the table as property: */
+    setProperty("table", QVariant::fromValue(table));
+}
+#endif /* VBOX_WITH_PARALLEL_PORTS */
+
+
+void UIGInformationUpdateTaskUSB::run()
+{
+    /* Acquire corresponding machine: */
+    CMachine machine = property("machine").value<CMachine>();
+    if (machine.isNull())
+        return;
+
+    /* Prepare table: */
+    UITextTable table;
+
+    /* Gather information: */
+    if (machine.GetAccessible())
+    {
+        /* Iterate over all the USB filters: */
+        const CUSBDeviceFilters &filters = machine.GetUSBDeviceFilters();
+        if (!filters.isNull() && machine.GetUSBProxyAvailable())
+        {
+            const CUSBDeviceFilters flts = machine.GetUSBDeviceFilters();
+            const CUSBControllerVector controllers = machine.GetUSBControllers();
+            if (!flts.isNull() && !controllers.isEmpty())
+            {
+                /* USB Controllers info: */
+                QStringList controllerList;
+                foreach (const CUSBController &controller, controllers)
+                    controllerList << gpConverter->toString(controller.GetType());
+                table << UITextTableLine(QApplication::translate("UIGInformation", "USB Controller", "details (usb)"),
+                                          controllerList.join(", "));
+                /* USB Device Filters info: */
+                const CUSBDeviceFilterVector &coll = flts.GetDeviceFilters();
+                uint uActive = 0;
+                for (int i = 0; i < coll.size(); ++i)
+                    if (coll[i].GetActive())
+                        ++uActive;
+                table << UITextTableLine(QApplication::translate("UIGInformation", "Device Filters", "details (usb)"),
+                                         QApplication::translate("UIGInformation", "%1 (%2 active)", "details (usb)").arg(coll.size()).arg(uActive));
+            }
+            else
+                table << UITextTableLine(QApplication::translate("UIGInformation", "Disabled", "details (usb)"), QString());
+        }
+        else
+            table << UITextTableLine(QApplication::translate("UIGInformation", "USB Controller Inaccessible", "details (usb)"), QString());
+    }
+    else
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Information Inaccessible", "details"), QString());
+
+    /* Save the table as property: */
+    setProperty("table", QVariant::fromValue(table));
+}
+
+
+void UIGInformationUpdateTaskSF::run()
+{
+    /* Acquire corresponding machine: */
+    CMachine machine = property("machine").value<CMachine>();
+    if (machine.isNull())
+        return;
+
+    /* Prepare table: */
+    UITextTable table;
+
+    /* Gather information: */
+    if (machine.GetAccessible())
+    {
+        /* Iterate over all the shared folders: */
+        ulong uCount = machine.GetSharedFolders().size();
+        if (uCount > 0)
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Shared Folders", "details (shared folders)"), QString::number(uCount));
+        else
+            table << UITextTableLine(QApplication::translate("UIGInformation", "None", "details (shared folders)"), QString());
+    }
+    else
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Information Inaccessible", "details"), QString());
+
+    /* Save the table as property: */
+    setProperty("table", QVariant::fromValue(table));
+}
+
+
+void UIGInformationUpdateTaskUI::run()
+{
+    /* Acquire corresponding machine: */
+    CMachine machine = property("machine").value<CMachine>();
+    if (machine.isNull())
+        return;
+
+    /* Prepare table: */
+    UITextTable table;
+
+    /* Gather information: */
+    if (machine.GetAccessible())
+    {
+#ifndef Q_WS_MAC
+        /* Get menu-bar availability status: */
+        const QString strMenubarEnabled = machine.GetExtraData(UIExtraDataDefs::GUI_MenuBar_Enabled);
+        {
+            /* Try to convert loaded data to bool: */
+            const bool fEnabled = !(strMenubarEnabled.compare("false", Qt::CaseInsensitive) == 0 ||
+                                    strMenubarEnabled.compare("no", Qt::CaseInsensitive) == 0 ||
+                                    strMenubarEnabled.compare("off", Qt::CaseInsensitive) == 0 ||
+                                    strMenubarEnabled == "0");
+            /* Append information: */
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Menu-bar", "details (user interface)"),
+                                     fEnabled ? QApplication::translate("UIGInformation", "Enabled", "details (user interface/menu-bar)") :
+                                                QApplication::translate("UIGInformation", "Disabled", "details (user interface/menu-bar)"));
+        }
+#endif /* !Q_WS_MAC */
+
+        /* Get status-bar availability status: */
+        const QString strStatusbarEnabled = machine.GetExtraData(UIExtraDataDefs::GUI_StatusBar_Enabled);
+        {
+            /* Try to convert loaded data to bool: */
+            const bool fEnabled = !(strStatusbarEnabled.compare("false", Qt::CaseInsensitive) == 0 ||
+                                    strStatusbarEnabled.compare("no", Qt::CaseInsensitive) == 0 ||
+                                    strStatusbarEnabled.compare("off", Qt::CaseInsensitive) == 0 ||
+                                    strStatusbarEnabled == "0");
+            /* Append information: */
+            table << UITextTableLine(QApplication::translate("UIGInformation", "Status-bar", "details (user interface)"),
+                                     fEnabled ? QApplication::translate("UIGInformation", "Enabled", "details (user interface/status-bar)") :
+                                                QApplication::translate("UIGInformation", "Disabled", "details (user interface/status-bar)"));
+        }
+
+#ifndef Q_WS_MAC
+        /* Get mini-toolbar availability status: */
+        const QString strMiniToolbarEnabled = machine.GetExtraData(UIExtraDataDefs::GUI_ShowMiniToolBar);
+        {
+            /* Try to convert loaded data to bool: */
+            const bool fEnabled = !(strMiniToolbarEnabled.compare("false", Qt::CaseInsensitive) == 0 ||
+                                    strMiniToolbarEnabled.compare("no", Qt::CaseInsensitive) == 0 ||
+                                    strMiniToolbarEnabled.compare("off", Qt::CaseInsensitive) == 0 ||
+                                    strMiniToolbarEnabled == "0");
+            /* Append information: */
+            if (fEnabled)
+            {
+                /* Get mini-toolbar position: */
+                const QString &strMiniToolbarPosition = machine.GetExtraData(UIExtraDataDefs::GUI_MiniToolBarAlignment);
+                {
+                    /* Try to convert loaded data to alignment: */
+                    switch (gpConverter->fromInternalString<MiniToolbarAlignment>(strMiniToolbarPosition))
+                    {
+                        /* Append information: */
+                        case MiniToolbarAlignment_Top:
+                            table << UITextTableLine(QApplication::translate("UIGInformation", "Mini-toolbar Position", "details (user interface)"),
+                                                     QApplication::translate("UIGInformation", "Top", "details (user interface/mini-toolbar position)"));
+                            break;
+                        /* Append information: */
+                        case MiniToolbarAlignment_Bottom:
+                            table << UITextTableLine(QApplication::translate("UIGInformation", "Mini-toolbar Position", "details (user interface)"),
+                                                     QApplication::translate("UIGInformation", "Bottom", "details (user interface/mini-toolbar position)"));
+                            break;
+                    }
+                }
+            }
+            /* Append information: */
+            else
+                table << UITextTableLine(QApplication::translate("UIGInformation", "Mini-toolbar", "details (user interface)"),
+                                         QApplication::translate("UIGInformation", "Disabled", "details (user interface/mini-toolbar)"));
+        }
+#endif /* !Q_WS_MAC */
+    }
+    else
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Information Inaccessible", "details"), QString());
+
+    /* Save the table as property: */
+    setProperty("table", QVariant::fromValue(table));
+}
+
+
+void UIGInformationUpdateTaskDescription::run()
+{
+    /* Acquire corresponding machine: */
+    CMachine machine = property("machine").value<CMachine>();
+    if (machine.isNull())
+        return;
+
+    /* Prepare table: */
+    UITextTable table;
+
+    /* Gather information: */
+    if (machine.GetAccessible())
+    {
+        /* Get description: */
+        const QString &strDesc = machine.GetDescription();
+        if (!strDesc.isEmpty())
+            table << UITextTableLine(strDesc, QString());
+        else
+            table << UITextTableLine(QApplication::translate("UIGInformation", "None", "details (description)"), QString());
+    }
+    else
+        table << UITextTableLine(QApplication::translate("UIGInformation", "Information Inaccessible", "details"), QString());
+
+    /* Save the table as property: */
+    setProperty("table", QVariant::fromValue(table));
+}
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationElements.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationElements.h	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationElements.h	(revision 58611)
@@ -0,0 +1,552 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformationElement[Name] classes declaration.
+ */
+
+/*
+ * Copyright (C) 2012-2015 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ___UIGInformationElements_h___
+#define ___UIGInformationElements_h___
+
+/* GUI includes: */
+#include "UIThreadPool.h"
+#include "UIGInformationElement.h"
+
+/* Forward declarations: */
+class UIGInformationPreview;
+class CNetworkAdapter;
+
+
+/** UITask extension used as update task for the details-element. */
+class UIGInformationUpdateTask : public UITask
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs update task taking @a machine as data. */
+    UIGInformationUpdateTask(const CMachine &machine);
+};
+
+/** UIGInformationElement extension used as a wrapping interface to
+  * extend base-class with async functionality performed by the COM worker-threads. */
+class UIGInformationElementInterface : public UIGInformationElement
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs details-element interface for passed @a pParent set.
+      * @param type    brings the details-element type this element belongs to.
+      * @param fOpened brings whether the details-element should be visually opened. */
+    UIGInformationElementInterface(UIGInformationSet *pParent, DetailsElementType type, bool fOpened);
+
+protected:
+
+    /** Performs translation. */
+    virtual void retranslateUi();
+
+    /** Updates appearance. */
+    virtual void updateAppearance();
+
+    /** Creates update task. */
+    virtual UITask* createUpdateTask() = 0;
+
+private slots:
+
+    /** Handles the signal about update @a pTask is finished. */
+    virtual void sltUpdateAppearanceFinished(UITask *pTask);
+
+private:
+
+    /** Holds the instance of the update task. */
+    UITask *m_pTask;
+};
+
+
+/** UIGInformationElementInterface extension for the details-element type 'Preview'. */
+class UIGInformationElementPreview : public UIGInformationElement
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs details-element interface for passed @a pParent set.
+      * @param fOpened brings whether the details-element should be opened. */
+    UIGInformationElementPreview(UIGInformationSet *pParent, bool fOpened);
+
+private slots:
+
+    /** Handles preview size-hint changes. */
+    void sltPreviewSizeHintChanged();
+
+private:
+
+    /** Performs translation. */
+    virtual void retranslateUi();
+
+    /** Returns minimum width hint. */
+    int minimumWidthHint() const;
+    /** Returns minimum height hint.
+      * @param fClosed allows to specify whether the hint should
+      *                be calculated for the closed element. */
+    int minimumHeightHint(bool fClosed) const;
+    /** Updates layout. */
+    void updateLayout();
+
+    /** Updates appearance. */
+    void updateAppearance();
+
+    /** Holds the instance of VM preview. */
+    UIGInformationPreview *m_pPreview;
+};
+
+
+/** UITask extension used as update task for the details-element type 'General'. */
+class UIGInformationUpdateTaskGeneral : public UIGInformationUpdateTask
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs update task passing @a machine to the base-class. */
+    UIGInformationUpdateTaskGeneral(const CMachine &machine)
+        : UIGInformationUpdateTask(machine) {}
+
+private:
+
+    /** Contains update task body. */
+    void run();
+};
+
+/** UIGInformationElementInterface extension for the details-element type 'General'. */
+class UIGInformationElementGeneral : public UIGInformationElementInterface
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs details-element object for passed @a pParent set.
+      * @param fOpened brings whether the details-element should be visually opened. */
+    UIGInformationElementGeneral(UIGInformationSet *pParent, bool fOpened)
+        : UIGInformationElementInterface(pParent, DetailsElementType_General, fOpened) {}
+
+private:
+
+    /** Creates update task for this element. */
+    UITask* createUpdateTask() { return new UIGInformationUpdateTaskGeneral(machine()); }
+};
+
+
+/** UITask extension used as update task for the details-element type 'System'. */
+class UIGInformationUpdateTaskSystem : public UIGInformationUpdateTask
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs update task passing @a machine to the base-class. */
+    UIGInformationUpdateTaskSystem(const CMachine &machine)
+        : UIGInformationUpdateTask(machine) {}
+
+private:
+
+    /** Contains update task body. */
+    void run();
+};
+
+/** UIGInformationElementInterface extension for the details-element type 'System'. */
+class UIGInformationElementSystem : public UIGInformationElementInterface
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs details-element object for passed @a pParent set.
+      * @param fOpened brings whether the details-element should be visually opened. */
+    UIGInformationElementSystem(UIGInformationSet *pParent, bool fOpened)
+        : UIGInformationElementInterface(pParent, DetailsElementType_System, fOpened) {}
+
+private:
+
+    /** Creates update task for this element. */
+    UITask* createUpdateTask() { return new UIGInformationUpdateTaskSystem(machine()); }
+};
+
+
+/** UITask extension used as update task for the details-element type 'Display'. */
+class UIGInformationUpdateTaskDisplay : public UIGInformationUpdateTask
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs update task passing @a machine to the base-class. */
+    UIGInformationUpdateTaskDisplay(const CMachine &machine)
+        : UIGInformationUpdateTask(machine) {}
+
+private:
+
+    /** Contains update task body. */
+    void run();
+};
+
+/** UIGInformationElementInterface extension for the details-element type 'Display'. */
+class UIGInformationElementDisplay : public UIGInformationElementInterface
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs details-element object for passed @a pParent set.
+      * @param fOpened brings whether the details-element should be visually opened. */
+    UIGInformationElementDisplay(UIGInformationSet *pParent, bool fOpened)
+        : UIGInformationElementInterface(pParent, DetailsElementType_Display, fOpened) {}
+
+private:
+
+    /** Creates update task for this element. */
+    UITask* createUpdateTask() { return new UIGInformationUpdateTaskDisplay(machine()); }
+};
+
+
+/** UITask extension used as update task for the details-element type 'Storage'. */
+class UIGInformationUpdateTaskStorage : public UIGInformationUpdateTask
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs update task passing @a machine to the base-class. */
+    UIGInformationUpdateTaskStorage(const CMachine &machine)
+        : UIGInformationUpdateTask(machine) {}
+
+private:
+
+    /** Contains update task body. */
+    void run();
+};
+
+/** UIGInformationElementInterface extension for the details-element type 'Storage'. */
+class UIGInformationElementStorage : public UIGInformationElementInterface
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs details-element object for passed @a pParent set.
+      * @param fOpened brings whether the details-element should be visually opened. */
+    UIGInformationElementStorage(UIGInformationSet *pParent, bool fOpened)
+        : UIGInformationElementInterface(pParent, DetailsElementType_Storage, fOpened) {}
+
+private:
+
+    /** Creates update task for this element. */
+    UITask* createUpdateTask() { return new UIGInformationUpdateTaskStorage(machine()); }
+};
+
+
+/** UITask extension used as update task for the details-element type 'Audio'. */
+class UIGInformationUpdateTaskAudio : public UIGInformationUpdateTask
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs update task passing @a machine to the base-class. */
+    UIGInformationUpdateTaskAudio(const CMachine &machine)
+        : UIGInformationUpdateTask(machine) {}
+
+private:
+
+    /** Contains update task body. */
+    void run();
+};
+
+/** UIGInformationElementInterface extension for the details-element type 'Audio'. */
+class UIGInformationElementAudio : public UIGInformationElementInterface
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs details-element object for passed @a pParent set.
+      * @param fOpened brings whether the details-element should be visually opened. */
+    UIGInformationElementAudio(UIGInformationSet *pParent, bool fOpened)
+        : UIGInformationElementInterface(pParent, DetailsElementType_Audio, fOpened) {}
+
+private:
+
+    /** Creates update task for this element. */
+    UITask* createUpdateTask() { return new UIGInformationUpdateTaskAudio(machine()); }
+};
+
+
+/** UITask extension used as update task for the details-element type 'Network'. */
+class UIGInformationUpdateTaskNetwork : public UIGInformationUpdateTask
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs update task passing @a machine to the base-class. */
+    UIGInformationUpdateTaskNetwork(const CMachine &machine)
+        : UIGInformationUpdateTask(machine) {}
+
+private:
+
+    /** Contains update task body. */
+    void run();
+
+    /** Summarizes generic properties. */
+    static QString summarizeGenericProperties(const CNetworkAdapter &adapter);
+};
+
+/** UIGInformationElementInterface extension for the details-element type 'Network'. */
+class UIGInformationElementNetwork : public UIGInformationElementInterface
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs details-element object for passed @a pParent set.
+      * @param fOpened brings whether the details-element should be visually opened. */
+    UIGInformationElementNetwork(UIGInformationSet *pParent, bool fOpened)
+        : UIGInformationElementInterface(pParent, DetailsElementType_Network, fOpened) {}
+
+private:
+
+    /** Creates update task for this element. */
+    UITask* createUpdateTask() { return new UIGInformationUpdateTaskNetwork(machine()); }
+};
+
+
+/** UITask extension used as update task for the details-element type 'Serial'. */
+class UIGInformationUpdateTaskSerial : public UIGInformationUpdateTask
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs update task passing @a machine to the base-class. */
+    UIGInformationUpdateTaskSerial(const CMachine &machine)
+        : UIGInformationUpdateTask(machine) {}
+
+private:
+
+    /** Contains update task body. */
+    void run();
+};
+
+/** UIGInformationElementInterface extension for the details-element type 'Serial'. */
+class UIGInformationElementSerial : public UIGInformationElementInterface
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs details-element object for passed @a pParent set.
+      * @param fOpened brings whether the details-element should be visually opened. */
+    UIGInformationElementSerial(UIGInformationSet *pParent, bool fOpened)
+        : UIGInformationElementInterface(pParent, DetailsElementType_Serial, fOpened) {}
+
+private:
+
+    /** Creates update task for this element. */
+    UITask* createUpdateTask() { return new UIGInformationUpdateTaskSerial(machine()); }
+};
+
+
+#ifdef VBOX_WITH_PARALLEL_PORTS
+/** UITask extension used as update task for the details-element type 'Parallel'. */
+class UIGInformationUpdateTaskParallel : public UIGInformationUpdateTask
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs update task passing @a machine to the base-class. */
+    UIGInformationUpdateTaskParallel(const CMachine &machine)
+        : UIGInformationUpdateTask(machine) {}
+
+private:
+
+    /** Contains update task body. */
+    void run();
+};
+
+/** UIGInformationElementInterface extension for the details-element type 'Parallel'. */
+class UIGInformationElementParallel : public UIGInformationElementInterface
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs details-element object for passed @a pParent set.
+      * @param fOpened brings whether the details-element should be visually opened. */
+    UIGInformationElementParallel(UIGInformationSet *pParent, bool fOpened)
+        : UIGInformationElementInterface(pParent, DetailsElementType_Parallel, fOpened) {}
+
+private:
+
+    /** Creates update task for this element. */
+    UITask* createUpdateTask() { return new UIGInformationUpdateTaskParallel(machine()); }
+};
+#endif /* VBOX_WITH_PARALLEL_PORTS */
+
+
+/** UITask extension used as update task for the details-element type 'USB'. */
+class UIGInformationUpdateTaskUSB : public UIGInformationUpdateTask
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs update task passing @a machine to the base-class. */
+    UIGInformationUpdateTaskUSB(const CMachine &machine)
+        : UIGInformationUpdateTask(machine) {}
+
+private:
+
+    /** Contains update task body. */
+    void run();
+};
+
+/** UIGInformationElementInterface extension for the details-element type 'USB'. */
+class UIGInformationElementUSB : public UIGInformationElementInterface
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs details-element object for passed @a pParent set.
+      * @param fOpened brings whether the details-element should be visually opened. */
+    UIGInformationElementUSB(UIGInformationSet *pParent, bool fOpened)
+        : UIGInformationElementInterface(pParent, DetailsElementType_USB, fOpened) {}
+
+private:
+
+    /** Creates update task for this element. */
+    UITask* createUpdateTask() { return new UIGInformationUpdateTaskUSB(machine()); }
+};
+
+
+/** UITask extension used as update task for the details-element type 'SF'. */
+class UIGInformationUpdateTaskSF : public UIGInformationUpdateTask
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs update task passing @a machine to the base-class. */
+    UIGInformationUpdateTaskSF(const CMachine &machine)
+        : UIGInformationUpdateTask(machine) {}
+
+private:
+
+    /** Contains update task body. */
+    void run();
+};
+
+/** UIGInformationElementInterface extension for the details-element type 'SF'. */
+class UIGInformationElementSF : public UIGInformationElementInterface
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs details-element object for passed @a pParent set.
+      * @param fOpened brings whether the details-element should be visually opened. */
+    UIGInformationElementSF(UIGInformationSet *pParent, bool fOpened)
+        : UIGInformationElementInterface(pParent, DetailsElementType_SF, fOpened) {}
+
+private:
+
+    /** Creates update task for this element. */
+    UITask* createUpdateTask() { return new UIGInformationUpdateTaskSF(machine()); }
+};
+
+
+/** UITask extension used as update task for the details-element type 'UI'. */
+class UIGInformationUpdateTaskUI : public UIGInformationUpdateTask
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs update task passing @a machine to the base-class. */
+    UIGInformationUpdateTaskUI(const CMachine &machine)
+        : UIGInformationUpdateTask(machine) {}
+
+private:
+
+    /** Contains update task body. */
+    void run();
+};
+
+/** UIGInformationElementInterface extension for the details-element type 'UI'. */
+class UIGInformationElementUI : public UIGInformationElementInterface
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs details-element object for passed @a pParent set.
+      * @param fOpened brings whether the details-element should be visually opened. */
+    UIGInformationElementUI(UIGInformationSet *pParent, bool fOpened)
+        : UIGInformationElementInterface(pParent, DetailsElementType_UI, fOpened) {}
+
+private:
+
+    /** Creates update task for this element. */
+    UITask* createUpdateTask() { return new UIGInformationUpdateTaskUI(machine()); }
+};
+
+
+/** UITask extension used as update task for the details-element type 'Description'. */
+class UIGInformationUpdateTaskDescription : public UIGInformationUpdateTask
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs update task passing @a machine to the base-class. */
+    UIGInformationUpdateTaskDescription(const CMachine &machine)
+        : UIGInformationUpdateTask(machine) {}
+
+private:
+
+    /** Contains update task body. */
+    void run();
+};
+
+/** UIGInformationElementInterface extension for the details-element type 'Description'. */
+class UIGInformationElementDescription : public UIGInformationElementInterface
+{
+    Q_OBJECT;
+
+public:
+
+    /** Constructs details-element object for passed @a pParent set.
+      * @param fOpened brings whether the details-element should be visually opened. */
+    UIGInformationElementDescription(UIGInformationSet *pParent, bool fOpened)
+        : UIGInformationElementInterface(pParent, DetailsElementType_Description, fOpened) {}
+
+private:
+
+    /** Creates update task for this element. */
+    UITask* createUpdateTask() { return new UIGInformationUpdateTaskDescription(machine()); }
+};
+
+#endif /* !___UIGInformationElements_h___ */
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationGroup.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationGroup.cpp	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationGroup.cpp	(revision 58611)
@@ -0,0 +1,306 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformationGroup class implementation.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifdef VBOX_WITH_PRECOMPILED_HEADERS
+# include <precomp.h>
+#else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+/* Qt include: */
+# include <QGraphicsScene>
+
+/* GUI includes: */
+# include "UIGInformationGroup.h"
+# include "UIGInformationSet.h"
+# include "UIGInformationModel.h"
+# include "UIExtraDataManager.h"
+# include "VBoxGlobal.h"
+# include "UIVMItem.h"
+
+#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+
+UIGInformationGroup::UIGInformationGroup(QGraphicsScene *pParent)
+    : UIGInformationItem(0)
+    , m_iPreviousMinimumWidthHint(0)
+    , m_iPreviousMinimumHeightHint(0)
+    , m_pBuildStep(0)
+{
+    /* Add group to the parent scene: */
+    pParent->addItem(this);
+
+    /* Prepare connections: */
+    prepareConnections();
+}
+
+UIGInformationGroup::~UIGInformationGroup()
+{
+    /* Cleanup items: */
+    clearItems();
+}
+
+void UIGInformationGroup::buildGroup(const QList<UIVMItem*> &machineItems)
+{
+    /* Remember passed machine-items: */
+    m_machineItems = machineItems;
+
+    /* Cleanup superflous items: */
+    bool fCleanupPerformed = m_items.size() > m_machineItems.size();
+    while (m_items.size() > m_machineItems.size())
+        delete m_items.last();
+    if (fCleanupPerformed)
+        updateGeometry();
+
+    /* Start building group: */
+    rebuildGroup();
+}
+
+void UIGInformationGroup::rebuildGroup()
+{
+    /* Cleanup build-step: */
+    delete m_pBuildStep;
+    m_pBuildStep = 0;
+
+    /* Generate new group-id: */
+    m_strGroupId = QUuid::createUuid().toString();
+
+    /* Request to build first step: */
+    emit sigBuildStep(m_strGroupId, 0);
+}
+
+void UIGInformationGroup::stopBuildingGroup()
+{
+    /* Generate new group-id: */
+    m_strGroupId = QUuid::createUuid().toString();
+}
+
+void UIGInformationGroup::sltBuildStep(QString strStepId, int iStepNumber)
+{
+    /* Cleanup build-step: */
+    delete m_pBuildStep;
+    m_pBuildStep = 0;
+
+    /* Is step id valid? */
+    if (strStepId != m_strGroupId)
+        return;
+
+    /* Step number feats the bounds: */
+    if (iStepNumber >= 0 && iStepNumber < m_machineItems.size())
+    {
+        /* Should we create a new set for this step? */
+        UIGInformationSet *pSet = 0;
+        if (iStepNumber > m_items.size() - 1)
+            pSet = new UIGInformationSet(this);
+        /* Or use existing? */
+        else
+            pSet = m_items.at(iStepNumber)->toSet();
+
+        /* Create next build-step: */
+        m_pBuildStep = new UIInformationBuildStep(this, pSet, strStepId, iStepNumber + 1);
+
+        /* Build set: */
+        pSet->buildSet(m_machineItems[iStepNumber], m_machineItems.size() == 1, model()->settings());
+    }
+    else
+    {
+        /* Notify listener about build done: */
+        emit sigBuildDone();
+    }
+}
+
+QVariant UIGInformationGroup::data(int iKey) const
+{
+    /* Provide other members with required data: */
+    switch (iKey)
+    {
+        /* Layout hints: */
+        case GroupData_Margin: return 2;
+        case GroupData_Spacing: return 10;
+        /* Default: */
+        default: break;
+    }
+    return QVariant();
+}
+
+void UIGInformationGroup::addItem(UIGInformationItem *pItem)
+{
+    switch (pItem->type())
+    {
+        case UIGInformationItemType_Set: m_items.append(pItem); break;
+        default: AssertMsgFailed(("Invalid item type!")); break;
+    }
+}
+
+void UIGInformationGroup::removeItem(UIGInformationItem *pItem)
+{
+    switch (pItem->type())
+    {
+        case UIGInformationItemType_Set: m_items.removeAt(m_items.indexOf(pItem)); break;
+        default: AssertMsgFailed(("Invalid item type!")); break;
+    }
+}
+
+QList<UIGInformationItem*> UIGInformationGroup::items(UIGInformationItemType type /* = UIGInformationItemType_Set */) const
+{
+    switch (type)
+    {
+        case UIGInformationItemType_Set: return m_items;
+        case UIGInformationItemType_Any: return items(UIGInformationItemType_Set);
+        default: AssertMsgFailed(("Invalid item type!")); break;
+    }
+    return QList<UIGInformationItem*>();
+}
+
+bool UIGInformationGroup::hasItems(UIGInformationItemType type /* = UIGInformationItemType_Set */) const
+{
+    switch (type)
+    {
+        case UIGInformationItemType_Set: return !m_items.isEmpty();
+        case UIGInformationItemType_Any: return hasItems(UIGInformationItemType_Set);
+        default: AssertMsgFailed(("Invalid item type!")); break;
+    }
+    return false;
+}
+
+void UIGInformationGroup::clearItems(UIGInformationItemType type /* = UIGInformationItemType_Set */)
+{
+    switch (type)
+    {
+        case UIGInformationItemType_Set: while (!m_items.isEmpty()) { delete m_items.last(); } break;
+        case UIGInformationItemType_Any: clearItems(UIGInformationItemType_Set); break;
+        default: AssertMsgFailed(("Invalid item type!")); break;
+    }
+}
+
+void UIGInformationGroup::prepareConnections()
+{
+    /* Prepare group-item connections: */
+    connect(this, SIGNAL(sigMinimumWidthHintChanged(int)),
+            model(), SIGNAL(sigRootItemMinimumWidthHintChanged(int)));
+    connect(this, SIGNAL(sigMinimumHeightHintChanged(int)),
+            model(), SIGNAL(sigRootItemMinimumHeightHintChanged(int)));
+}
+
+void UIGInformationGroup::updateGeometry()
+{
+    /* Call to base class: */
+    UIGInformationItem::updateGeometry();
+
+    /* Group-item should notify details-view if minimum-width-hint was changed: */
+    int iMinimumWidthHint = minimumWidthHint();
+    if (m_iPreviousMinimumWidthHint != iMinimumWidthHint)
+    {
+        /* Save new minimum-width-hint, notify listener: */
+        m_iPreviousMinimumWidthHint = iMinimumWidthHint;
+        emit sigMinimumWidthHintChanged(m_iPreviousMinimumWidthHint);
+    }
+    /* Group-item should notify details-view if minimum-height-hint was changed: */
+    int iMinimumHeightHint = minimumHeightHint();
+    if (m_iPreviousMinimumHeightHint != iMinimumHeightHint)
+    {
+        /* Save new minimum-height-hint, notify listener: */
+        m_iPreviousMinimumHeightHint = iMinimumHeightHint;
+        emit sigMinimumHeightHintChanged(m_iPreviousMinimumHeightHint);
+    }
+}
+
+int UIGInformationGroup::minimumWidthHint() const
+{
+    /* Prepare variables: */
+    int iMargin = data(GroupData_Margin).toInt();
+    int iMinimumWidthHint = 0;
+
+    /* For each the set we have: */
+    bool fHasItems = false;
+    foreach (UIGInformationItem *pItem, items())
+    {
+        /* Ignore which are with no details: */
+        if (UIGInformationSet *pSetItem = pItem->toSet())
+            if (!pSetItem->hasDetails())
+                continue;
+        /* And take into account all the others: */
+        iMinimumWidthHint = qMax(iMinimumWidthHint, pItem->minimumWidthHint());
+        if (!fHasItems)
+            fHasItems = true;
+    }
+
+    /* Add two margins finally: */
+    if (fHasItems)
+        iMinimumWidthHint += 2 * iMargin;
+
+    /* Return result: */
+    return iMinimumWidthHint;
+}
+
+int UIGInformationGroup::minimumHeightHint() const
+{
+    /* Prepare variables: */
+    int iMargin = data(GroupData_Margin).toInt();
+    int iSpacing = data(GroupData_Spacing).toInt();
+    int iMinimumHeightHint = 0;
+
+    /* For each the set we have: */
+    bool fHasItems = false;
+    foreach (UIGInformationItem *pItem, items())
+    {
+        /* Ignore which are with no details: */
+        if (UIGInformationSet *pSetItem = pItem->toSet())
+            if (!pSetItem->hasDetails())
+                continue;
+        /* And take into account all the others: */
+        iMinimumHeightHint += (pItem->minimumHeightHint() + iSpacing);
+        if (!fHasItems)
+            fHasItems = true;
+    }
+    /* Minus last spacing: */
+    if (fHasItems)
+        iMinimumHeightHint -= iSpacing;
+
+    /* Add two margins finally: */
+    if (fHasItems)
+        iMinimumHeightHint += 2 * iMargin;
+
+    /* Return result: */
+    return iMinimumHeightHint;
+}
+
+void UIGInformationGroup::updateLayout()
+{
+    /* Prepare variables: */
+    int iMargin = data(GroupData_Margin).toInt();
+    int iSpacing = data(GroupData_Spacing).toInt();
+    int iMaximumWidth = (int)geometry().width() - 2 * iMargin;
+    int iVerticalIndent = iMargin;
+
+    /* Layout all the sets: */
+    foreach (UIGInformationItem *pItem, items())
+    {
+        /* Ignore sets with no details: */
+        if (UIGInformationSet *pSetItem = pItem->toSet())
+            if (!pSetItem->hasDetails())
+                continue;
+        /* Move set: */
+        pItem->setPos(iMargin, iVerticalIndent);
+        /* Resize set: */
+        int iWidth = iMaximumWidth;
+        pItem->resize(iWidth, pItem->minimumHeightHint());
+        /* Layout set content: */
+        pItem->updateLayout();
+        /* Advance indent: */
+        iVerticalIndent += (pItem->minimumHeightHint() + iSpacing);
+    }
+}
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationGroup.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationGroup.h	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationGroup.h	(revision 58611)
@@ -0,0 +1,102 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformationGroup class declaration.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef __UIGInformationGroup_h__
+#define __UIGInformationGroup_h__
+
+/* GUI includes: */
+#include "UIGInformationItem.h"
+
+/* Forward declarations: */
+class UIVMItem;
+class QGraphicsScene;
+
+/* Details group
+ * for graphics details model/view architecture: */
+class UIGInformationGroup : public UIGInformationItem
+{
+    Q_OBJECT;
+
+signals:
+
+    /* Notifiers: Size-hint stuff: */
+    void sigMinimumWidthHintChanged(int iMinimumWidthHint);
+    void sigMinimumHeightHintChanged(int iMinimumHeightHint);
+
+public:
+
+    /* Graphics-item type: */
+    enum { Type = UIGInformationItemType_Group };
+    int type() const { return Type; }
+
+    /* Constructor/destructor: */
+    UIGInformationGroup(QGraphicsScene *pParent);
+    ~UIGInformationGroup();
+
+    /* API: Build stuff: */
+    void buildGroup(const QList<UIVMItem*> &machineItems);
+    void rebuildGroup();
+    void stopBuildingGroup();
+
+private slots:
+
+    /* Handler: Build stuff: */
+    void sltBuildStep(QString strStepId, int iStepNumber);
+
+private:
+
+    /* Data enumerator: */
+    enum GroupItemData
+    {
+        /* Layout hints: */
+        GroupData_Margin,
+        GroupData_Spacing
+    };
+
+    /* Data provider: */
+    QVariant data(int iKey) const;
+
+    /* Hidden API: Children stuff: */
+    void addItem(UIGInformationItem *pItem);
+    void removeItem(UIGInformationItem *pItem);
+    QList<UIGInformationItem*> items(UIGInformationItemType type = UIGInformationItemType_Set) const;
+    bool hasItems(UIGInformationItemType type = UIGInformationItemType_Set) const;
+    void clearItems(UIGInformationItemType type = UIGInformationItemType_Set);
+
+    /* Helpers: Prepare stuff: */
+    void prepareConnections();
+
+    /* Helpers: Layout stuff: */
+    void updateGeometry();
+    int minimumWidthHint() const;
+    int minimumHeightHint() const;
+    void updateLayout();
+
+    /* Variables: */
+    int m_iPreviousMinimumWidthHint;
+    int m_iPreviousMinimumHeightHint;
+    QList<UIGInformationItem*> m_items;
+    QList<UIVMItem*> m_machineItems;
+    UIInformationBuildStep *m_pBuildStep;
+    QString m_strGroupId;
+
+    /* Friends: */
+    friend class UIGInformationModel;
+};
+
+#endif /* __UIGInformationGroup_h__ */
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationItem.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationItem.cpp	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationItem.cpp	(revision 58611)
@@ -0,0 +1,184 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformationItem class definition.
+ */
+
+/*
+ * Copyright (C) 2012-2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifdef VBOX_WITH_PRECOMPILED_HEADERS
+# include <precomp.h>
+#else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+/* Qt includes: */
+# include <QApplication>
+# include <QPainter>
+# include <QGraphicsScene>
+# include <QStyleOptionGraphicsItem>
+
+/* GUI includes: */
+# include "UIGInformationGroup.h"
+# include "UIGInformationSet.h"
+# include "UIGInformationElement.h"
+# include "UIGInformationModel.h"
+
+#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+
+UIGInformationItem::UIGInformationItem(UIGInformationItem *pParent)
+    : QIWithRetranslateUI4<QIGraphicsWidget>(pParent)
+    , m_pParent(pParent)
+{
+    /* Basic item setup: */
+    setOwnedByLayout(false);
+    setAcceptDrops(false);
+    setFocusPolicy(Qt::NoFocus);
+    setFlag(QGraphicsItem::ItemIsSelectable, false);
+
+    /* Non-root item? */
+    if (parentItem())
+    {
+        /* Non-root item setup: */
+        setAcceptHoverEvents(true);
+    }
+
+    /* Setup connections: */
+    connect(this, SIGNAL(sigBuildStep(QString, int)),
+            this, SLOT(sltBuildStep(QString, int)), Qt::QueuedConnection);
+}
+
+UIGInformationGroup* UIGInformationItem::toGroup()
+{
+    UIGInformationGroup *pItem = qgraphicsitem_cast<UIGInformationGroup*>(this);
+    AssertMsg(pItem, ("Trying to cast invalid item type to UIGInformationGroup!"));
+    return pItem;
+}
+
+UIGInformationSet* UIGInformationItem::toSet()
+{
+    UIGInformationSet *pItem = qgraphicsitem_cast<UIGInformationSet*>(this);
+    AssertMsg(pItem, ("Trying to cast invalid item type to UIGInformationSet!"));
+    return pItem;
+}
+
+UIGInformationElement* UIGInformationItem::toElement()
+{
+    UIGInformationElement *pItem = qgraphicsitem_cast<UIGInformationElement*>(this);
+    AssertMsg(pItem, ("Trying to cast invalid item type to UIGInformationElement!"));
+    return pItem;
+}
+
+UIGInformationModel* UIGInformationItem::model() const
+{
+    UIGInformationModel *pModel = qobject_cast<UIGInformationModel*>(QIGraphicsWidget::scene()->parent());
+    AssertMsg(pModel, ("Incorrect graphics scene parent set!"));
+    return pModel;
+}
+
+UIGInformationItem* UIGInformationItem::parentItem() const
+{
+    return m_pParent;
+}
+
+void UIGInformationItem::updateGeometry()
+{
+    /* Call to base-class: */
+    QIGraphicsWidget::updateGeometry();
+
+    /* Do the same for the parent: */
+    if (parentItem())
+        parentItem()->updateGeometry();
+}
+
+QSizeF UIGInformationItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint /* = QSizeF() */) const
+{
+    /* If Qt::MinimumSize or Qt::PreferredSize requested: */
+    if (which == Qt::MinimumSize || which == Qt::PreferredSize)
+        /* Return wrappers: */
+        return QSizeF(minimumWidthHint(), minimumHeightHint());
+    /* Call to base-class: */
+    return QIGraphicsWidget::sizeHint(which, constraint);
+}
+
+void UIGInformationItem::sltBuildStep(QString, int)
+{
+    AssertMsgFailed(("This item doesn't support building!"));
+}
+
+/* static */
+void UIGInformationItem::configurePainterShape(QPainter *pPainter,
+                                           const QStyleOptionGraphicsItem *pOption,
+                                           int iRadius)
+{
+    /* Rounded corners? */
+    if (iRadius)
+    {
+        /* Setup clipping: */
+        QPainterPath roundedPath;
+        roundedPath.addRoundedRect(pOption->rect, iRadius, iRadius);
+        pPainter->setRenderHint(QPainter::Antialiasing);
+        pPainter->setClipPath(roundedPath);
+    }
+}
+
+/* static */
+void UIGInformationItem::paintFrameRect(QPainter *pPainter, const QRect &rect, int iRadius)
+{
+    pPainter->save();
+    QPalette pal = QApplication::palette();
+    QColor base = pal.color(QPalette::Active, QPalette::Window);
+    pPainter->setPen(base.darker(160));
+    if (iRadius)
+        pPainter->drawRoundedRect(rect, iRadius, iRadius);
+    else
+        pPainter->drawRect(rect);
+    pPainter->restore();
+}
+
+/* static */
+void UIGInformationItem::paintPixmap(QPainter *pPainter, const QRect &rect, const QPixmap &pixmap)
+{
+    pPainter->drawPixmap(rect, pixmap);
+}
+
+/* static */
+void UIGInformationItem::paintText(QPainter *pPainter, QPoint point,
+                               const QFont &font, QPaintDevice *pPaintDevice,
+                               const QString &strText, const QColor &color)
+{
+    /* Prepare variables: */
+    QFontMetrics fm(font, pPaintDevice);
+    point += QPoint(0, fm.ascent());
+
+    /* Draw text: */
+    pPainter->save();
+    pPainter->setFont(font);
+    pPainter->setPen(color);
+    pPainter->drawText(point, strText);
+    pPainter->restore();
+}
+
+UIInformationBuildStep::UIInformationBuildStep(QObject *pParent, QObject *pBuildObject, const QString &strStepId, int iStepNumber)
+    : QObject(pParent)
+    , m_strStepId(strStepId)
+    , m_iStepNumber(iStepNumber)
+{
+    /* Prepare connections: */
+    connect(pBuildObject, SIGNAL(sigBuildDone()), this, SLOT(sltStepDone()), Qt::QueuedConnection);
+    connect(this, SIGNAL(sigStepDone(QString, int)), pParent, SLOT(sltBuildStep(QString, int)), Qt::QueuedConnection);
+}
+
+void UIInformationBuildStep::sltStepDone()
+{
+    emit sigStepDone(m_strStepId, m_iStepNumber);
+}
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationItem.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationItem.h	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationItem.h	(revision 58611)
@@ -0,0 +1,137 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformationItem class declaration.
+ */
+
+/*
+ * Copyright (C) 2012-2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef __UIGInformationItem_h__
+#define __UIGInformationItem_h__
+
+/* GUI includes: */
+#include "QIGraphicsWidget.h"
+#include "QIWithRetranslateUI.h"
+
+/* Forward declaration: */
+class UIGInformationModel;
+class QGraphicsSceneHoverEvent;
+class QGraphicsSceneMouseEvent;
+class UIGInformationGroup;
+class UIGInformationSet;
+class UIGInformationElement;
+
+/* UIGInformationItem types: */
+enum UIGInformationItemType
+{
+    UIGInformationItemType_Any     = QGraphicsItem::UserType,
+    UIGInformationItemType_Group   = QGraphicsItem::UserType + 1,
+    UIGInformationItemType_Set     = QGraphicsItem::UserType + 2,
+    UIGInformationItemType_Element = QGraphicsItem::UserType + 3,
+    UIGInformationItemType_Preview = QGraphicsItem::UserType + 10
+};
+
+/* Details item interface
+ * for graphics details model/view architecture: */
+class UIGInformationItem : public QIWithRetranslateUI4<QIGraphicsWidget>
+{
+    Q_OBJECT;
+
+signals:
+
+    /* Notifiers: Build stuff: */
+    void sigBuildStep(QString strStepId, int iStepNumber);
+    void sigBuildDone();
+
+public:
+
+    /* Constructor: */
+    UIGInformationItem(UIGInformationItem *pParent);
+
+    /* API: Cast stuff: */
+    UIGInformationGroup* toGroup();
+    UIGInformationSet* toSet();
+    UIGInformationElement* toElement();
+
+    /* API: Model stuff: */
+    UIGInformationModel* model() const;
+
+    /* API: Parent stuff: */
+    UIGInformationItem* parentItem() const;
+
+    /* API: Children stuff: */
+    virtual void addItem(UIGInformationItem *pItem) = 0;
+    virtual void removeItem(UIGInformationItem *pItem) = 0;
+    virtual QList<UIGInformationItem*> items(UIGInformationItemType type = UIGInformationItemType_Any) const = 0;
+    virtual bool hasItems(UIGInformationItemType type = UIGInformationItemType_Any) const = 0;
+    virtual void clearItems(UIGInformationItemType type = UIGInformationItemType_Any) = 0;
+
+    /* API: Layout stuff: */
+    void updateGeometry();
+    virtual int minimumWidthHint() const = 0;
+    virtual int minimumHeightHint() const = 0;
+    QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+    virtual void updateLayout() = 0;
+
+protected slots:
+
+    /* Handler: Build stuff: */
+    virtual void sltBuildStep(QString strStepId, int iStepNumber);
+
+protected:
+
+    /* Helper: Translate stuff: */
+    void retranslateUi() {}
+
+    /* Helpers: Paint stuff: */
+    static void configurePainterShape(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption, int iRadius);
+    static void paintFrameRect(QPainter *pPainter, const QRect &rect, int iRadius);
+    static void paintPixmap(QPainter *pPainter, const QRect &rect, const QPixmap &pixmap);
+    static void paintText(QPainter *pPainter, QPoint point,
+                          const QFont &font, QPaintDevice *pPaintDevice,
+                          const QString &strText, const QColor &color);
+
+private:
+
+    /* Variables: */
+    UIGInformationItem *m_pParent;
+};
+
+/* Allows to build item content synchronously: */
+class UIInformationBuildStep : public QObject
+{
+    Q_OBJECT;
+
+signals:
+
+    /* Notifier: Build stuff: */
+    void sigStepDone(QString strStepId, int iStepNumber);
+
+public:
+
+    /* Constructor: */
+    UIInformationBuildStep(QObject *pParent, QObject *pBuildObject, const QString &strStepId, int iStepNumber);
+
+private slots:
+
+    /* Handler: Build stuff: */
+    void sltStepDone();
+
+private:
+
+    /* Variables: */
+    QString m_strStepId;
+    int m_iStepNumber;
+};
+
+#endif /* __UIGInformationItem_h__ */
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationModel.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationModel.cpp	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationModel.cpp	(revision 58611)
@@ -0,0 +1,332 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformationModel class implementation.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifdef VBOX_WITH_PRECOMPILED_HEADERS
+# include <precomp.h>
+#else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+/* Qt includes: */
+# include <QGraphicsScene>
+# include <QGraphicsSceneContextMenuEvent>
+# include <QGraphicsView>
+
+/* GUI includes: */
+# include "UIGInformationModel.h"
+# include "UIGInformationGroup.h"
+# include "UIGInformationElement.h"
+# include "UIExtraDataManager.h"
+# include "VBoxGlobal.h"
+# include "UIConverter.h"
+
+#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+
+UIGInformationModel::UIGInformationModel(QObject *pParent)
+    : QObject(pParent)
+    , m_pScene(0)
+    , m_pRoot(0)
+    , m_pAnimationCallback(0)
+{
+    /* Prepare scene: */
+    prepareScene();
+
+    /* Prepare root: */
+    prepareRoot();
+
+    /* Load settings: */
+    loadSettings();
+
+    /* Register meta-type: */
+    qRegisterMetaType<DetailsElementType>();
+}
+
+UIGInformationModel::~UIGInformationModel()
+{
+    /* Save settings: */
+    saveSettings();
+
+    /* Cleanup root: */
+    cleanupRoot();
+
+    /* Cleanup scene: */
+    cleanupScene();
+ }
+
+QGraphicsScene* UIGInformationModel::scene() const
+{
+    return m_pScene;
+}
+
+QGraphicsView* UIGInformationModel::paintDevice() const
+{
+    if (!m_pScene || m_pScene->views().isEmpty())
+        return 0;
+    return m_pScene->views().first();
+}
+
+QGraphicsItem* UIGInformationModel::itemAt(const QPointF &position) const
+{
+    return scene()->itemAt(position);
+}
+
+void UIGInformationModel::updateLayout()
+{
+    /* Prepare variables: */
+    int iSceneMargin = data(DetailsModelData_Margin).toInt();
+    QSize viewportSize = paintDevice()->viewport()->size();
+    int iViewportWidth = viewportSize.width() - 2 * iSceneMargin;
+    int iViewportHeight = viewportSize.height() - 2 * iSceneMargin;
+
+    /* Move root: */
+    m_pRoot->setPos(iSceneMargin, iSceneMargin);
+    /* Resize root: */
+    m_pRoot->resize(iViewportWidth, iViewportHeight);
+    /* Layout root content: */
+    m_pRoot->updateLayout();
+}
+
+void UIGInformationModel::setItems(const QList<UIVMItem*> &items)
+{
+    m_pRoot->buildGroup(items);
+}
+
+void UIGInformationModel::sltHandleViewResize()
+{
+    /* Relayout: */
+    updateLayout();
+}
+
+void UIGInformationModel::sltToggleElements(DetailsElementType type, bool fToggled)
+{
+    /* Make sure it is not started yet: */
+    if (m_pAnimationCallback)
+        return;
+
+    /* Prepare/configure animation callback: */
+    m_pAnimationCallback = new UIGInformationElementAnimationCallback(this, type, fToggled);
+    connect(m_pAnimationCallback, SIGNAL(sigAllAnimationFinished(DetailsElementType, bool)),
+            this, SLOT(sltToggleAnimationFinished(DetailsElementType, bool)), Qt::QueuedConnection);
+    /* For each the set of the group: */
+    foreach (UIGInformationItem *pSetItem, m_pRoot->items())
+    {
+        /* For each the element of the set: */
+        foreach (UIGInformationItem *pElementItem, pSetItem->items())
+        {
+            /* Get each element: */
+            UIGInformationElement *pElement = pElementItem->toElement();
+            /* Check if this element is of required type: */
+            if (pElement->elementType() == type)
+            {
+                if (fToggled && pElement->closed())
+                {
+                    m_pAnimationCallback->addNotifier(pElement);
+                    pElement->open();
+                }
+                else if (!fToggled && pElement->opened())
+                {
+                    m_pAnimationCallback->addNotifier(pElement);
+                    pElement->close();
+                }
+            }
+        }
+    }
+    /* Update layout: */
+    updateLayout();
+}
+
+void UIGInformationModel::sltToggleAnimationFinished(DetailsElementType type, bool fToggled)
+{
+    /* Cleanup animation callback: */
+    delete m_pAnimationCallback;
+    m_pAnimationCallback = 0;
+
+    /* Mark animation finished: */
+    foreach (UIGInformationItem *pSetItem, m_pRoot->items())
+    {
+        foreach (UIGInformationItem *pElementItem, pSetItem->items())
+        {
+            UIGInformationElement *pElement = pElementItem->toElement();
+            if (pElement->elementType() == type)
+                pElement->markAnimationFinished();
+        }
+    }
+    /* Update layout: */
+    updateLayout();
+
+    /* Update element open/close status: */
+    if (m_settings.contains(type))
+        m_settings[type] = fToggled;
+}
+
+void UIGInformationModel::sltElementTypeToggled()
+{
+    /* Which item was toggled? */
+    QAction *pAction = qobject_cast<QAction*>(sender());
+    DetailsElementType type = pAction->data().value<DetailsElementType>();
+
+    /* Toggle element visibility status: */
+    if (m_settings.contains(type))
+        m_settings.remove(type);
+    else
+        m_settings[type] = true;
+
+    /* Rebuild group: */
+    m_pRoot->rebuildGroup();
+}
+
+void UIGInformationModel::sltHandleSlidingStarted()
+{
+    m_pRoot->stopBuildingGroup();
+}
+
+void UIGInformationModel::sltHandleToggleStarted()
+{
+    m_pRoot->stopBuildingGroup();
+}
+
+void UIGInformationModel::sltHandleToggleFinished()
+{
+    m_pRoot->rebuildGroup();
+}
+
+QVariant UIGInformationModel::data(int iKey) const
+{
+    switch (iKey)
+    {
+        case DetailsModelData_Margin: return 0;
+        default: break;
+    }
+    return QVariant();
+}
+
+void UIGInformationModel::prepareScene()
+{
+    m_pScene = new QGraphicsScene(this);
+    m_pScene->installEventFilter(this);
+}
+
+void UIGInformationModel::prepareRoot()
+{
+    m_pRoot = new UIGInformationGroup(scene());
+}
+
+void UIGInformationModel::loadSettings()
+{
+    /* Load settings: */
+    m_settings = gEDataManager->selectorWindowDetailsElements();
+    /* If settings are empty: */
+    if (m_settings.isEmpty())
+    {
+        /* Propose the defaults: */
+        m_settings[DetailsElementType_General] = true;
+        m_settings[DetailsElementType_Preview] = true;
+        m_settings[DetailsElementType_System] = true;
+        m_settings[DetailsElementType_Display] = true;
+        m_settings[DetailsElementType_Storage] = true;
+        m_settings[DetailsElementType_Audio] = true;
+        m_settings[DetailsElementType_Network] = true;
+        m_settings[DetailsElementType_USB] = true;
+        m_settings[DetailsElementType_SF] = true;
+        m_settings[DetailsElementType_Description] = true;
+    }
+}
+
+void UIGInformationModel::saveSettings()
+{
+    /* Save settings: */
+    gEDataManager->setSelectorWindowDetailsElements(m_settings);
+}
+
+void UIGInformationModel::cleanupRoot()
+{
+    delete m_pRoot;
+    m_pRoot = 0;
+}
+
+void UIGInformationModel::cleanupScene()
+{
+    delete m_pScene;
+    m_pScene = 0;
+}
+
+bool UIGInformationModel::eventFilter(QObject *pObject, QEvent *pEvent)
+{
+    /* Ignore if no scene object: */
+    if (pObject != scene())
+        return QObject::eventFilter(pObject, pEvent);
+
+    /* Ignore if no context-menu event: */
+    if (pEvent->type() != QEvent::GraphicsSceneContextMenu)
+        return QObject::eventFilter(pObject, pEvent);
+
+    /* Process context menu event: */
+    return processContextMenuEvent(static_cast<QGraphicsSceneContextMenuEvent*>(pEvent));
+}
+
+bool UIGInformationModel::processContextMenuEvent(QGraphicsSceneContextMenuEvent *pEvent)
+{
+    /* Pass preview context menu instead: */
+    if (QGraphicsItem *pItem = itemAt(pEvent->scenePos()))
+        if (pItem->type() == UIGInformationItemType_Preview)
+            return false;
+
+    /* Prepare context-menu: */
+    QMenu contextMenu;
+    /* Enumerate elements settings: */
+    for (int iType = DetailsElementType_General; iType <= DetailsElementType_Description; ++iType)
+    {
+        DetailsElementType currentElementType = (DetailsElementType)iType;
+        QAction *pAction = contextMenu.addAction(gpConverter->toString(currentElementType), this, SLOT(sltElementTypeToggled()));
+        pAction->setCheckable(true);
+        pAction->setChecked(m_settings.contains(currentElementType));
+        pAction->setData(QVariant::fromValue(currentElementType));
+    }
+    /* Exec context-menu: */
+    contextMenu.exec(pEvent->screenPos());
+
+    /* Filter: */
+    return true;
+}
+
+UIGInformationElementAnimationCallback::UIGInformationElementAnimationCallback(QObject *pParent, DetailsElementType type, bool fToggled)
+    : QObject(pParent)
+    , m_type(type)
+    , m_fToggled(fToggled)
+{
+}
+
+void UIGInformationElementAnimationCallback::addNotifier(UIGInformationItem *pItem)
+{
+    /* Connect notifier: */
+    connect(pItem, SIGNAL(sigToggleElementFinished()), this, SLOT(sltAnimationFinished()));
+    /* Remember notifier: */
+    m_notifiers << pItem;
+}
+
+void UIGInformationElementAnimationCallback::sltAnimationFinished()
+{
+    /* Determine notifier: */
+    UIGInformationItem *pItem = qobject_cast<UIGInformationItem*>(sender());
+    /* Disconnect notifier: */
+    disconnect(pItem, SIGNAL(sigToggleElementFinished()), this, SLOT(sltAnimationFinished()));
+    /* Remove notifier: */
+    m_notifiers.removeAll(pItem);
+    /* Check if we finished: */
+    if (m_notifiers.isEmpty())
+        emit sigAllAnimationFinished(m_type, m_fToggled);
+}
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationModel.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationModel.h	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationModel.h	(revision 58611)
@@ -0,0 +1,160 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformationModel class declaration.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef __UIGInformationModel_h__
+#define __UIGInformationModel_h__
+
+/* Qt includes: */
+#include <QObject>
+#include <QPointer>
+#include <QMap>
+#include <QSet>
+
+/* GUI includes: */
+#include "UIExtraDataDefs.h"
+
+/* COM includes: */
+#include "COMEnums.h"
+
+/* Forward declaration: */
+class QGraphicsItem;
+class QGraphicsScene;
+class QGraphicsSceneContextMenuEvent;
+class QGraphicsView;
+class UIGInformationGroup;
+class UIVMItem;
+class UIGInformationElementAnimationCallback;
+class UIGInformationItem;
+
+/* Graphics details-model: */
+class UIGInformationModel : public QObject
+{
+    Q_OBJECT;
+
+signals:
+
+    /* Notifiers: Root-item stuff: */
+    void sigRootItemMinimumWidthHintChanged(int iRootItemMinimumWidthHint);
+    void sigRootItemMinimumHeightHintChanged(int iRootItemMinimumHeightHint);
+
+    /* Notifier: Link processing stuff: */
+    void sigLinkClicked(const QString &strCategory, const QString &strControl, const QString &strId);
+
+public:
+
+    /* Constructor/destructor: */
+    UIGInformationModel(QObject *pParent);
+    ~UIGInformationModel();
+
+    /* API: Scene stuff: */
+    QGraphicsScene* scene() const;
+    QGraphicsView* paintDevice() const;
+    QGraphicsItem* itemAt(const QPointF &position) const;
+
+    /* API: Layout stuff: */
+    void updateLayout();
+
+    /* API: Current-item(s) stuff: */
+    void setItems(const QList<UIVMItem*> &items);
+
+    /** Returns the details settings. */
+    const QMap<DetailsElementType, bool>& settings() const { return m_settings; }
+
+private slots:
+
+    /* Handler: Details-view stuff: */
+    void sltHandleViewResize();
+
+    /* Handlers: Element-items stuff: */
+    void sltToggleElements(DetailsElementType type, bool fToggled);
+    void sltToggleAnimationFinished(DetailsElementType type, bool fToggled);
+    void sltElementTypeToggled();
+
+    /* Handlers: Chooser stuff: */
+    void sltHandleSlidingStarted();
+    void sltHandleToggleStarted();
+    void sltHandleToggleFinished();
+
+private:
+
+    /* Data enumerator: */
+    enum DetailsModelData
+    {
+        /* Layout hints: */
+        DetailsModelData_Margin
+    };
+
+    /* Data provider: */
+    QVariant data(int iKey) const;
+
+    /* Helpers: Prepare stuff: */
+    void prepareScene();
+    void prepareRoot();
+    void loadSettings();
+
+    /* Helpers: Cleanup stuff: */
+    void saveSettings();
+    void cleanupRoot();
+    void cleanupScene();
+
+    /* Handler: Event-filter: */
+    bool eventFilter(QObject *pObject, QEvent *pEvent);
+
+    /* Handler: Context-menu stuff: */
+    bool processContextMenuEvent(QGraphicsSceneContextMenuEvent *pEvent);
+
+    /* Variables: */
+    QGraphicsScene *m_pScene;
+    UIGInformationGroup *m_pRoot;
+    UIGInformationElementAnimationCallback *m_pAnimationCallback;
+    /** Holds the details settings. */
+    QMap<DetailsElementType, bool> m_settings;
+};
+
+/* Details-element animation callback: */
+class UIGInformationElementAnimationCallback : public QObject
+{
+    Q_OBJECT;
+
+signals:
+
+    /* Notifier: Complete stuff: */
+    void sigAllAnimationFinished(DetailsElementType type, bool fToggled);
+
+public:
+
+    /* Constructor: */
+    UIGInformationElementAnimationCallback(QObject *pParent, DetailsElementType type, bool fToggled);
+
+    /* API: Notifiers stuff: */
+    void addNotifier(UIGInformationItem *pItem);
+
+private slots:
+
+    /* Handler: Progress stuff: */
+    void sltAnimationFinished();
+
+private:
+
+    /* Variables: */
+    QList<UIGInformationItem*> m_notifiers;
+    DetailsElementType m_type;
+    bool m_fToggled;
+};
+
+#endif /* __UIGInformationModel_h__ */
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationPreview.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationPreview.cpp	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationPreview.cpp	(revision 58611)
@@ -0,0 +1,556 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformationPreview class implementation.
+ */
+
+/*
+ * Copyright (C) 2010-2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifdef VBOX_WITH_PRECOMPILED_HEADERS
+# include <precomp.h>
+#else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+/* Qt includes: */
+# include <QGraphicsSceneContextMenuEvent>
+# include <QMenu>
+# include <QPainter>
+# include <QTimer>
+
+/* GUI includes: */
+# include "UIGInformationPreview.h"
+# include "UIVirtualBoxEventHandler.h"
+# include "UIExtraDataManager.h"
+# include "UIImageTools.h"
+# include "UIConverter.h"
+# include "UIIconPool.h"
+# include "VBoxGlobal.h"
+
+/* COM includes: */
+# include "CConsole.h"
+# include "CDisplay.h"
+
+#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+/* VirtualBox interface declarations: */
+#ifndef VBOX_WITH_XPCOM
+# include "VirtualBox.h"
+#else /* !VBOX_WITH_XPCOM */
+# include "VirtualBox_XPCOM.h"
+#endif /* VBOX_WITH_XPCOM */
+
+UIGInformationPreview::UIGInformationPreview(QIGraphicsWidget *pParent)
+    : QIWithRetranslateUI4<QIGraphicsWidget>(pParent)
+    , m_pUpdateTimer(new QTimer(this))
+    , m_pUpdateTimerMenu(0)
+    , m_iMargin(0)
+    , m_preset(AspectRatioPreset_16x9)
+    , m_pPreviewImg(0)
+{
+    /* Create session instance: */
+    m_session.createInstance(CLSID_Session);
+
+    /* Cache aspect-ratio preset settings: */
+    const QIcon empty16x10 = UIIconPool::iconSet(":/preview_empty_16to10_242x167px.png");
+    const QIcon empty16x9 = UIIconPool::iconSet(":/preview_empty_16to9_242x155px.png");
+    const QIcon empty4x3 = UIIconPool::iconSet(":/preview_empty_4to3_242x192px.png");
+    const QIcon full16x10 = UIIconPool::iconSet(":/preview_full_16to10_242x167px.png");
+    const QIcon full16x9 = UIIconPool::iconSet(":/preview_full_16to9_242x155px.png");
+    const QIcon full4x3 = UIIconPool::iconSet(":/preview_full_4to3_242x192px.png");
+    m_sizes.insert(AspectRatioPreset_16x10, empty16x10.availableSizes().first());
+    m_sizes.insert(AspectRatioPreset_16x9, empty16x9.availableSizes().first());
+    m_sizes.insert(AspectRatioPreset_4x3, empty4x3.availableSizes().first());
+    m_ratios.insert(AspectRatioPreset_16x10, (double)16/10);
+    m_ratios.insert(AspectRatioPreset_16x9, (double)16/9);
+    m_ratios.insert(AspectRatioPreset_4x3, (double)4/3);
+    m_emptyPixmaps.insert(AspectRatioPreset_16x10, new QPixmap(empty16x10.pixmap(m_sizes.value(AspectRatioPreset_16x10))));
+    m_emptyPixmaps.insert(AspectRatioPreset_16x9, new QPixmap(empty16x9.pixmap(m_sizes.value(AspectRatioPreset_16x9))));
+    m_emptyPixmaps.insert(AspectRatioPreset_4x3, new QPixmap(empty4x3.pixmap(m_sizes.value(AspectRatioPreset_4x3))));
+    m_fullPixmaps.insert(AspectRatioPreset_16x10, new QPixmap(full16x10.pixmap(m_sizes.value(AspectRatioPreset_16x10))));
+    m_fullPixmaps.insert(AspectRatioPreset_16x9, new QPixmap(full16x9.pixmap(m_sizes.value(AspectRatioPreset_16x9))));
+    m_fullPixmaps.insert(AspectRatioPreset_4x3, new QPixmap(full4x3.pixmap(m_sizes.value(AspectRatioPreset_4x3))));
+
+    /* Setup contents (depends on presets above!): */
+    setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+
+    /* Create the context menu: */
+    m_pUpdateTimerMenu = new QMenu;
+    QActionGroup *pUpdateTimeG = new QActionGroup(this);
+    pUpdateTimeG->setExclusive(true);
+    for(int i = 0; i < PreviewUpdateIntervalType_Max; ++i)
+    {
+        QAction *pUpdateTime = new QAction(pUpdateTimeG);
+        pUpdateTime->setData(i);
+        pUpdateTime->setCheckable(true);
+        pUpdateTimeG->addAction(pUpdateTime);
+        m_pUpdateTimerMenu->addAction(pUpdateTime);
+        m_actions[static_cast<PreviewUpdateIntervalType>(i)] = pUpdateTime;
+    }
+    m_pUpdateTimerMenu->insertSeparator(m_actions[static_cast<PreviewUpdateIntervalType>(PreviewUpdateIntervalType_500ms)]);
+
+    /* Initialize with the new update interval: */
+    setUpdateInterval(gEDataManager->selectorWindowPreviewUpdateInterval(), false);
+
+    /* Setup connections: */
+    connect(m_pUpdateTimer, SIGNAL(timeout()), this, SLOT(sltRecreatePreview()));
+    connect(gVBoxEvents, SIGNAL(sigMachineStateChange(QString, KMachineState)),
+            this, SLOT(sltMachineStateChange(QString)));
+
+    /* Retranslate the UI */
+    retranslateUi();
+}
+
+UIGInformationPreview::~UIGInformationPreview()
+{
+    /* Close any open session: */
+    if (m_session.GetState() == KSessionState_Locked)
+        m_session.UnlockMachine();
+
+    /* Destroy background images: */
+    foreach (const AspectRatioPreset &preset, m_emptyPixmaps.keys())
+    {
+        delete m_emptyPixmaps.value(preset);
+        m_emptyPixmaps.remove(preset);
+    }
+    foreach (const AspectRatioPreset &preset, m_fullPixmaps.keys())
+    {
+        delete m_fullPixmaps.value(preset);
+        m_fullPixmaps.remove(preset);
+    }
+
+    /* Destroy preview image: */
+    if (m_pPreviewImg)
+        delete m_pPreviewImg;
+
+    /* Destroy update timer: */
+    if (m_pUpdateTimerMenu)
+        delete m_pUpdateTimerMenu;
+}
+
+void UIGInformationPreview::setMachine(const CMachine& machine)
+{
+    /* Pause: */
+    stop();
+
+    /* Assign new machine: */
+    m_machine = machine;
+
+    /* Fetch machine data: */
+    m_strPreviewName = tr("No preview");
+    if (!m_machine.isNull())
+        m_strPreviewName = m_machine.GetAccessible() ? m_machine.GetName() :
+                           QApplication::translate("UIVMListView", "Inaccessible");
+
+    /* Resume: */
+    restart();
+}
+
+CMachine UIGInformationPreview::machine() const
+{
+    return m_machine;
+}
+
+void UIGInformationPreview::sltMachineStateChange(QString strId)
+{
+    /* Make sure its the event for our machine: */
+    if (m_machine.isNull() || m_machine.GetId() != strId)
+        return;
+
+    /* Restart the preview: */
+    restart();
+}
+
+void UIGInformationPreview::sltRecreatePreview()
+{
+    /* Skip invisible preview: */
+    if (!isVisible())
+        return;
+
+    /* Cleanup previous image: */
+    if (m_pPreviewImg)
+    {
+        delete m_pPreviewImg;
+        m_pPreviewImg = 0;
+    }
+
+    /* Fetch actual machine-state: */
+    const KMachineState machineState = m_machine.isNull() ? KMachineState_Null : m_machine.GetState();
+
+    /* We are creating preview only for assigned and accessible VMs: */
+    if (!m_machine.isNull() && machineState != KMachineState_Null &&
+        m_vRect.width() > 0 && m_vRect.height() > 0)
+    {
+        /* Prepare image: */
+        QImage image;
+
+        /* Use 10x9 as the aspect-ratio preset by default: */
+        AspectRatioPreset preset = AspectRatioPreset_16x9;
+
+        /* Preview update enabled? */
+        if (m_pUpdateTimer->interval() > 0)
+        {
+            /* Depending on machine state: */
+            switch (machineState)
+            {
+                /* If machine is in SAVED/RESTORING state: */
+                case KMachineState_Saved:
+                case KMachineState_Restoring:
+                {
+                    /* Use the screenshot from saved-state if possible: */
+                    ULONG uGuestWidth = 0, uGuestHeight = 0;
+                    QVector<BYTE> screenData = m_machine.ReadSavedScreenshotToArray(0, KBitmapFormat_PNG, uGuestWidth, uGuestHeight);
+
+                    /* Make sure screen-data is OK: */
+                    if (!m_machine.isOk() || screenData.isEmpty())
+                        break;
+
+                    if (uGuestWidth > 0 && uGuestHeight > 0)
+                    {
+                        /* Calculate aspect-ratio: */
+                        const double dAspectRatio = (double)uGuestWidth / uGuestHeight;
+                        /* Look for the best aspect-ratio preset: */
+                        preset = bestAspectRatioPreset(dAspectRatio, m_ratios);
+                    }
+
+                    /* Create image based on shallow copy or screenshot data,
+                     * scale image down if necessary to the size possible to reflect: */
+                    image = QImage::fromData(screenData.data(), screenData.size(), "PNG")
+                            .scaled(imageAspectRatioSize(m_vRect.size(), QSize(uGuestWidth, uGuestHeight)),
+                                    Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+                    /* And detach that copy to make it deep: */
+                    image.detach();
+                    /* Dim image to give it required look: */
+                    dimImage(image);
+                    break;
+                }
+                /* If machine is in RUNNING/PAUSED state: */
+                case KMachineState_Running:
+                case KMachineState_Paused:
+                {
+                    /* Make sure session state is Locked: */
+                    if (m_session.GetState() != KSessionState_Locked)
+                        break;
+
+                    /* Make sure console is OK: */
+                    CConsole console = m_session.GetConsole();
+                    if (!m_session.isOk() || console.isNull())
+                        break;
+                    /* Make sure display is OK: */
+                    CDisplay display = console.GetDisplay();
+                    if (!console.isOk() || display.isNull())
+                        break;
+
+                    /* Acquire guest-screen attributes: */
+                    LONG iOriginX = 0, iOriginY = 0;
+                    ULONG uGuestWidth = 0, uGuestHeight = 0, uBpp = 0;
+                    KGuestMonitorStatus monitorStatus = KGuestMonitorStatus_Enabled;
+                    display.GetScreenResolution(0, uGuestWidth, uGuestHeight, uBpp, iOriginX, iOriginY, monitorStatus);
+                    if (uGuestWidth > 0 && uGuestHeight > 0)
+                    {
+                        /* Calculate aspect-ratio: */
+                        const double dAspectRatio = (double)uGuestWidth / uGuestHeight;
+                        /* Look for the best aspect-ratio preset: */
+                        preset = bestAspectRatioPreset(dAspectRatio, m_ratios);
+                    }
+
+                    /* Calculate size corresponding to aspect-ratio: */
+                    const QSize size = imageAspectRatioSize(m_vRect.size(), QSize(uGuestWidth, uGuestHeight));
+
+                    /* Use direct VM content: */
+                    QVector<BYTE> screenData = display.TakeScreenShotToArray(0, size.width(), size.height(), KBitmapFormat_BGR0);
+
+                    /* Make sure screen-data is OK: */
+                    if (!display.isOk() || screenData.isEmpty())
+                        break;
+
+                    /* Make sure screen-data size is valid: */
+                    const int iExpectedSize = size.width() * size.height() * 4;
+                    const int iActualSize = screenData.size();
+                    if (iActualSize != iExpectedSize)
+                    {
+                        AssertMsgFailed(("Invalid screen-data size '%d', should be '%d'!\n", iActualSize, iExpectedSize));
+                        break;
+                    }
+
+                    /* Create image based on shallow copy of acquired data: */
+                    QImage tempImage(screenData.data(), size.width(), size.height(), QImage::Format_RGB32);
+                    image = tempImage;
+                    /* And detach that copy to make it deep: */
+                    image.detach();
+                    /* Dim image to give it required look for PAUSED state: */
+                    if (machineState == KMachineState_Paused)
+                        dimImage(image);
+                    break;
+                }
+                default:
+                    break;
+            }
+        }
+
+        /* If image initialized: */
+        if (!image.isNull())
+        {
+            /* Shallow copy that image: */
+            m_pPreviewImg = new QImage(image);
+            /* And detach that copy to make it deep: */
+            m_pPreviewImg->detach();
+        }
+
+        /* If preset changed: */
+        if (m_preset != preset)
+        {
+            /* Save new preset: */
+            m_preset = preset;
+            /* And update geometry: */
+            updateGeometry();
+            emit sigSizeHintChanged();
+        }
+    }
+
+    /* Redraw preview in any case: */
+    update();
+}
+
+void UIGInformationPreview::resizeEvent(QGraphicsSceneResizeEvent *pEvent)
+{
+    recalculatePreviewRectangle();
+    sltRecreatePreview();
+    QIGraphicsWidget::resizeEvent(pEvent);
+}
+
+void UIGInformationPreview::showEvent(QShowEvent *pEvent)
+{
+    restart();
+    QIGraphicsWidget::showEvent(pEvent);
+}
+
+void UIGInformationPreview::hideEvent(QHideEvent *pEvent)
+{
+    stop();
+    QIGraphicsWidget::hideEvent(pEvent);
+}
+
+void UIGInformationPreview::contextMenuEvent(QGraphicsSceneContextMenuEvent *pEvent)
+{
+    QAction *pReturn = m_pUpdateTimerMenu->exec(pEvent->screenPos(), 0);
+    if (pReturn)
+    {
+        PreviewUpdateIntervalType interval = static_cast<PreviewUpdateIntervalType>(pReturn->data().toInt());
+        setUpdateInterval(interval, true);
+        restart();
+    }
+}
+
+void UIGInformationPreview::retranslateUi()
+{
+    m_actions.value(PreviewUpdateIntervalType_Disabled)->setText(tr("Update disabled"));
+    m_actions.value(PreviewUpdateIntervalType_500ms)->setText(tr("Every 0.5 s"));
+    m_actions.value(PreviewUpdateIntervalType_1000ms)->setText(tr("Every 1 s"));
+    m_actions.value(PreviewUpdateIntervalType_2000ms)->setText(tr("Every 2 s"));
+    m_actions.value(PreviewUpdateIntervalType_5000ms)->setText(tr("Every 5 s"));
+    m_actions.value(PreviewUpdateIntervalType_10000ms)->setText(tr("Every 10 s"));
+}
+
+QSizeF UIGInformationPreview::sizeHint(Qt::SizeHint which, const QSizeF &constraint /* = QSizeF() */) const
+{
+    if (which == Qt::MinimumSize)
+    {
+        AssertReturn(m_emptyPixmaps.contains(m_preset),
+                     QIGraphicsWidget::sizeHint(which, constraint));
+        QSize size = m_sizes.value(m_preset);
+        if (m_iMargin != 0)
+        {
+            size.setWidth(size.width() - 2 * m_iMargin);
+            size.setHeight(size.height() - 2 * m_iMargin);
+        }
+        return size;
+    }
+    return QIGraphicsWidget::sizeHint(which, constraint);
+}
+
+void UIGInformationPreview::paint(QPainter *pPainter, const QStyleOptionGraphicsItem*, QWidget*)
+{
+    /* Where should the content go: */
+    QRect cr = contentsRect().toRect();
+    if (!cr.isValid())
+        return;
+
+    /* If there is a preview image available: */
+    if (m_pPreviewImg)
+    {
+        /* Draw empty monitor frame: */
+        pPainter->drawPixmap(cr.x() + m_iMargin, cr.y() + m_iMargin, *m_emptyPixmaps.value(m_preset));
+
+        /* Move image to viewport center: */
+        QRect imageRect(QPoint(0, 0), m_pPreviewImg->size());
+        imageRect.moveCenter(m_vRect.center());
+        /* Draw preview image: */
+        pPainter->drawImage(imageRect.topLeft(), *m_pPreviewImg);
+    }
+    else
+    {
+        /* Draw full monitor frame: */
+        pPainter->drawPixmap(cr.x() + m_iMargin, cr.y() + m_iMargin, *m_fullPixmaps.value(m_preset));
+
+        /* Paint preview name: */
+        QFont font = pPainter->font();
+        font.setBold(true);
+        int fFlags = Qt::AlignCenter | Qt::TextWordWrap;
+        float h = m_vRect.size().height() * .2;
+        QRect r;
+        /* Make a little magic to find out if the given text fits into our rectangle.
+         * Decrease the font pixel size as long as it doesn't fit. */
+        int cMax = 30;
+        do
+        {
+            h = h * .8;
+            font.setPixelSize((int)h);
+            pPainter->setFont(font);
+            r = pPainter->boundingRect(m_vRect, fFlags, m_strPreviewName);
+        }
+        while ((r.height() > m_vRect.height() || r.width() > m_vRect.width()) && cMax-- != 0);
+        pPainter->setPen(Qt::white);
+        pPainter->drawText(m_vRect, fFlags, m_strPreviewName);
+    }
+}
+
+void UIGInformationPreview::setUpdateInterval(PreviewUpdateIntervalType interval, bool fSave)
+{
+    switch (interval)
+    {
+        case PreviewUpdateIntervalType_Disabled:
+        {
+            /* Stop the timer: */
+            m_pUpdateTimer->stop();
+            /* And continue with other cases: */
+        }
+        case PreviewUpdateIntervalType_500ms:
+        case PreviewUpdateIntervalType_1000ms:
+        case PreviewUpdateIntervalType_2000ms:
+        case PreviewUpdateIntervalType_5000ms:
+        case PreviewUpdateIntervalType_10000ms:
+        {
+            /* Set the timer interval: */
+            m_pUpdateTimer->setInterval(gpConverter->toInternalInteger(interval));
+            /* Check corresponding action: */
+            m_actions[interval]->setChecked(true);
+            break;
+        }
+        case PreviewUpdateIntervalType_Max:
+            break;
+    }
+    if (fSave)
+        gEDataManager->setSelectorWindowPreviewUpdateInterval(interval);
+}
+
+void UIGInformationPreview::recalculatePreviewRectangle()
+{
+    /* Contents rectangle: */
+    QRect cr = contentsRect().toRect();
+    m_vRect = cr.adjusted(21 + m_iMargin, 21 + m_iMargin, -21 - m_iMargin, -21 - m_iMargin);
+}
+
+void UIGInformationPreview::restart()
+{
+    /* Fetch the latest machine-state: */
+    KMachineState machineState = m_machine.isNull() ? KMachineState_Null : m_machine.GetState();
+
+    /* Reopen session if necessary: */
+    if (m_session.GetState() == KSessionState_Locked)
+        m_session.UnlockMachine();
+    if (!m_machine.isNull())
+    {
+        /* Lock the session for the current machine: */
+        if (machineState == KMachineState_Running || machineState == KMachineState_Paused)
+            m_machine.LockMachine(m_session, KLockType_Shared);
+    }
+
+    /* Recreate the preview image: */
+    sltRecreatePreview();
+
+    /* Start the timer if necessary: */
+    if (!m_machine.isNull())
+    {
+        if (m_pUpdateTimer->interval() > 0 && machineState == KMachineState_Running)
+            m_pUpdateTimer->start();
+    }
+}
+
+void UIGInformationPreview::stop()
+{
+    /* Stop the timer: */
+    m_pUpdateTimer->stop();
+}
+
+/* static */
+UIGInformationPreview::AspectRatioPreset UIGInformationPreview::bestAspectRatioPreset(const double dAspectRatio,
+                                                                              const QMap<AspectRatioPreset, double> &ratios)
+{
+    /* Use 16x9 preset as the 'best' by 'default': */
+    AspectRatioPreset bestPreset = AspectRatioPreset_16x9;
+    /* Calculate minimum diff based on 'default' preset: */
+    double dMinimumDiff = qAbs(dAspectRatio - ratios.value(bestPreset));
+    /* Now look for the 'best' aspect-ratio preset among existing: */
+    for (AspectRatioPreset currentPreset = AspectRatioPreset_16x10;
+         currentPreset <= AspectRatioPreset_4x3;
+         currentPreset = (AspectRatioPreset)(currentPreset + 1))
+    {
+        /* Calculate current diff based on 'current' preset: */
+        const double dDiff = qAbs(dAspectRatio - ratios.value(currentPreset));
+        /* If new 'best' preset found: */
+        if (dDiff < dMinimumDiff)
+        {
+            /* Remember new diff: */
+            dMinimumDiff = dDiff;
+            /* And new preset: */
+            bestPreset = currentPreset;
+        }
+    }
+    /* Return 'best' preset: */
+    return bestPreset;
+}
+
+/* static */
+QSize UIGInformationPreview::imageAspectRatioSize(const QSize &hostSize, const QSize &guestSize)
+{
+    /* Make sure host-size and guest-size are valid: */
+    AssertReturn(!hostSize.isNull(), QSize());
+    if (guestSize.isNull())
+        return hostSize;
+
+    /* Calculate host/guest aspect-ratio: */
+    const double dHostAspectRatio = (double)hostSize.width() / hostSize.height();
+    const double dGuestAspectRatio = (double)guestSize.width() / guestSize.height();
+    int iWidth = 0, iHeight = 0;
+    /* Guest-screen more thin by vertical than host-screen: */
+    if (dGuestAspectRatio >= dHostAspectRatio)
+    {
+        /* Get host width: */
+        iWidth = hostSize.width();
+        /* And calculate height based on guest aspect ratio: */
+        iHeight = (int)((double)iWidth / dGuestAspectRatio);
+        /* But no more than host height: */
+        iHeight = qMin(iHeight, hostSize.height());
+    }
+    /* Host-screen more thin by vertical than guest-screen: */
+    else
+    {
+        /* Get host height: */
+        iHeight = hostSize.height();
+        /* And calculate width based on guest aspect ratio: */
+        iWidth = (int)((double)iHeight * dGuestAspectRatio);
+        /* But no more than host width: */
+        iWidth = qMin(iWidth, hostSize.width());
+    }
+    /* Return actual size: */
+    return QSize(iWidth, iHeight);
+}
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationPreview.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationPreview.h	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationPreview.h	(revision 58611)
@@ -0,0 +1,127 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformationPreview class declaration.
+ */
+
+/*
+ * Copyright (C) 2010-2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef __UIGInformationPreview_h__
+#define __UIGInformationPreview_h__
+
+/* Qt includes: */
+#include <QHash>
+
+/* GUI includes: */
+#include "QIWithRetranslateUI.h"
+#include "UIGInformationItem.h"
+#include "UIExtraDataDefs.h"
+
+/* COM includes: */
+#include "COMEnums.h"
+#include "CSession.h"
+#include "CMachine.h"
+
+/* Forward declarations: */
+class QAction;
+class QImage;
+class QPixmap;
+class QMenu;
+class QTimer;
+
+/* Preview window class: */
+class UIGInformationPreview : public QIWithRetranslateUI4<QIGraphicsWidget>
+{
+    Q_OBJECT;
+
+signals:
+
+    /** Notifies about size-hint changes. */
+    void sigSizeHintChanged();
+
+public:
+
+    /* Graphics-item type: */
+    enum { Type = UIGInformationItemType_Preview };
+    int type() const { return Type; }
+
+    /* Constructor/destructor: */
+    UIGInformationPreview(QIGraphicsWidget *pParent);
+    ~UIGInformationPreview();
+
+    /* API: Machine stuff: */
+    void setMachine(const CMachine& machine);
+    CMachine machine() const;
+
+private slots:
+
+    /* Handler: Global-event listener stuff: */
+    void sltMachineStateChange(QString strId);
+
+    /* Handler: Preview recreator: */
+    void sltRecreatePreview();
+
+private:
+
+    /** Aspect ratio presets. */
+    enum AspectRatioPreset
+    {
+        AspectRatioPreset_16x10,
+        AspectRatioPreset_16x9,
+        AspectRatioPreset_4x3,
+    };
+
+    /* Helpers: Event handlers: */
+    void resizeEvent(QGraphicsSceneResizeEvent *pEvent);
+    void showEvent(QShowEvent *pEvent);
+    void hideEvent(QHideEvent *pEvent);
+    void contextMenuEvent(QGraphicsSceneContextMenuEvent *pEvent);
+
+    /* Helpers: Translate stuff; */
+    void retranslateUi();
+
+    /* Helpers: Layout stuff: */
+    QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+
+    /* Helpers: Paint stuff: */
+    void paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption, QWidget *pWidget = 0);
+
+    /* Helpers: Update stuff: */
+    void setUpdateInterval(PreviewUpdateIntervalType interval, bool fSave);
+    void recalculatePreviewRectangle();
+    void restart();
+    void stop();
+
+    /** Looks for the best aspect-ratio preset for the passed @a dAspectRatio among all the passed @a ratios. */
+    static AspectRatioPreset bestAspectRatioPreset(const double dAspectRatio, const QMap<AspectRatioPreset, double> &ratios);
+    /** Calculates image size suitable to passed @a hostSize and @a guestSize. */
+    static QSize imageAspectRatioSize(const QSize &hostSize, const QSize &guestSize);
+
+    /* Variables: */
+    CSession m_session;
+    CMachine m_machine;
+    QTimer *m_pUpdateTimer;
+    QMenu *m_pUpdateTimerMenu;
+    QHash<PreviewUpdateIntervalType, QAction*> m_actions;
+    const int m_iMargin;
+    QRect m_vRect;
+    AspectRatioPreset m_preset;
+    QMap<AspectRatioPreset, QSize> m_sizes;
+    QMap<AspectRatioPreset, double> m_ratios;
+    QMap<AspectRatioPreset, QPixmap*> m_emptyPixmaps;
+    QMap<AspectRatioPreset, QPixmap*> m_fullPixmaps;
+    QImage *m_pPreviewImg;
+    QString m_strPreviewName;
+};
+
+#endif /* !__UIGInformationPreview_h__ */
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationSet.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationSet.cpp	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationSet.cpp	(revision 58611)
@@ -0,0 +1,596 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformationSet class implementation.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifdef VBOX_WITH_PRECOMPILED_HEADERS
+# include <precomp.h>
+#else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+/* GUI includes: */
+# include "UIGInformationSet.h"
+# include "UIGInformationModel.h"
+# include "UIGInformationElements.h"
+# include "UIVMItem.h"
+# include "UIVirtualBoxEventHandler.h"
+# include "VBoxGlobal.h"
+
+/* COM includes: */
+# include "CUSBController.h"
+# include "CUSBDeviceFilters.h"
+
+#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+
+UIGInformationSet::UIGInformationSet(UIGInformationItem *pParent)
+    : UIGInformationItem(pParent)
+    , m_pMachineItem(0)
+    , m_fHasDetails(false)
+    , m_configurationAccessLevel(ConfigurationAccessLevel_Null)
+    , m_fFullSet(true)
+    , m_pBuildStep(0)
+    , m_iLastStepNumber(-1)
+{
+    /* Add set to the parent group: */
+    parentItem()->addItem(this);
+
+    /* Prepare set: */
+    prepareSet();
+
+    /* Prepare connections: */
+    prepareConnections();
+}
+
+UIGInformationSet::~UIGInformationSet()
+{
+    /* Cleanup items: */
+    clearItems();
+
+    /* Remove set from the parent group: */
+    parentItem()->removeItem(this);
+}
+
+void UIGInformationSet::buildSet(UIVMItem *pMachineItem, bool fFullSet, const QMap<DetailsElementType, bool> &settings)
+{
+    /* Remember passed arguments: */
+    m_pMachineItem = pMachineItem;
+    m_machine = m_pMachineItem->machine();
+    m_fHasDetails = m_pMachineItem->hasDetails();
+    m_fFullSet = fFullSet;
+    m_settings = settings;
+
+    /* Cleanup superfluous items: */
+    if (!m_fFullSet || !m_fHasDetails)
+    {
+        int iFirstItem = m_fHasDetails ? DetailsElementType_Display : DetailsElementType_General;
+        int iLastItem = DetailsElementType_Description;
+        bool fCleanupPerformed = false;
+        for (int i = iFirstItem; i <= iLastItem; ++i)
+            if (m_elements.contains(i))
+            {
+                delete m_elements[i];
+                fCleanupPerformed = true;
+            }
+        if (fCleanupPerformed)
+            updateGeometry();
+    }
+
+    /* Make sure we have details: */
+    if (!m_fHasDetails)
+    {
+        /* Reset last-step number: */
+        m_iLastStepNumber = -1;
+        /* Notify parent group we are built: */
+        emit sigBuildDone();
+        return;
+    }
+
+    /* Choose last-step number: */
+    m_iLastStepNumber = m_fFullSet ? DetailsElementType_Description : DetailsElementType_Preview;
+
+    /* Fetch USB controller restrictions: */
+    const CUSBDeviceFilters &filters = m_machine.GetUSBDeviceFilters();
+    if (filters.isNull() || !m_machine.GetUSBProxyAvailable())
+        m_settings.remove(DetailsElementType_USB);
+
+    /* Start building set: */
+    rebuildSet();
+}
+
+void UIGInformationSet::sltBuildStep(QString strStepId, int iStepNumber)
+{
+    /* Cleanup build-step: */
+    delete m_pBuildStep;
+    m_pBuildStep = 0;
+
+    /* Is step id valid? */
+    if (strStepId != m_strSetId)
+        return;
+
+    /* Step number feats the bounds: */
+    if (iStepNumber >= 0 && iStepNumber <= m_iLastStepNumber)
+    {
+        /* Load details settings: */
+        DetailsElementType elementType = (DetailsElementType)iStepNumber;
+        /* Should the element be visible? */
+        bool fVisible = m_settings.contains(elementType);
+        /* Should the element be opened? */
+        bool fOpen = fVisible && m_settings[elementType];
+
+        /* Check if element is present already: */
+        UIGInformationElement *pElement = element(elementType);
+        if (pElement && fOpen)
+            pElement->open(false);
+        /* Create element if necessary: */
+        bool fJustCreated = false;
+        if (!pElement)
+        {
+            fJustCreated = true;
+            pElement = createElement(elementType, fOpen);
+        }
+
+        /* Show element if necessary: */
+        if (fVisible && !pElement->isVisible())
+        {
+            /* Show the element: */
+            pElement->show();
+            /* Recursively update size-hint: */
+            pElement->updateGeometry();
+            /* Update layout: */
+            model()->updateLayout();
+        }
+        /* Hide element if necessary: */
+        else if (!fVisible && pElement->isVisible())
+        {
+            /* Hide the element: */
+            pElement->hide();
+            /* Recursively update size-hint: */
+            updateGeometry();
+            /* Update layout: */
+            model()->updateLayout();
+        }
+        /* Update model if necessary: */
+        else if (fJustCreated)
+            model()->updateLayout();
+
+        /* For visible element: */
+        if (pElement->isVisible())
+        {
+            /* Create next build-step: */
+            m_pBuildStep = new UIInformationBuildStep(this, pElement, strStepId, iStepNumber + 1);
+
+            /* Build element: */
+            pElement->updateAppearance();
+        }
+        /* For invisible element: */
+        else
+        {
+            /* Just build next step: */
+            sltBuildStep(strStepId, iStepNumber + 1);
+        }
+    }
+    /* Step number out of bounds: */
+    else
+    {
+        /* Update model: */
+        model()->updateLayout();
+        /* Repaint all the items: */
+        foreach (UIGInformationItem *pItem, items())
+            pItem->update();
+        /* Notify listener about build done: */
+        emit sigBuildDone();
+    }
+}
+
+void UIGInformationSet::sltMachineStateChange(QString strId)
+{
+    /* Is this our VM changed? */
+    if (m_machine.GetId() != strId)
+        return;
+
+    /* Update appearance: */
+    rebuildSet();
+}
+
+void UIGInformationSet::sltMachineAttributesChange(QString strId)
+{
+    /* Is this our VM changed? */
+    if (m_machine.GetId() != strId)
+        return;
+
+    /* Update appearance: */
+    rebuildSet();
+}
+
+void UIGInformationSet::sltUpdateAppearance()
+{
+    /* Update appearance: */
+    rebuildSet();
+}
+
+QVariant UIGInformationSet::data(int iKey) const
+{
+    /* Provide other members with required data: */
+    switch (iKey)
+    {
+        /* Layout hints: */
+        case SetData_Margin: return 0;
+        case SetData_Spacing: return 3;
+        /* Default: */
+        default: break;
+    }
+    return QVariant();
+}
+
+void UIGInformationSet::addItem(UIGInformationItem *pItem)
+{
+    switch (pItem->type())
+    {
+        case UIGInformationItemType_Element:
+        {
+            UIGInformationElement *pElement = pItem->toElement();
+            DetailsElementType type = pElement->elementType();
+            AssertMsg(!m_elements.contains(type), ("Element already added!"));
+            m_elements.insert(type, pItem);
+            break;
+        }
+        default:
+        {
+            AssertMsgFailed(("Invalid item type!"));
+            break;
+        }
+    }
+}
+
+void UIGInformationSet::removeItem(UIGInformationItem *pItem)
+{
+    switch (pItem->type())
+    {
+        case UIGInformationItemType_Element:
+        {
+            UIGInformationElement *pElement = pItem->toElement();
+            DetailsElementType type = pElement->elementType();
+            AssertMsg(m_elements.contains(type), ("Element do not present (type = %d)!", (int)type));
+            m_elements.remove(type);
+            break;
+        }
+        default:
+        {
+            AssertMsgFailed(("Invalid item type!"));
+            break;
+        }
+    }
+}
+
+QList<UIGInformationItem*> UIGInformationSet::items(UIGInformationItemType type /* = UIGInformationItemType_Element */) const
+{
+    switch (type)
+    {
+        case UIGInformationItemType_Element: return m_elements.values();
+        case UIGInformationItemType_Any: return items(UIGInformationItemType_Element);
+        default: AssertMsgFailed(("Invalid item type!")); break;
+    }
+    return QList<UIGInformationItem*>();
+}
+
+bool UIGInformationSet::hasItems(UIGInformationItemType type /* = UIGInformationItemType_Element */) const
+{
+    switch (type)
+    {
+        case UIGInformationItemType_Element: return !m_elements.isEmpty();
+        case UIGInformationItemType_Any: return hasItems(UIGInformationItemType_Element);
+        default: AssertMsgFailed(("Invalid item type!")); break;
+    }
+    return false;
+}
+
+void UIGInformationSet::clearItems(UIGInformationItemType type /* = UIGInformationItemType_Element */)
+{
+    switch (type)
+    {
+        case UIGInformationItemType_Element:
+        {
+            foreach (int iKey, m_elements.keys())
+                delete m_elements[iKey];
+            AssertMsg(m_elements.isEmpty(), ("Set items cleanup failed!"));
+            break;
+        }
+        case UIGInformationItemType_Any:
+        {
+            clearItems(UIGInformationItemType_Element);
+            break;
+        }
+        default:
+        {
+            AssertMsgFailed(("Invalid item type!"));
+            break;
+        }
+    }
+}
+
+UIGInformationElement* UIGInformationSet::element(DetailsElementType elementType) const
+{
+    UIGInformationItem *pItem = m_elements.value(elementType, 0);
+    if (pItem)
+        return pItem->toElement();
+    return 0;
+}
+
+void UIGInformationSet::prepareSet()
+{
+    /* Setup size-policy: */
+    setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
+}
+
+void UIGInformationSet::prepareConnections()
+{
+    /* Global-events connections: */
+    connect(gVBoxEvents, SIGNAL(sigMachineStateChange(QString, KMachineState)), this, SLOT(sltMachineStateChange(QString)));
+    connect(gVBoxEvents, SIGNAL(sigMachineDataChange(QString)), this, SLOT(sltMachineAttributesChange(QString)));
+    connect(gVBoxEvents, SIGNAL(sigSessionStateChange(QString, KSessionState)), this, SLOT(sltMachineAttributesChange(QString)));
+    connect(gVBoxEvents, SIGNAL(sigSnapshotTake(QString, QString)), this, SLOT(sltMachineAttributesChange(QString)));
+    connect(gVBoxEvents, SIGNAL(sigSnapshotDelete(QString, QString)), this, SLOT(sltMachineAttributesChange(QString)));
+    connect(gVBoxEvents, SIGNAL(sigSnapshotChange(QString, QString)), this, SLOT(sltMachineAttributesChange(QString)));
+    connect(gVBoxEvents, SIGNAL(sigSnapshotRestore(QString, QString)), this, SLOT(sltMachineAttributesChange(QString)));
+
+    /* Meidum-enumeration connections: */
+    connect(&vboxGlobal(), SIGNAL(sigMediumEnumerationStarted()), this, SLOT(sltUpdateAppearance()));
+    connect(&vboxGlobal(), SIGNAL(sigMediumEnumerationFinished()), this, SLOT(sltUpdateAppearance()));
+}
+
+int UIGInformationSet::minimumWidthHint() const
+{
+    /* Zero if has no details: */
+    if (!hasDetails())
+        return 0;
+
+    /* Prepare variables: */
+    int iMargin = data(SetData_Margin).toInt();
+    int iSpacing = data(SetData_Spacing).toInt();
+    int iMinimumWidthHint = 0;
+
+    /* Take into account all the elements: */
+    foreach (UIGInformationItem *pItem, items())
+    {
+        /* Skip hidden: */
+        if (!pItem->isVisible())
+            continue;
+
+        /* For each particular element: */
+        UIGInformationElement *pElement = pItem->toElement();
+        switch (pElement->elementType())
+        {
+            case DetailsElementType_General:
+            case DetailsElementType_System:
+            case DetailsElementType_Display:
+            case DetailsElementType_Storage:
+            case DetailsElementType_Audio:
+            case DetailsElementType_Network:
+            case DetailsElementType_Serial:
+#ifdef VBOX_WITH_PARALLEL_PORTS
+            case DetailsElementType_Parallel:
+#endif /* VBOX_WITH_PARALLEL_PORTS */
+            case DetailsElementType_USB:
+            case DetailsElementType_SF:
+            case DetailsElementType_UI:
+            case DetailsElementType_Description:
+            {
+                iMinimumWidthHint = qMax(iMinimumWidthHint, pItem->minimumWidthHint());
+                break;
+            }
+            case DetailsElementType_Preview:
+            {
+                UIGInformationItem *pGeneralItem = element(DetailsElementType_General);
+                UIGInformationItem *pSystemItem = element(DetailsElementType_System);
+                int iGeneralElementWidth = pGeneralItem ? pGeneralItem->minimumWidthHint() : 0;
+                int iSystemElementWidth = pSystemItem ? pSystemItem->minimumWidthHint() : 0;
+                int iFirstColumnWidth = qMax(iGeneralElementWidth, iSystemElementWidth);
+                iMinimumWidthHint = qMax(iMinimumWidthHint, iFirstColumnWidth + iSpacing + pItem->minimumWidthHint());
+                break;
+            }
+        }
+    }
+
+    /* And two margins finally: */
+    iMinimumWidthHint += 2 * iMargin;
+
+    /* Return result: */
+    return iMinimumWidthHint;
+}
+
+int UIGInformationSet::minimumHeightHint() const
+{
+    /* Zero if has no details: */
+    if (!hasDetails())
+        return 0;
+
+    /* Prepare variables: */
+    int iMargin = data(SetData_Margin).toInt();
+    int iSpacing = data(SetData_Spacing).toInt();
+    int iMinimumHeightHint = 0;
+
+    /* Take into account all the elements: */
+    foreach (UIGInformationItem *pItem, items())
+    {
+        /* Skip hidden: */
+        if (!pItem->isVisible())
+            continue;
+
+        /* For each particular element: */
+        UIGInformationElement *pElement = pItem->toElement();
+        switch (pElement->elementType())
+        {
+            case DetailsElementType_General:
+            case DetailsElementType_System:
+            case DetailsElementType_Display:
+            case DetailsElementType_Storage:
+            case DetailsElementType_Audio:
+            case DetailsElementType_Network:
+            case DetailsElementType_Serial:
+#ifdef VBOX_WITH_PARALLEL_PORTS
+            case DetailsElementType_Parallel:
+#endif /* VBOX_WITH_PARALLEL_PORTS */
+            case DetailsElementType_USB:
+            case DetailsElementType_SF:
+            case DetailsElementType_UI:
+            case DetailsElementType_Description:
+            {
+                iMinimumHeightHint += (pItem->minimumHeightHint() + iSpacing);
+                break;
+            }
+            case DetailsElementType_Preview:
+            {
+                iMinimumHeightHint = qMax(iMinimumHeightHint, pItem->minimumHeightHint() + iSpacing);
+                break;
+            }
+        }
+    }
+
+    /* Minus last spacing: */
+    iMinimumHeightHint -= iSpacing;
+
+    /* And two margins finally: */
+    iMinimumHeightHint += 2 * iMargin;
+
+    /* Return result: */
+    return iMinimumHeightHint;
+}
+
+void UIGInformationSet::updateLayout()
+{
+    /* Prepare variables: */
+    int iMargin = data(SetData_Margin).toInt();
+    int iSpacing = data(SetData_Spacing).toInt();
+    int iMaximumWidth = geometry().size().toSize().width();
+    int iVerticalIndent = iMargin;
+
+    /* Layout all the elements: */
+    foreach (UIGInformationItem *pItem, items())
+    {
+        /* Skip hidden: */
+        if (!pItem->isVisible())
+            continue;
+
+        /* For each particular element: */
+        UIGInformationElement *pElement = pItem->toElement();
+        switch (pElement->elementType())
+        {
+            case DetailsElementType_General:
+            case DetailsElementType_System:
+            case DetailsElementType_Display:
+            case DetailsElementType_Storage:
+            case DetailsElementType_Audio:
+            case DetailsElementType_Network:
+            case DetailsElementType_Serial:
+#ifdef VBOX_WITH_PARALLEL_PORTS
+            case DetailsElementType_Parallel:
+#endif /* VBOX_WITH_PARALLEL_PORTS */
+            case DetailsElementType_USB:
+            case DetailsElementType_SF:
+            case DetailsElementType_UI:
+            case DetailsElementType_Description:
+            {
+                /* Move element: */
+                pElement->setPos(iMargin, iVerticalIndent);
+                /* Calculate required width: */
+                int iWidth = iMaximumWidth - 2 * iMargin;
+                if (pElement->elementType() == DetailsElementType_General ||
+                    pElement->elementType() == DetailsElementType_System)
+                    if (UIGInformationElement *pPreviewElement = element(DetailsElementType_Preview))
+                        if (pPreviewElement->isVisible())
+                            iWidth -= (iSpacing + pPreviewElement->minimumWidthHint());
+                /* If element width is wrong: */
+                if (pElement->geometry().width() != iWidth)
+                {
+                    /* Resize element to required width: */
+                    pElement->resize(iWidth, pElement->geometry().height());
+                }
+                /* Acquire required height: */
+                int iHeight = pElement->minimumHeightHint();
+                /* If element height is wrong: */
+                if (pElement->geometry().height() != iHeight)
+                {
+                    /* Resize element to required height: */
+                    pElement->resize(pElement->geometry().width(), iHeight);
+                }
+                /* Layout element content: */
+                pItem->updateLayout();
+                /* Advance indent: */
+                iVerticalIndent += (iHeight + iSpacing);
+                break;
+            }
+            case DetailsElementType_Preview:
+            {
+                /* Prepare variables: */
+                int iWidth = pElement->minimumWidthHint();
+                int iHeight = pElement->minimumHeightHint();
+                /* Move element: */
+                pElement->setPos(iMaximumWidth - iMargin - iWidth, iMargin);
+                /* Resize element: */
+                pElement->resize(iWidth, iHeight);
+                /* Layout element content: */
+                pItem->updateLayout();
+                /* Advance indent: */
+                iVerticalIndent = qMax(iVerticalIndent, iHeight + iSpacing);
+                break;
+            }
+        }
+    }
+}
+
+void UIGInformationSet::rebuildSet()
+{
+    /* Make sure we have details: */
+    if (!m_fHasDetails)
+        return;
+
+    /* Recache properties: */
+    m_configurationAccessLevel = m_pMachineItem->configurationAccessLevel();
+
+    /* Cleanup build-step: */
+    delete m_pBuildStep;
+    m_pBuildStep = 0;
+
+    /* Generate new set-id: */
+    m_strSetId = QUuid::createUuid().toString();
+
+    /* Request to build first step: */
+    emit sigBuildStep(m_strSetId, DetailsElementType_General);
+}
+
+UIGInformationElement* UIGInformationSet::createElement(DetailsElementType elementType, bool fOpen)
+{
+    /* Element factory: */
+    switch (elementType)
+    {
+        case DetailsElementType_General:     return new UIGInformationElementGeneral(this, fOpen);
+        case DetailsElementType_System:      return new UIGInformationElementSystem(this, fOpen);
+        case DetailsElementType_Preview:     return new UIGInformationElementPreview(this, fOpen);
+        case DetailsElementType_Display:     return new UIGInformationElementDisplay(this, fOpen);
+        case DetailsElementType_Storage:     return new UIGInformationElementStorage(this, fOpen);
+        case DetailsElementType_Audio:       return new UIGInformationElementAudio(this, fOpen);
+        case DetailsElementType_Network:     return new UIGInformationElementNetwork(this, fOpen);
+        case DetailsElementType_Serial:      return new UIGInformationElementSerial(this, fOpen);
+#ifdef VBOX_WITH_PARALLEL_PORTS
+        case DetailsElementType_Parallel:    return new UIGInformationElementParallel(this, fOpen);
+#endif /* VBOX_WITH_PARALLEL_PORTS */
+        case DetailsElementType_USB:         return new UIGInformationElementUSB(this, fOpen);
+        case DetailsElementType_SF:          return new UIGInformationElementSF(this, fOpen);
+        case DetailsElementType_UI:          return new UIGInformationElementUI(this, fOpen);
+        case DetailsElementType_Description: return new UIGInformationElementDescription(this, fOpen);
+    }
+    return 0;
+}
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationSet.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationSet.h	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationSet.h	(revision 58611)
@@ -0,0 +1,128 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformationSet class declaration.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef __UIGInformationSet_h__
+#define __UIGInformationSet_h__
+
+/* GUI includes: */
+#include "UIGInformationItem.h"
+#include "UIExtraDataDefs.h"
+#include "UISettingsDefs.h"
+
+/* COM includes: */
+#include "COMEnums.h"
+#include "CMachine.h"
+
+/* Forward declarations: */
+class UIVMItem;
+
+/* Using declarations: */
+using namespace UISettingsDefs;
+
+/* Details set
+ * for graphics details model/view architecture: */
+class UIGInformationSet : public UIGInformationItem
+{
+    Q_OBJECT;
+
+public:
+
+    /* Graphics-item type: */
+    enum { Type = UIGInformationItemType_Set };
+    int type() const { return Type; }
+
+    /* Constructor/destructor: */
+    UIGInformationSet(UIGInformationItem *pParent);
+    ~UIGInformationSet();
+
+    /* API: Build stuff: */
+    void buildSet(UIVMItem *pMachineItem, bool fFullSet, const QMap<DetailsElementType, bool> &settings);
+
+    /* API: Machine stuff: */
+    const CMachine& machine() const { return m_machine; }
+    bool hasDetails() const { return m_fHasDetails; }
+
+    /** Returns configuration access level. */
+    ConfigurationAccessLevel configurationAccessLevel() const { return m_configurationAccessLevel; }
+
+private slots:
+
+    /* Handler: Build stuff: */
+    void sltBuildStep(QString strStepId, int iStepNumber);
+
+    /* Handlers: Global event stuff: */
+    void sltMachineStateChange(QString strId);
+    void sltMachineAttributesChange(QString strId);
+
+    /* Handler: Update stuff: */
+    void sltUpdateAppearance();
+
+private:
+
+    /* Data enumerator: */
+    enum SetItemData
+    {
+        /* Layout hints: */
+        SetData_Margin,
+        SetData_Spacing
+    };
+
+    /* Data provider: */
+    QVariant data(int iKey) const;
+
+    /* Hidden API: Children stuff: */
+    void addItem(UIGInformationItem *pItem);
+    void removeItem(UIGInformationItem *pItem);
+    QList<UIGInformationItem*> items(UIGInformationItemType type = UIGInformationItemType_Element) const;
+    bool hasItems(UIGInformationItemType type = UIGInformationItemType_Element) const;
+    void clearItems(UIGInformationItemType type = UIGInformationItemType_Element);
+    UIGInformationElement* element(DetailsElementType elementType) const;
+
+    /* Helpers: Prepare stuff: */
+    void prepareSet();
+    void prepareConnections();
+
+    /* Helpers: Layout stuff: */
+    int minimumWidthHint() const;
+    int minimumHeightHint() const;
+    void updateLayout();
+
+    /* Helpers: Build stuff: */
+    void rebuildSet();
+    UIGInformationElement* createElement(DetailsElementType elementType, bool fOpen);
+
+    /** Machine-item this set built for. */
+    UIVMItem *m_pMachineItem;
+
+    /* Main variables: */
+    CMachine m_machine;
+    QMap<int, UIGInformationItem*> m_elements;
+    bool m_fHasDetails;
+
+    /** Holds configuration access level. */
+    ConfigurationAccessLevel m_configurationAccessLevel;
+
+    /* Prepare variables: */
+    bool m_fFullSet;
+    UIInformationBuildStep *m_pBuildStep;
+    int m_iLastStepNumber;
+    QString m_strSetId;
+    QMap<DetailsElementType, bool> m_settings;
+};
+
+#endif /* __UIGInformationSet_h__ */
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationView.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationView.cpp	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationView.cpp	(revision 58611)
@@ -0,0 +1,105 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformationView class implementation.
+ */
+
+/*
+ * Copyright (C) 2012-2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifdef VBOX_WITH_PRECOMPILED_HEADERS
+# include <precomp.h>
+#else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+/* Qt includes: */
+# include <QApplication>
+# include <QScrollBar>
+
+/* GUI includes: */
+# include "UIGInformationView.h"
+
+#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+
+UIGInformationView::UIGInformationView(QWidget *pParent)
+    : QIGraphicsView(pParent)
+    , m_iMinimumWidthHint(0)
+    , m_iMinimumHeightHint(0)
+{
+    /* Prepare palette: */
+    preparePalette();
+
+    /* Setup frame: */
+    setFrameShape(QFrame::NoFrame);
+    setFrameShadow(QFrame::Plain);
+    setAlignment(Qt::AlignLeft | Qt::AlignTop);
+
+    /* Setup scroll-bars policy: */
+    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+
+    /* Update scene-rect: */
+    updateSceneRect();
+}
+
+void UIGInformationView::sltMinimumWidthHintChanged(int iMinimumWidthHint)
+{
+    /* Is there something changed? */
+    if (m_iMinimumWidthHint == iMinimumWidthHint)
+        return;
+
+    /* Remember new value: */
+    m_iMinimumWidthHint = iMinimumWidthHint;
+    if (m_iMinimumWidthHint <= 0)
+        m_iMinimumWidthHint = 1;
+
+    /* Set minimum view width according passed width-hint: */
+    setMinimumWidth(2 * frameWidth() + iMinimumWidthHint + verticalScrollBar()->sizeHint().width());
+
+    /* Update scene-rect: */
+    updateSceneRect();
+}
+
+void UIGInformationView::sltMinimumHeightHintChanged(int iMinimumHeightHint)
+{
+    /* Is there something changed? */
+    if (m_iMinimumHeightHint == iMinimumHeightHint)
+        return;
+
+    /* Remember new value: */
+    m_iMinimumHeightHint = iMinimumHeightHint;
+    if (m_iMinimumHeightHint <= 0)
+        m_iMinimumHeightHint = 1;
+
+    /* Update scene-rect: */
+    updateSceneRect();
+}
+
+void UIGInformationView::preparePalette()
+{
+    /* Setup palette: */
+    QPalette pal = qApp->palette();
+    pal.setColor(QPalette::Base, pal.color(QPalette::Active, QPalette::Window));
+    setPalette(pal);
+}
+
+void UIGInformationView::resizeEvent(QResizeEvent *pEvent)
+{
+    /* Call to base-class: */
+    QIGraphicsView::resizeEvent(pEvent);
+    /* Notify listeners: */
+    emit sigResized();
+}
+
+void UIGInformationView::updateSceneRect()
+{
+    setSceneRect(0, 0, m_iMinimumWidthHint, m_iMinimumHeightHint);
+}
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationView.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationView.h	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIGInformationView.h	(revision 58611)
@@ -0,0 +1,62 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGInformationView class declaration.
+ */
+
+/*
+ * Copyright (C) 2012-2015 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef __UIGInformationView_h__
+#define __UIGInformationView_h__
+
+/* GUI includes: */
+#include "QIGraphicsView.h"
+
+/* Graphics details-view: */
+class UIGInformationView : public QIGraphicsView
+{
+    Q_OBJECT;
+
+signals:
+
+    /* Notifier: Resize stuff: */
+    void sigResized();
+
+public:
+
+    /* Constructor: */
+    UIGInformationView(QWidget *pParent);
+
+private slots:
+
+    /* Handlers: Size-hint stuff: */
+    void sltMinimumWidthHintChanged(int iMinimumWidthHint);
+    void sltMinimumHeightHintChanged(int iMinimumHeightHint);
+
+private:
+
+    /* Helper: Prepare stuff: */
+    void preparePalette();
+
+    /* Handler: Resize-event stuff: */
+    void resizeEvent(QResizeEvent *pEvent);
+
+    /* Helper: Update stuff: */
+    void updateSceneRect();
+
+    /* Variables: */
+    int m_iMinimumWidthHint;
+    int m_iMinimumHeightHint;
+};
+
+#endif /* __UIGInformationView_h__ */
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIVMInformationDialog.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIVMInformationDialog.cpp	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIVMInformationDialog.cpp	(revision 58611)
@@ -0,0 +1,931 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIVMInformationDialog class implementation.
+ */
+
+/*
+ * Copyright (C) 2006-2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifdef VBOX_WITH_PRECOMPILED_HEADERS
+# include <precomp.h>
+#else  /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+/* Qt includes: */
+# include <QTimer>
+# include <QScrollBar>
+# include <QPushButton>
+
+/* GUI includes: */
+# include "UIVMInformationDialog.h"
+# include "UIExtraDataManager.h"
+# include "UISession.h"
+# include "UIMachineLogic.h"
+# include "UIMachineWindow.h"
+# include "UIMachineView.h"
+# include "UIConverter.h"
+# include "UIIconPool.h"
+# include "QITabWidget.h"
+# include "QIDialogButtonBox.h"
+# include "VBoxGlobal.h"
+# include "VBoxUtils.h"
+# include "UIGInformation.h"
+# include "UIMachine.h"
+# include "UIVMItem.h"
+
+/* COM includes: */
+# include "COMEnums.h"
+# include "CMachine.h"
+# include "CConsole.h"
+# include "CSystemProperties.h"
+# include "CMachineDebugger.h"
+# include "CDisplay.h"
+# include "CGuest.h"
+# include "CStorageController.h"
+# include "CMediumAttachment.h"
+# include "CNetworkAdapter.h"
+
+/* Other VBox includes: */
+# include <iprt/time.h>
+
+#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
+
+#include "CVRDEServerInfo.h"
+
+
+/* static */
+UIVMInformationDialog* UIVMInformationDialog::m_spInstance = 0;
+
+void UIVMInformationDialog::invoke(UIMachineWindow *pMachineWindow)
+{
+    /* Make sure dialog instance exists: */
+    if (!m_spInstance)
+    {
+        /* Create new dialog instance if it doesn't exists yet: */
+        new UIVMInformationDialog(pMachineWindow);
+    }
+
+    /* Show dialog: */
+    m_spInstance->show();
+    /* Raise it: */
+    m_spInstance->raise();
+    /* De-miniaturize if necessary: */
+    m_spInstance->setWindowState(m_spInstance->windowState() & ~Qt::WindowMinimized);
+    /* And activate finally: */
+    m_spInstance->activateWindow();
+}
+
+UIVMInformationDialog::UIVMInformationDialog(UIMachineWindow *pMachineWindow)
+    : QIWithRetranslateUI<QMainWindow>(0)
+    , m_pMachineWindow(pMachineWindow)
+    , m_pTabWidget(0)
+    , m_session(pMachineWindow->session())
+    , m_pTimer(new QTimer(this))
+{    
+    /* Initialize instance: */
+    m_spInstance = this;
+
+    /* Prepare: */
+    prepare();
+}
+
+UIVMInformationDialog::~UIVMInformationDialog()
+{
+    /* Cleanup: */
+    cleanup();
+
+    /* Deinitialize instance: */
+    m_spInstance = 0;
+}
+
+void UIVMInformationDialog::retranslateUi()
+{
+    sltUpdateDetails();
+
+    AssertReturnVoid(!m_session.isNull());
+    CMachine machine = m_session.GetMachine();
+    AssertReturnVoid(!machine.isNull());
+
+    /* Setup dialog title: */
+    setWindowTitle(tr("%1 - Session Information").arg(machine.GetName()));
+
+    /* Translate tabs: */
+    m_pTabWidget->setTabText(0, tr("Configuration &Details"));
+    m_pTabWidget->setTabText(1, tr("&Runtime Information"));
+
+    /* Clear counter names initially: */
+    m_names.clear();
+    m_units.clear();
+    m_links.clear();
+
+    /* Storage statistics: */
+    CSystemProperties sp = vboxGlobal().virtualBox().GetSystemProperties();
+    CStorageControllerVector controllers = m_session.GetMachine().GetStorageControllers();
+    int iIDECount = 0, iSATACount = 0, iSCSICount = 0;
+    foreach (const CStorageController &controller, controllers)
+    {
+        switch (controller.GetBus())
+        {
+            case KStorageBus_IDE:
+            {
+                for (ULONG i = 0; i < sp.GetMaxPortCountForStorageBus(KStorageBus_IDE); ++i)
+                {
+                    for (ULONG j = 0; j < sp.GetMaxDevicesPerPortForStorageBus(KStorageBus_IDE); ++j)
+                    {
+                        /* Names: */
+                        m_names[QString("/Devices/IDE%1/ATA%2/Unit%3/*DMA")
+                            .arg(iIDECount).arg(i).arg(j)] = tr("DMA Transfers");
+                        m_names[QString("/Devices/IDE%1/ATA%2/Unit%3/*PIO")
+                            .arg(iIDECount).arg(i).arg(j)] = tr("PIO Transfers");
+                        m_names[QString("/Devices/IDE%1/ATA%2/Unit%3/ReadBytes")
+                            .arg(iIDECount).arg(i).arg(j)] = tr("Data Read");
+                        m_names[QString("/Devices/IDE%1/ATA%2/Unit%3/WrittenBytes")
+                            .arg(iIDECount).arg(i).arg(j)] = tr("Data Written");
+
+                        /* Units: */
+                        m_units[QString("/Devices/IDE%1/ATA%2/Unit%3/*DMA")
+                            .arg(iIDECount).arg(i).arg(j)] = "[B]";
+                        m_units[QString("/Devices/IDE%1/ATA%2/Unit%3/*PIO")
+                            .arg(iIDECount).arg(i).arg(j)] = "[B]";
+                        m_units[QString("/Devices/IDE%1/ATA%2/Unit%3/ReadBytes")
+                            .arg(iIDECount).arg(i).arg(j)] = "B";
+                        m_units[QString("/Devices/IDE%1/ATA%2/Unit%3/WrittenBytes")
+                            .arg(iIDECount).arg(i).arg(j)] = "B";
+
+                        /* Belongs to */
+                        m_links[QString("/Devices/IDE%1/ATA%2/Unit%3").arg(iIDECount).arg(i).arg(j)] = QStringList()
+                            << QString("/Devices/IDE%1/ATA%2/Unit%3/*DMA").arg(iIDECount).arg(i).arg(j)
+                            << QString("/Devices/IDE%1/ATA%2/Unit%3/*PIO").arg(iIDECount).arg(i).arg(j)
+                            << QString("/Devices/IDE%1/ATA%2/Unit%3/ReadBytes").arg(iIDECount).arg(i).arg(j)
+                            << QString("/Devices/IDE%1/ATA%2/Unit%3/WrittenBytes").arg(iIDECount).arg(i).arg(j);
+                    }
+                }
+                ++iIDECount;
+                break;
+            }
+            case KStorageBus_SATA:
+            {
+                for (ULONG i = 0; i < sp.GetMaxPortCountForStorageBus(KStorageBus_SATA); ++i)
+                {
+                    for (ULONG j = 0; j < sp.GetMaxDevicesPerPortForStorageBus(KStorageBus_SATA); ++j)
+                    {
+                        /* Names: */
+                        m_names[QString("/Devices/SATA%1/Port%2/DMA").arg(iSATACount).arg(i)]
+                            = tr("DMA Transfers");
+                        m_names[QString("/Devices/SATA%1/Port%2/ReadBytes").arg(iSATACount).arg(i)]
+                            = tr("Data Read");
+                        m_names[QString("/Devices/SATA%1/Port%2/WrittenBytes").arg(iSATACount).arg(i)]
+                            = tr("Data Written");
+
+                        /* Units: */
+                        m_units[QString("/Devices/SATA%1/Port%2/DMA").arg(iSATACount).arg(i)] = "[B]";
+                        m_units[QString("/Devices/SATA%1/Port%2/ReadBytes").arg(iSATACount).arg(i)] = "B";
+                        m_units[QString("/Devices/SATA%1/Port%2/WrittenBytes").arg(iSATACount).arg(i)] = "B";
+
+                        /* Belongs to: */
+                        m_links[QString("/Devices/SATA%1/Port%2").arg(iSATACount).arg(i)] = QStringList()
+                            << QString("/Devices/SATA%1/Port%2/DMA").arg(iSATACount).arg(i)
+                            << QString("/Devices/SATA%1/Port%2/ReadBytes").arg(iSATACount).arg(i)
+                            << QString("/Devices/SATA%1/Port%2/WrittenBytes").arg(iSATACount).arg(i);
+                    }
+                }
+                ++iSATACount;
+                break;
+            }
+            case KStorageBus_SCSI:
+            {
+                for (ULONG i = 0; i < sp.GetMaxPortCountForStorageBus(KStorageBus_SCSI); ++i)
+                {
+                    for (ULONG j = 0; j < sp.GetMaxDevicesPerPortForStorageBus(KStorageBus_SCSI); ++j)
+                    {
+                        /* Names: */
+                        m_names[QString("/Devices/SCSI%1/%2/ReadBytes").arg(iSCSICount).arg(i)]
+                            = tr("Data Read");
+                        m_names[QString("/Devices/SCSI%1/%2/WrittenBytes").arg(iSCSICount).arg(i)]
+                            = tr("Data Written");
+
+                        /* Units: */
+                        m_units[QString("/Devices/SCSI%1/%2/ReadBytes").arg(iSCSICount).arg(i)] = "B";
+                        m_units[QString("/Devices/SCSI%1/%2/WrittenBytes").arg(iSCSICount).arg(i)] = "B";
+
+                        /* Belongs to: */
+                        m_links[QString("/Devices/SCSI%1/%2").arg(iSCSICount).arg(i)] = QStringList()
+                            << QString("/Devices/SCSI%1/%2/ReadBytes").arg(iSCSICount).arg(i)
+                            << QString("/Devices/SCSI%1/%2/WrittenBytes").arg(iSCSICount).arg(i);
+                    }
+                }
+                ++iSCSICount;
+                break;
+            }
+            default:
+                break;
+        }
+    }
+
+    /* Network statistics: */
+    ulong count = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(KChipsetType_PIIX3);
+    for (ulong i = 0; i < count; ++i)
+    {
+        CNetworkAdapter na = machine.GetNetworkAdapter(i);
+        KNetworkAdapterType ty = na.GetAdapterType();
+        const char *name;
+
+        switch (ty)
+        {
+            case KNetworkAdapterType_I82540EM:
+            case KNetworkAdapterType_I82543GC:
+            case KNetworkAdapterType_I82545EM:
+                name = "E1k";
+                break;
+            case KNetworkAdapterType_Virtio:
+                name = "VNet";
+                break;
+            default:
+                name = "PCNet";
+                break;
+        }
+
+        /* Names: */
+        m_names[QString("/Devices/%1%2/TransmitBytes").arg(name).arg(i)] = tr("Data Transmitted");
+        m_names[QString("/Devices/%1%2/ReceiveBytes").arg(name).arg(i)] = tr("Data Received");
+
+        /* Units: */
+        m_units[QString("/Devices/%1%2/TransmitBytes").arg(name).arg(i)] = "B";
+        m_units[QString("/Devices/%1%2/ReceiveBytes").arg(name).arg(i)] = "B";
+
+        /* Belongs to: */
+        m_links[QString("NA%1").arg(i)] = QStringList()
+            << QString("/Devices/%1%2/TransmitBytes").arg(name).arg(i)
+            << QString("/Devices/%1%2/ReceiveBytes").arg(name).arg(i);
+    }
+
+    /* Statistics page update: */
+    refreshStatistics();
+}
+
+bool UIVMInformationDialog::event(QEvent *pEvent)
+{
+    /* Pre-process through base-class: */
+    bool fResult = QMainWindow::event(pEvent);
+
+    /* Process required events: */
+    switch (pEvent->type())
+    {
+        /* Handle every Resize and Move we keep track of the geometry. */
+        case QEvent::Resize:
+        {
+            if (isVisible() && (windowState() & (Qt::WindowMaximized | Qt::WindowMinimized | Qt::WindowFullScreen)) == 0)
+            {
+                QResizeEvent *pResizeEvent = static_cast<QResizeEvent*>(pEvent);
+                m_geometry.setSize(pResizeEvent->size());
+            }
+            break;
+        }
+        case QEvent::Move:
+        {
+            if (isVisible() && (windowState() & (Qt::WindowMaximized | Qt::WindowMinimized | Qt::WindowFullScreen)) == 0)
+            {
+#ifdef Q_WS_MAC
+                QMoveEvent *pMoveEvent = static_cast<QMoveEvent*>(pEvent);
+                m_geometry.moveTo(pMoveEvent->pos());
+#else /* Q_WS_MAC */
+                m_geometry.moveTo(geometry().x(), geometry().y());
+#endif /* !Q_WS_MAC */
+            }
+            break;
+        }
+        default:
+            break;
+    }
+
+    /* Return result: */
+    return fResult;
+}
+
+void UIVMInformationDialog::sltUpdateDetails()
+{
+    /* Details page update: */
+    //setText(m_browsers[0], vboxGlobal().detailsReport(m_session.GetMachine(), false /* with links */));
+}
+
+void UIVMInformationDialog::sltProcessStatistics()
+{
+    /* Get machine debugger: */
+    CMachineDebugger dbg = m_session.GetConsole().GetDebugger();
+    QString strInfo;
+
+    /* Process selected VM statistics: */
+    for (DataMapType::const_iterator it = m_names.begin(); it != m_names.end(); ++it)
+    {
+        strInfo = dbg.GetStats(it.key(), true);
+        m_values[it.key()] = parseStatistics(strInfo);
+    }
+
+    /* Update VM statistics page: */
+    refreshStatistics();
+}
+
+void UIVMInformationDialog::sltHandlePageChanged(int iIndex)
+{
+    /* Focus the browser on shown page: */
+    m_pTabWidget->widget(iIndex)->setFocus();
+}
+
+void UIVMInformationDialog::prepare()
+{
+    /* Prepare dialog: */
+    prepareThis();
+    /* Load settings: */
+    loadSettings();
+}
+
+void UIVMInformationDialog::prepareThis()
+{
+    /* Delete dialog on close: */
+    setAttribute(Qt::WA_DeleteOnClose);
+    /* Delete dialog on machine-window destruction: */
+    connect(m_pMachineWindow, SIGNAL(destroyed(QObject*)), this, SLOT(suicide()));
+
+#ifdef Q_WS_MAC
+    /* No window-icon on Mac OX X, because it acts as proxy icon which isn't necessary here. */
+    setWindowIcon(QIcon());
+#else /* !Q_WS_MAC */
+    /* Assign window-icon(s: */
+    setWindowIcon(UIIconPool::iconSetFull(":/session_info_32px.png", ":/session_info_16px.png"));
+#endif /* !Q_WS_MAC */
+
+    /* Prepare central-widget: */
+    prepareCentralWidget();
+
+    /* Configure handlers: */
+    connect(m_pMachineWindow->uisession(), SIGNAL(sigMediumChange(const CMediumAttachment&)), this, SLOT(sltUpdateDetails()));
+    connect(m_pMachineWindow->uisession(), SIGNAL(sigSharedFolderChange()), this, SLOT(sltUpdateDetails()));
+    /* TODO_NEW_CORE: this is ofc not really right in the mm sense. There are more than one screens. */
+    connect(m_pMachineWindow->machineView(), SIGNAL(sigFrameBufferResize()), this, SLOT(sltProcessStatistics()));
+    connect(m_pTabWidget, SIGNAL(currentChanged(int)), this, SLOT(sltHandlePageChanged(int)));
+    connect(&vboxGlobal(), SIGNAL(sigMediumEnumerationFinished()), this, SLOT(sltUpdateDetails()));
+    connect(m_pTimer, SIGNAL(timeout()), this, SLOT(sltProcessStatistics()));
+
+    /* Retranslate: */
+    retranslateUi();
+
+    /* Details page update: */
+    sltUpdateDetails();
+
+    /* Statistics page update: */
+    sltProcessStatistics();
+    m_pTimer->start(5000);
+}
+
+void UIVMInformationDialog::prepareCentralWidget()
+{
+    /* Create central-widget: */
+    setCentralWidget(new QWidget);
+    AssertPtrReturnVoid(centralWidget());
+    {
+        /* Create main-layout: */
+        new QVBoxLayout(centralWidget());
+        AssertPtrReturnVoid(centralWidget()->layout());
+        {
+            /* Create tab-widget: */
+            prepareTabWidget();
+            /* Create button-box: */
+            prepareButtonBox();
+        }
+    }
+}
+
+void UIVMInformationDialog::prepareTabWidget()
+{
+    /* Create tab-widget: */
+    m_pTabWidget = new QITabWidget;
+    AssertPtrReturnVoid(m_pTabWidget);
+    {
+        /* Create tabs: */
+        /* Create Configuration details tab: */
+
+        UIGInformation *pInformationWidget = new UIGInformation(this);
+        QList<UIVMItem*> items;
+        items << new UIVMItem(gpMachine->uisession()->machine());
+        pInformationWidget->setItems(items);
+        m_tabs.insert(0, pInformationWidget);
+
+        m_pTabWidget->addTab(m_tabs.value(0), QString());
+
+        for (int iTabIndex = 1; iTabIndex < 2; ++iTabIndex)
+            prepareTab(iTabIndex);
+        /* Configure tab-widget: */
+        m_pTabWidget->setTabIcon(0, UIIconPool::iconSet(":/session_info_details_16px.png"));
+        m_pTabWidget->setTabIcon(1, UIIconPool::iconSet(":/session_info_runtime_16px.png"));
+        m_pTabWidget->setCurrentIndex(1);
+        /* Add tab-widget into main-layout: */
+        centralWidget()->layout()->addWidget(m_pTabWidget);
+    }
+}
+
+void UIVMInformationDialog::prepareTab(int iTabIndex)
+{
+    /* Create tab: */
+    m_tabs.insert(iTabIndex, new QWidget);
+    AssertPtrReturnVoid(m_tabs.value(iTabIndex));
+    {
+        /* Create tab-layout: */
+        QVBoxLayout *pLayout = new QVBoxLayout(m_tabs.value(iTabIndex));
+        {
+            /* Configure tab-layout: */
+            pLayout->setContentsMargins(0, 0, 0, 0);
+            /* Create browser: */
+            m_browsers.insert(iTabIndex, new QRichTextEdit);
+            AssertPtrReturnVoid(m_browsers.value(iTabIndex));
+            {
+                /* Configure browser: */
+                m_browsers[iTabIndex]->setReadOnly(true);
+                m_browsers[iTabIndex]->setFrameShadow(QFrame::Plain);
+                m_browsers[iTabIndex]->setFrameShape(QFrame::NoFrame);
+                m_browsers[iTabIndex]->setViewportMargins(5, 5, 5, 5);
+                m_browsers[iTabIndex]->viewport()->setAutoFillBackground(false);
+                m_tabs[iTabIndex]->setFocusProxy(m_browsers.value(iTabIndex));
+                /* Add browser into tab-layout: */
+                pLayout->addWidget(m_browsers.value(iTabIndex));
+            }
+        }
+        /* Add tab into tab-widget: */
+        m_pTabWidget->addTab(m_tabs.value(iTabIndex), QString());
+    }
+}
+
+void UIVMInformationDialog::prepareButtonBox()
+{
+    /* Create button-box: */
+    m_pButtonBox = new QIDialogButtonBox;
+    AssertPtrReturnVoid(m_pButtonBox);
+    {
+        /* Configure button-box: */
+        m_pButtonBox->setStandardButtons(QDialogButtonBox::Close);
+        m_pButtonBox->button(QDialogButtonBox::Close)->setShortcut(Qt::Key_Escape);
+        connect(m_pButtonBox, SIGNAL(rejected()), this, SLOT(close()));
+        /* Add button-box into main-layout: */
+        centralWidget()->layout()->addWidget(m_pButtonBox);
+    }
+}
+
+void UIVMInformationDialog::loadSettings()
+{
+    /* Restore window geometry: */
+    {
+        /* Load geometry: */
+        m_geometry = gEDataManager->informationWindowGeometry(this, m_pMachineWindow, vboxGlobal().managedVMUuid());
+#ifdef Q_WS_MAC
+        move(m_geometry.topLeft());
+        resize(m_geometry.size());
+#else /* Q_WS_MAC */
+        setGeometry(m_geometry);
+#endif /* !Q_WS_MAC */
+        LogRel(("GUI: UIVMInformationDialog: Geometry loaded to: Origin=%dx%d, Size=%dx%d\n",
+                m_geometry.x(), m_geometry.y(), m_geometry.width(), m_geometry.height()));
+
+        /* Maximize (if necessary): */
+        if (gEDataManager->informationWindowShouldBeMaximized(vboxGlobal().managedVMUuid()))
+            showMaximized();
+    }
+}
+
+void UIVMInformationDialog::saveSettings()
+{
+    /* Save window geometry: */
+    {
+        /* Save geometry: */
+#ifdef Q_WS_MAC
+        gEDataManager->setInformationWindowGeometry(m_geometry, ::darwinIsWindowMaximized(this), vboxGlobal().managedVMUuid());
+#else /* Q_WS_MAC */
+        gEDataManager->setInformationWindowGeometry(m_geometry, isMaximized(), vboxGlobal().managedVMUuid());
+#endif /* !Q_WS_MAC */
+        LogRel(("GUI: UIVMInformationDialog: Geometry saved as: Origin=%dx%d, Size=%dx%d\n",
+                m_geometry.x(), m_geometry.y(), m_geometry.width(), m_geometry.height()));
+    }
+}
+
+void UIVMInformationDialog::cleanup()
+{
+    /* Save settings: */
+    saveSettings();
+}
+
+QString UIVMInformationDialog::parseStatistics(const QString &strText)
+{
+    /* Filters VM statistics counters body: */
+    QRegExp query("^.+<Statistics>\n(.+)\n</Statistics>.*$");
+    if (query.indexIn(strText) == -1)
+        return QString();
+
+    /* Split whole VM statistics text to lines: */
+    const QStringList text = query.cap(1).split("\n");
+
+    /* Iterate through all VM statistics: */
+    ULONG64 uSumm = 0;
+    for (QStringList::const_iterator lineIt = text.begin(); lineIt != text.end(); ++lineIt)
+    {
+        /* Get current line: */
+        QString strLine = *lineIt;
+        strLine.remove(1, 1);
+        strLine.remove(strLine.length() -2, 2);
+
+        /* Parse incoming counter and fill the counter-element values: */
+        CounterElementType counter;
+        counter.type = strLine.section(" ", 0, 0);
+        strLine = strLine.section(" ", 1);
+        QStringList list = strLine.split("\" ");
+        for (QStringList::Iterator it = list.begin(); it != list.end(); ++it)
+        {
+            QString pair = *it;
+            QRegExp regExp("^(.+)=\"([^\"]*)\"?$");
+            regExp.indexIn(pair);
+            counter.list.insert(regExp.cap(1), regExp.cap(2));
+        }
+
+        /* Fill the output with the necessary counter's value.
+         * Currently we are using "c" field of simple counter only. */
+        QString result = counter.list.contains("c") ? counter.list["c"] : "0";
+        uSumm += result.toULongLong();
+    }
+
+    return QString::number(uSumm);
+}
+
+void UIVMInformationDialog::refreshStatistics()
+{
+    /* Skip for inactive session: */
+    if (m_session.isNull())
+        return;
+
+    /* Prepare templates: */
+    QString strTable = "<table width=100% cellspacing=1 cellpadding=0>%1</table>";
+    QString strHeader = "<tr><td width=22><img width=16 height=16 src='%1'></td>"
+                        "<td colspan=2><nobr><b>%2</b></nobr></td></tr>";
+    QString strParagraph = "<tr><td colspan=3></td></tr>";
+    QString strResult;
+
+    /* Get current machine: */
+    CMachine m = m_session.GetMachine();
+
+    /* Runtime Information: */
+    {
+        /* Get current console: */
+        CConsole console = m_session.GetConsole();
+
+        ULONG cGuestScreens = m.GetMonitorCount();
+        QVector<QString> aResolutions(cGuestScreens);
+        for (ULONG iScreen = 0; iScreen < cGuestScreens; ++iScreen)
+        {
+            /* Determine resolution: */
+            ULONG uWidth = 0;
+            ULONG uHeight = 0;
+            ULONG uBpp = 0;
+            LONG xOrigin = 0;
+            LONG yOrigin = 0;
+            KGuestMonitorStatus monitorStatus = KGuestMonitorStatus_Enabled;
+            console.GetDisplay().GetScreenResolution(iScreen, uWidth, uHeight, uBpp, xOrigin, yOrigin, monitorStatus);
+            QString strResolution = QString("%1x%2").arg(uWidth).arg(uHeight);
+            if (uBpp)
+                strResolution += QString("x%1").arg(uBpp);
+            strResolution += QString(" @%1,%2").arg(xOrigin).arg(yOrigin);
+            if (monitorStatus == KGuestMonitorStatus_Disabled)
+            {
+                strResolution += QString(" ");
+                strResolution += QString(VBoxGlobal::tr("off", "guest monitor status"));
+            }
+            aResolutions[iScreen] = strResolution;
+        }
+
+        /* Calculate uptime: */
+        uint32_t uUpSecs = (RTTimeProgramSecTS() / 5) * 5;
+        char szUptime[32];
+        uint32_t uUpDays = uUpSecs / (60 * 60 * 24);
+        uUpSecs -= uUpDays * 60 * 60 * 24;
+        uint32_t uUpHours = uUpSecs / (60 * 60);
+        uUpSecs -= uUpHours * 60 * 60;
+        uint32_t uUpMins  = uUpSecs / 60;
+        uUpSecs -= uUpMins * 60;
+        RTStrPrintf(szUptime, sizeof(szUptime), "%dd %02d:%02d:%02d",
+                    uUpDays, uUpHours, uUpMins, uUpSecs);
+        QString strUptime = QString(szUptime);
+
+        /* Determine clipboard mode: */
+        QString strClipboardMode = gpConverter->toString(m.GetClipboardMode());
+        /* Determine Drag&Drop mode: */
+        QString strDnDMode = gpConverter->toString(m.GetDnDMode());
+
+        /* Deterine virtualization attributes: */
+        CMachineDebugger debugger = console.GetDebugger();
+        QString strVirtualization = debugger.GetHWVirtExEnabled() ?
+            VBoxGlobal::tr("Active", "details report (VT-x/AMD-V)") :
+            VBoxGlobal::tr("Inactive", "details report (VT-x/AMD-V)");
+        QString strNestedPaging = debugger.GetHWVirtExNestedPagingEnabled() ?
+            VBoxGlobal::tr("Active", "details report (Nested Paging)") :
+            VBoxGlobal::tr("Inactive", "details report (Nested Paging)");
+        QString strUnrestrictedExecution = debugger.GetHWVirtExUXEnabled() ?
+            VBoxGlobal::tr("Active", "details report (Unrestricted Execution)") :
+            VBoxGlobal::tr("Inactive", "details report (Unrestricted Execution)");
+        QString strParavirtProvider = gpConverter->toString(m.GetEffectiveParavirtProvider());
+
+        /* Guest information: */
+        CGuest guest = console.GetGuest();
+        QString strGAVersion = guest.GetAdditionsVersion();
+        if (strGAVersion.isEmpty())
+            strGAVersion = tr("Not Detected", "guest additions");
+        else
+        {
+            ULONG uRevision = guest.GetAdditionsRevision();
+            if (uRevision != 0)
+                strGAVersion += QString(" r%1").arg(uRevision);
+        }
+        QString strOSType = guest.GetOSTypeId();
+        if (strOSType.isEmpty())
+            strOSType = tr("Not Detected", "guest os type");
+        else
+            strOSType = vboxGlobal().vmGuestOSTypeDescription(strOSType);
+
+        /* VRDE information: */
+        int iVRDEPort = console.GetVRDEServerInfo().GetPort();
+        QString strVRDEInfo = (iVRDEPort == 0 || iVRDEPort == -1)?
+            tr("Not Available", "details report (VRDE server port)") :
+            QString("%1").arg(iVRDEPort);
+
+        /* Searching for longest string: */
+        QStringList values;
+        for (ULONG iScreen = 0; iScreen < cGuestScreens; ++iScreen)
+            values << aResolutions[iScreen];
+        values << strUptime
+               << strVirtualization << strNestedPaging << strUnrestrictedExecution
+               << strGAVersion << strOSType << strVRDEInfo;
+        int iMaxLength = 0;
+        foreach (const QString &strValue, values)
+            iMaxLength = iMaxLength < fontMetrics().width(strValue)
+                         ? fontMetrics().width(strValue) : iMaxLength;
+
+        /* Summary: */
+        strResult += strHeader.arg(":/state_running_16px.png").arg(tr("Runtime Attributes"));
+        for (ULONG iScreen = 0; iScreen < cGuestScreens; ++iScreen)
+        {
+            QString strLabel(tr("Screen Resolution"));
+            /* The screen number makes sense only if there are multiple monitors in the guest: */
+            if (cGuestScreens > 1)
+                strLabel += QString(" %1").arg(iScreen + 1);
+            strResult += formatValue(strLabel, aResolutions[iScreen], iMaxLength);
+        }
+        strResult += formatValue(tr("VM Uptime"), strUptime, iMaxLength);
+        strResult += formatValue(tr("Clipboard Mode"), strClipboardMode, iMaxLength);
+        strResult += formatValue(tr("Drag and Drop Mode"), strDnDMode, iMaxLength);
+        strResult += formatValue(VBoxGlobal::tr("VT-x/AMD-V", "details report"), strVirtualization, iMaxLength);
+        strResult += formatValue(VBoxGlobal::tr("Nested Paging", "details report"), strNestedPaging, iMaxLength);
+        strResult += formatValue(VBoxGlobal::tr("Unrestricted Execution", "details report"), strUnrestrictedExecution, iMaxLength);
+        strResult += formatValue(VBoxGlobal::tr("Paravirtualization Interface", "details report"), strParavirtProvider, iMaxLength);
+        strResult += formatValue(tr("Guest Additions"), strGAVersion, iMaxLength);
+        strResult += formatValue(tr("Guest OS Type"), strOSType, iMaxLength);
+        strResult += formatValue(VBoxGlobal::tr("Remote Desktop Server Port", "details report (VRDE Server)"), strVRDEInfo, iMaxLength);
+        strResult += strParagraph;
+    }
+
+    /* Storage statistics: */
+    {
+        /* Prepare storage-statistics: */
+        QString strStorageStat;
+
+        /* Append result with storage-statistics header: */
+        strResult += strHeader.arg(":/hd_16px.png").arg(tr("Storage Statistics"));
+
+        /* Enumerate storage-controllers: */
+        CStorageControllerVector controllers = m.GetStorageControllers();
+        int iIDECount = 0, iSATACount = 0, iSCSICount = 0;
+        foreach (const CStorageController &controller, controllers)
+        {
+            /* Get controller attributes: */
+            QString strName = controller.GetName();
+            KStorageBus busType = controller.GetBus();
+            CMediumAttachmentVector attachments = m.GetMediumAttachmentsOfController(strName);
+            /* Skip empty and floppy attachments: */
+            if (!attachments.isEmpty() && busType != KStorageBus_Floppy)
+            {
+                /* Prepare storage templates: */
+                QString strHeaderStorage = "<tr><td></td><td colspan=2><nobr>%1</nobr></td></tr>";
+                /* Prepare full controller name: */
+                QString strControllerName = QApplication::translate("UIMachineSettingsStorage", "Controller: %1");
+                /* Append storage-statistics with controller name: */
+                strStorageStat += strHeaderStorage.arg(strControllerName.arg(controller.GetName()));
+                int iSCSIIndex = 0;
+                /* Enumerate storage-attachments: */
+                foreach (const CMediumAttachment &attachment, attachments)
+                {
+                    const LONG iPort = attachment.GetPort();
+                    const LONG iDevice = attachment.GetDevice();
+                    switch (busType)
+                    {
+                        case KStorageBus_IDE:
+                        {
+                            /* Append storage-statistics with IDE controller statistics: */
+                            strStorageStat += formatStorageElement(strName, iPort, iDevice,
+                                                                   QString("/Devices/IDE%1/ATA%2/Unit%3")
+                                                                          .arg(iIDECount).arg(iPort).arg(iDevice));
+                            break;
+                        }
+                        case KStorageBus_SATA:
+                        {
+                            /* Append storage-statistics with SATA controller statistics: */
+                            strStorageStat += formatStorageElement(strName, iPort, iDevice,
+                                                                   QString("/Devices/SATA%1/Port%2")
+                                                                          .arg(iSATACount).arg(iPort));
+                            break;
+                        }
+                        case KStorageBus_SCSI:
+                        {
+                            /* Append storage-statistics with SCSI controller statistics: */
+                            strStorageStat += formatStorageElement(strName, iPort, iDevice,
+                                                                   QString("/Devices/SCSI%1/%2")
+                                                                          .arg(iSCSICount).arg(iSCSIIndex));
+                            ++iSCSIIndex;
+                            break;
+                        }
+                        default:
+                            break;
+                    }
+                    strStorageStat += strParagraph;
+                }
+            }
+            /* Increment controller counters: */
+            switch (busType)
+            {
+                case KStorageBus_IDE:  ++iIDECount; break;
+                case KStorageBus_SATA: ++iSATACount; break;
+                case KStorageBus_SCSI: ++iSCSICount; break;
+                default: break;
+            }
+        }
+
+        /* If there are no storage devices: */
+        if (strStorageStat.isNull())
+        {
+            strStorageStat = composeArticle(tr("No Storage Devices"));
+            strStorageStat += strParagraph;
+        }
+
+        /* Append result with storage-statistics: */
+        strResult += strStorageStat;
+    }
+
+    /* Network statistics: */
+    {
+        /* Prepare netork-statistics: */
+        QString strNetworkStat;
+
+        /* Append result with network-statistics header: */
+        strResult += strHeader.arg(":/nw_16px.png").arg(tr("Network Statistics"));
+
+        /* Enumerate network-adapters: */
+        ulong uCount = vboxGlobal().virtualBox().GetSystemProperties().GetMaxNetworkAdapters(m.GetChipsetType());
+        for (ulong uSlot = 0; uSlot < uCount; ++uSlot)
+        {
+            /* Skip disabled adapters: */
+            if (m.GetNetworkAdapter(uSlot).GetEnabled())
+            {
+                /* Append network-statistics with adapter-statistics: */
+                strNetworkStat += formatNetworkElement(uSlot, QString("NA%1").arg(uSlot));
+                strNetworkStat += strParagraph;
+            }
+        }
+
+        /* If there are no network adapters: */
+        if (strNetworkStat.isNull())
+        {
+            strNetworkStat = composeArticle(tr("No Network Adapters"));
+            strNetworkStat += strParagraph;
+        }
+
+        /* Append result with network-statistics: */
+        strResult += strNetworkStat;
+    }
+
+    /* Show full composed page & save/restore scroll-bar position: */
+    int iScrollBarValue = m_browsers[1]->verticalScrollBar()->value();
+    setText(m_browsers[1], strResult);
+    m_browsers[1]->verticalScrollBar()->setValue(iScrollBarValue);
+}
+
+QString UIVMInformationDialog::formatValue(const QString &strValueName,
+                                    const QString &strValue,
+                                    int iMaxSize)
+{
+    if (m_session.isNull())
+        return QString();
+
+    QString strMargin;
+    int size = iMaxSize - fontMetrics().width(strValue);
+    for (int i = 0; i < size; ++i)
+        strMargin += QString("<img width=1 height=1 src=:/tpixel.png>");
+
+    QString bdyRow = "<tr>"
+                     "<td></td>"
+                     "<td><nobr>%1</nobr></td>"
+                     "<td align=right><nobr>%2%3</nobr></td>"
+                     "</tr>";
+
+    return bdyRow.arg(strValueName).arg(strValue).arg(strMargin);
+}
+
+QString UIVMInformationDialog::formatStorageElement(const QString &strControllerName,
+                                             LONG iPort, LONG iDevice,
+                                             const QString &strBelongsTo)
+{
+    if (m_session.isNull())
+        return QString();
+
+    QString strHeader = "<tr><td></td><td colspan=2><nobr>&nbsp;&nbsp;%1:</nobr></td></tr>";
+    CStorageController ctr = m_session.GetMachine().GetStorageControllerByName(strControllerName);
+    QString strName = gpConverter->toString(StorageSlot(ctr.GetBus(), iPort, iDevice));
+
+    return strHeader.arg(strName) + composeArticle(strBelongsTo, 2);
+}
+
+QString UIVMInformationDialog::formatNetworkElement(ULONG uSlot,
+                                             const QString &strBelongsTo)
+{
+    if (m_session.isNull())
+        return QString();
+
+    QString strHeader = "<tr><td></td><td colspan=2><nobr>%1</nobr></td></tr>";
+    QString strName = VBoxGlobal::tr("Adapter %1", "details report (network)").arg(uSlot + 1);
+
+    return strHeader.arg(strName) + composeArticle(strBelongsTo, 1);
+}
+
+QString UIVMInformationDialog::composeArticle(const QString &strBelongsTo, int iSpacesCount /* = 0 */)
+{
+    QFontMetrics fm = QApplication::fontMetrics();
+
+    QString strBody = "<tr><td></td><td width=50%><nobr>%1%2</nobr></td>"
+                      "<td align=right><nobr>%3%4</nobr></td></tr>";
+    QString strIndent;
+    for (int i = 0; i < iSpacesCount; ++i)
+        strIndent += "&nbsp;&nbsp;";
+    strBody = strBody.arg(strIndent);
+
+    QString strResult;
+
+    if (m_links.contains(strBelongsTo))
+    {
+        QStringList keys = m_links[strBelongsTo];
+        foreach (const QString &key, keys)
+        {
+            QString line(strBody);
+            if (m_names.contains(key) && m_values.contains(key) && m_units.contains(key))
+            {
+                line = line.arg(m_names[key]).arg(QString("%L1").arg(m_values[key].toULongLong()));
+                line = m_units[key].contains(QRegExp("\\[\\S+\\]")) ?
+                    line.arg(QString("<img src=:/tpixel.png width=%1 height=1>")
+                                    .arg(fm.width(QString(" %1").arg(m_units[key].mid(1, m_units[key].length() - 2))))) :
+                    line.arg(QString (" %1").arg(m_units[key]));
+                strResult += line;
+            }
+        }
+    }
+    else
+        strResult = strBody.arg(strBelongsTo).arg(QString()).arg(QString());
+
+    return strResult;
+}
+
+/* static */
+void UIVMInformationDialog::setText(QRichTextEdit *pTextEdit, QString strText)
+{
+    /* Temporary replace ":/tpixel.png" with "__tpixel__": */
+    strText.replace(":/tpixel.png", "__tpixel__");
+    /* Search for all the mentioned pixmaps: */
+    QRegExp exp(":/([^/]+.png)");
+    exp.setMinimal(true);
+    /* Initialize iterator: */
+    int iPos = exp.indexIn(strText);
+    while (iPos != -1)
+    {
+        /* Replace pixmap record with HiDPI-aware analog: */
+        strText.replace(iPos, 2, "pixmaps://");
+        /* Load HiDPI-aware pixmap: */
+        QPixmap pixmap = UIIconPool::pixmap(exp.cap(0));
+        /* Register loaded pixmap in text-edit' document: */
+        pTextEdit->document()->addResource(QTextDocument::ImageResource,
+                                           QUrl(QString("pixmaps://%1").arg(exp.cap(1))), QVariant(pixmap));
+        /* Advance iterator: */
+        iPos = exp.indexIn(strText);
+    }
+    /* Replace "__tpixel__" with ":/tpixel.png" back: */
+    strText.replace("__tpixel__", ":/tpixel.png");
+    /* Assign text finally: */
+    pTextEdit->setText(strText);
+}
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIVMInformationDialog.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIVMInformationDialog.h	(revision 58611)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/information/UIVMInformationDialog.h	(revision 58611)
@@ -0,0 +1,159 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIVMInformationDialog class declaration.
+ */
+
+/*
+ * Copyright (C) 2006-2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#ifndef ___UIVMInformationDialog_h___
+#define ___UIVMInformationDialog_h___
+
+/* Qt includes: */
+#include <QMainWindow>
+
+/* GUI includes: */
+#include "QIWithRetranslateUI.h"
+
+/* COM includes: */
+#include "COMEnums.h"
+#include "CSession.h"
+
+/* Forward declarations: */
+class QITabWidget;
+class QIDialogButtonBox;
+class QRichTextEdit;
+class UIMachineWindow;
+class QTimer;
+
+/** QMainWindow based dialog providing user with VM details and statistics. */
+class UIVMInformationDialog : public QIWithRetranslateUI<QMainWindow>
+{
+    Q_OBJECT;
+
+public:
+
+    /** VM statistics counter data map. */
+    typedef QMap <QString, QString> DataMapType;
+    /** VM statistics counter links map. */
+    typedef QMap <QString, QStringList> LinksMapType;
+    /** VM statistics counter struct. */
+    struct CounterElementType { QString type; DataMapType list; };
+
+    /** Shows (and creates if necessary)
+      * information-dialog for passed @a pMachineWindow. */
+    static void invoke(UIMachineWindow *pMachineWindow);
+
+protected:
+
+    /** Information dialog constructor. */
+    UIVMInformationDialog(UIMachineWindow *pMachineWindow);
+    /** Information dialog destructor. */
+    ~UIVMInformationDialog();
+
+    /** Translation handler. */
+    void retranslateUi();
+
+    /** Common event-handler. */
+    bool event(QEvent *pEvent);
+
+private slots:
+
+    /** Slot to destroy dialog immediately. */
+    void suicide() { delete this; }
+    /** Slot to update general VM details. */
+    void sltUpdateDetails();
+    /** Slot to update runtime VM statistics. */
+    void sltProcessStatistics();
+    /** Slot to handle tab-widget page change. */
+    void sltHandlePageChanged(int iIndex);
+
+private:
+
+    /** General prepare helper. */
+    void prepare();
+    /** Prepare helper for dialog itself. */
+    void prepareThis();
+    /** Prepare helper for central-widget. */
+    void prepareCentralWidget();
+    /** Prepare helper for tab-widget. */
+    void prepareTabWidget();
+    /** Prepare helper for @a iTabIndex. */
+    void prepareTab(int iTabIndex);
+    /** Prepare helper for button-box. */
+    void prepareButtonBox();
+    /** Load settings helper. */
+    void loadSettings();
+
+    /** Save settings helper. */
+    void saveSettings();
+    /** General cleanup helper. */
+    void cleanup();
+
+    /** Helper to parse passed VM statistics @a aText. */
+    QString parseStatistics(const QString &strText);
+    /** Helper to re-acquire whole VM statistics. */
+    void refreshStatistics();
+
+    /** Helper to format common VM statistics value. */
+    QString formatValue(const QString &strValueName, const QString &strValue, int iMaxSize);
+    /** Helper to format VM storage-statistics value. */
+    QString formatStorageElement(const QString &strCtrName, LONG iPort, LONG iDevice, const QString &strBelongsTo);
+    /** Helper to format VM network-statistics value. */
+    QString formatNetworkElement(ULONG uSlot, const QString &strBelongsTo);
+
+    /** Helper to compose user-oriented article. */
+    QString composeArticle(const QString &strBelongsTo, int iSpacesCount = 0);
+
+    /** Helper to set @a strText with HiDPI-aware pixmaps to corresponding @a pTextEdit. */
+    static void setText(QRichTextEdit *pTextEdit, QString strText);
+
+    /** @name General variables.
+     * @{ */
+    /** Dialog instance pointer. */
+    static UIVMInformationDialog *m_spInstance;
+    /** Machine-window to center dialog according. */
+    UIMachineWindow       *m_pMachineWindow;
+    /** Current dialog geometry. */
+    QRect                  m_geometry;
+    /** @} */
+
+    /** @name Widget variables.
+     * @{ */
+    /** Dialog tab-widget. */
+    QITabWidget               *m_pTabWidget;
+    /** Dialog tabs map. */
+    QMap<int, QWidget*>        m_tabs;
+    /** Dialog browsers map. */
+    QMap<int, QRichTextEdit*>  m_browsers;
+    /** Dialog button-box. */
+    QIDialogButtonBox         *m_pButtonBox;
+    /** @} */
+
+    /** @name VM details/statistics variables.
+     * @{ */
+    /** Session to acquire VM details/statistics from. */
+    CSession           m_session;
+    /** VM statistics update timer. */
+    QTimer            *m_pTimer;
+    /** VM statistics counter names. */
+    DataMapType        m_names;
+    /** VM statistics counter values. */
+    DataMapType        m_values;
+    /** VM statistics counter units. */
+    DataMapType        m_units;
+    /** VM statistics counter links. */
+    LinksMapType       m_links;
+    /** @} */
+};
+
+#endif /* !___UIVMInformationDialog_h___ */
