Index: /trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk	(revision 50842)
+++ /trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk	(revision 50843)
@@ -396,4 +396,5 @@
 	src/widgets/graphics/UIGraphicsZoomButton.h \
 	src/widgets/graphics/UIGraphicsToolBar.h \
+	src/widgets/graphics/UIGraphicsTextPane.h \
 	src/wizards/UIWizard.h \
 	src/wizards/UIWizardPage.h \
@@ -680,4 +681,5 @@
 	src/widgets/graphics/UIGraphicsZoomButton.cpp \
 	src/widgets/graphics/UIGraphicsToolBar.cpp \
+	src/widgets/graphics/UIGraphicsTextPane.cpp \
 	src/wizards/UIWizard.cpp \
 	src/wizards/UIWizardPage.cpp \
Index: /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElement.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElement.cpp	(revision 50842)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElement.cpp	(revision 50843)
@@ -23,5 +23,4 @@
 #include <QPropertyAnimation>
 #include <QSignalTransition>
-#include <QTextLayout>
 #include <QStyleOptionGraphicsItem>
 #include <QGraphicsSceneMouseEvent>
@@ -32,4 +31,5 @@
 #include "UIGDetailsModel.h"
 #include "UIGraphicsRotatorButton.h"
+#include "UIGraphicsTextPane.h"
 #include "UIIconPool.h"
 #include "UIConverter.h"
@@ -42,10 +42,9 @@
     , m_iMinimumHeaderWidth(0)
     , m_iMinimumHeaderHeight(0)
-    , m_iMinimumTextWidth(0)
-    , m_iMinimumTextHeight(0)
+    , m_pButton(0)
     , m_fClosed(!fOpened)
-    , m_pButton(0)
     , m_iAdditionalHeight(0)
     , m_fAnimationRunning(false)
+    , m_pTextPane(0)
     , m_fHovered(false)
     , m_fNameHovered(false)
@@ -62,4 +61,6 @@
     /* Prepare button: */
     prepareButton();
+    /* Prepare text-pane: */
+    prepareTextPane();
 
     /* Setup size-policy: */
@@ -130,4 +131,10 @@
     /* Notify about finishing: */
     emit sigToggleElementFinished();
+}
+
+void UIGDetailsElement::resizeEvent(QGraphicsSceneResizeEvent*)
+{
+    /* Update layout: */
+    updateLayout();
 }
 
@@ -165,134 +172,4 @@
 }
 
-void UIGDetailsElement::updateMinimumTextWidth()
-{
-    /* Prepare variables: */
-    int iSpacing = data(ElementData_Spacing).toInt();
-    int iMinimumTextColumnWidth = data(ElementData_MinimumTextColumnWidth).toInt();
-    QFontMetrics fm(m_textFont, model()->paintDevice());
-
-    /* Search for the maximum line widths: */
-    int iMaximumLeftLineWidth = 0;
-    int iMaximumRightLineWidth = 0;
-    bool fSingleColumnText = true;
-    foreach (const UITextTableLine line, m_text)
-    {
-        bool fRightColumnPresent = !line.second.isEmpty();
-        if (fRightColumnPresent)
-            fSingleColumnText = false;
-        QString strLeftLine = fRightColumnPresent ? line.first + ":" : line.first;
-        QString strRightLine = line.second;
-        iMaximumLeftLineWidth = qMax(iMaximumLeftLineWidth, fm.width(strLeftLine));
-        iMaximumRightLineWidth = qMax(iMaximumRightLineWidth, fm.width(strRightLine));
-    }
-    iMaximumLeftLineWidth += 1;
-    iMaximumRightLineWidth += 1;
-
-    /* Calculate minimum-text-width: */
-    int iMinimumTextWidth = 0;
-    if (fSingleColumnText)
-    {
-        /* Take into account only left column: */
-        int iMinimumLeftColumnWidth = qMin(iMaximumLeftLineWidth, iMinimumTextColumnWidth);
-        iMinimumTextWidth = iMinimumLeftColumnWidth;
-    }
-    else
-    {
-        /* Take into account both columns, but wrap only right one: */
-        int iMinimumLeftColumnWidth = iMaximumLeftLineWidth;
-        int iMinimumRightColumnWidth = qMin(iMaximumRightLineWidth, iMinimumTextColumnWidth);
-        iMinimumTextWidth = iMinimumLeftColumnWidth + iSpacing + iMinimumRightColumnWidth;
-    }
-
-    /* Is there something changed? */
-    if (m_iMinimumTextWidth != iMinimumTextWidth)
-    {
-        /* Remember new value: */
-        m_iMinimumTextWidth = iMinimumTextWidth;
-        /* Recursively update size-hint: */
-        updateGeometry();
-    }
-}
-
-void UIGDetailsElement::updateMinimumTextHeight()
-{
-    /* Prepare variables: */
-    int iMargin = data(ElementData_Margin).toInt();
-    int iSpacing = data(ElementData_Spacing).toInt();
-    int iMinimumTextColumnWidth = data(ElementData_MinimumTextColumnWidth).toInt();
-    int iMaximumTextWidth = (int)geometry().width() - 3 * iMargin - iSpacing;
-    QPaintDevice *pPaintDevice = model()->paintDevice();
-    QFontMetrics fm(m_textFont, pPaintDevice);
-
-    /* Search for the maximum line widths: */
-    int iMaximumLeftLineWidth = 0;
-    int iMaximumRightLineWidth = 0;
-    bool fSingleColumnText = true;
-    foreach (const UITextTableLine line, m_text)
-    {
-        bool fRightColumnPresent = !line.second.isEmpty();
-        if (fRightColumnPresent)
-            fSingleColumnText = false;
-        QString strFirstLine = fRightColumnPresent ? line.first + ":" : line.first;
-        QString strSecondLine = line.second;
-        iMaximumLeftLineWidth = qMax(iMaximumLeftLineWidth, fm.width(strFirstLine));
-        iMaximumRightLineWidth = qMax(iMaximumRightLineWidth, fm.width(strSecondLine));
-    }
-    iMaximumLeftLineWidth += 1;
-    iMaximumRightLineWidth += 1;
-
-    /* Calculate column widths: */
-    int iLeftColumnWidth = 0;
-    int iRightColumnWidth = 0;
-    if (fSingleColumnText)
-    {
-        /* Take into account only left column: */
-        iLeftColumnWidth = qMax(iMinimumTextColumnWidth, iMaximumTextWidth);
-    }
-    else
-    {
-        /* Take into account both columns, but wrap only right one: */
-        iLeftColumnWidth = iMaximumLeftLineWidth;
-        iRightColumnWidth = iMaximumTextWidth - iLeftColumnWidth;
-    }
-
-    /* Calculate minimum-text-height: */
-    int iMinimumTextHeight = 0;
-    foreach (const UITextTableLine line, m_text)
-    {
-        /* First layout: */
-        int iLeftColumnHeight = 0;
-        if (!line.first.isEmpty())
-        {
-            bool fRightColumnPresent = !line.second.isEmpty();
-            QTextLayout *pTextLayout = prepareTextLayout(m_textFont, pPaintDevice,
-                                                         fRightColumnPresent ? line.first + ":" : line.first,
-                                                         iLeftColumnWidth, iLeftColumnHeight);
-            delete pTextLayout;
-        }
-
-        /* Second layout: */
-        int iRightColumnHeight = 0;
-        if (!line.second.isEmpty())
-        {
-            QTextLayout *pTextLayout = prepareTextLayout(m_textFont, pPaintDevice, line.second,
-                                                         iRightColumnWidth, iRightColumnHeight);
-            delete pTextLayout;
-        }
-
-        /* Append summary text height: */
-        iMinimumTextHeight += qMax(iLeftColumnHeight, iRightColumnHeight);
-    }
-
-    /* Is there something changed? */
-    if (m_iMinimumTextHeight != iMinimumTextHeight)
-    {
-        /* Remember new value: */
-        m_iMinimumTextHeight = iMinimumTextHeight;
-        /* Recursively update size-hint: */
-        updateGeometry();
-    }
-}
-
 void UIGDetailsElement::setIcon(const QIcon &icon)
 {
@@ -318,29 +195,14 @@
 }
 
+const UITextTable& UIGDetailsElement::text() const
+{
+    /* Retrieve text from text-pane: */
+    return m_pTextPane->text();
+}
+
 void UIGDetailsElement::setText(const UITextTable &text)
 {
-    /* Clear first: */
-    m_text.clear();
-    /* For each the line of the passed table: */
-    foreach (const UITextTableLine &line, text)
-    {
-        /* Get lines: */
-        QString strLeftLine = line.first;
-        QString strRightLine = line.second;
-        /* If 2nd line is empty: */
-        if (strRightLine.isEmpty())
-        {
-            /* Parse the 1st one: */
-            QStringList subLines = strLeftLine.split(QRegExp("\\n"));
-            foreach (const QString &strSubLine, subLines)
-                m_text << UITextTableLine(strSubLine, QString());
-        }
-        else
-            m_text << UITextTableLine(strLeftLine, strRightLine);
-    }
-
-    /* Update linked values: */
-    updateMinimumTextWidth();
-    updateMinimumTextHeight();
+    /* Pass text to text-pane: */
+    m_pTextPane->setText(text);
 }
 
@@ -357,5 +219,5 @@
 
     /* Maximum width: */
-    iMinimumWidthHint = qMax(m_iMinimumHeaderWidth, m_iMinimumTextWidth);
+    iMinimumWidthHint = qMax(m_iMinimumHeaderWidth, (int)m_pTextPane->minimumSizeHint().width());
 
     /* And 4 margins: 2 left and 2 right: */
@@ -382,6 +244,6 @@
     {
         /* Add text height: */
-        if (!m_text.isEmpty())
-            iMinimumHeightHint += 2 * iMargin + m_iMinimumTextHeight;
+        if (!m_pTextPane->isEmpty())
+            iMinimumHeightHint += 2 * iMargin + (int)m_pTextPane->minimumSizeHint().height();
     }
 
@@ -404,12 +266,33 @@
     QSize size = geometry().size().toSize();
     int iMargin = data(ElementData_Margin).toInt();
+
+    /* Layout button: */
     int iButtonWidth = m_buttonSize.width();
     int iButtonHeight = m_buttonSize.height();
-
-    /* Layout button: */
     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();
+    }
 }
 
@@ -504,4 +387,10 @@
 }
 
+void UIGDetailsElement::prepareTextPane()
+{
+    /* Create text-pane: */
+    m_pTextPane = new UIGraphicsTextPane(this, model()->paintDevice());
+}
+
 void UIGDetailsElement::paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption, QWidget*)
 {
@@ -540,19 +429,18 @@
     QColor buttonTextColor = pal.color(QPalette::Active, QPalette::ButtonText);
     QColor linkTextColor = pal.color(QPalette::Active, QPalette::Link);
-    QColor baseTextColor = pal.color(QPalette::Active, QPalette::Text);
 
     /* Paint pixmap: */
-    int iMachinePixmapX = 2 * iMargin;
-    int iMachinePixmapY = iPixmapHeight == iMaximumHeight ?
+    int iElementPixmapX = 2 * iMargin;
+    int iElementPixmapY = iPixmapHeight == iMaximumHeight ?
                           iMargin : iMargin + (iMaximumHeight - iPixmapHeight) / 2;
     paintPixmap(/* Painter: */
                 pPainter,
                 /* Rectangle to paint in: */
-                QRect(QPoint(iMachinePixmapX, iMachinePixmapY), m_pixmapSize),
+                QRect(QPoint(iElementPixmapX, iElementPixmapY), m_pixmapSize),
                 /* Pixmap to paint: */
                 m_pixmap);
 
     /* Paint name: */
-    int iMachineNameX = iMachinePixmapX +
+    int iMachineNameX = iElementPixmapX +
                         m_pixmapSize.width() +
                         iSpacing;
@@ -571,86 +459,4 @@
               /* Name hovered? */
               m_fNameHovered ? linkTextColor : buttonTextColor);
-
-    /* Paint text: */
-    if (!m_fClosed && !m_text.isEmpty() && !m_fAnimationRunning)
-    {
-        /* Prepare painter: */
-        pPainter->save();
-        pPainter->setPen(baseTextColor);
-
-        /* Prepare variables: */
-        int iMinimumTextColumnWidth = data(ElementData_MinimumTextColumnWidth).toInt();
-        int iMaximumTextWidth = geometry().width() - 3 * iMargin - iSpacing;
-        QPaintDevice *pPaintDevice = model()->paintDevice();
-        QFontMetrics fm(m_textFont, pPaintDevice);
-
-        /* Search for the maximum line widths: */
-        int iMaximumLeftLineWidth = 0;
-        int iMaximumRightLineWidth = 0;
-        bool fSingleColumnText = true;
-        foreach (const UITextTableLine line, m_text)
-        {
-            bool fRightColumnPresent = !line.second.isEmpty();
-            if (fRightColumnPresent)
-                fSingleColumnText = false;
-            QString strFirstLine = fRightColumnPresent ? line.first + ":" : line.first;
-            QString strSecondLine = line.second;
-            iMaximumLeftLineWidth = qMax(iMaximumLeftLineWidth, fm.width(strFirstLine));
-            iMaximumRightLineWidth = qMax(iMaximumRightLineWidth, fm.width(strSecondLine));
-        }
-        iMaximumLeftLineWidth += 1;
-        iMaximumRightLineWidth += 1;
-
-        /* Calculate column widths: */
-        int iLeftColumnWidth = 0;
-        int iRightColumnWidth = 0;
-        if (fSingleColumnText)
-        {
-            /* Take into account only left column: */
-            iLeftColumnWidth = qMax(iMinimumTextColumnWidth, iMaximumTextWidth);
-        }
-        else
-        {
-            /* Take into account both columns, but wrap only right one: */
-            iLeftColumnWidth = iMaximumLeftLineWidth;
-            iRightColumnWidth = iMaximumTextWidth - iLeftColumnWidth;
-        }
-
-        /* Where to paint? */
-        int iMachineTextX = iMachinePixmapX;
-        int iMachineTextY = iMargin + m_iMinimumHeaderHeight + 2 * iMargin;
-
-        /* For each the line: */
-        foreach (const UITextTableLine line, m_text)
-        {
-            /* First layout: */
-            int iLeftColumnHeight = 0;
-            if (!line.first.isEmpty())
-            {
-                bool fRightColumnPresent = !line.second.isEmpty();
-                QTextLayout *pTextLayout = prepareTextLayout(m_textFont, pPaintDevice,
-                                                             fRightColumnPresent ? line.first + ":" : line.first,
-                                                             iLeftColumnWidth, iLeftColumnHeight);
-                pTextLayout->draw(pPainter, QPointF(iMachineTextX, iMachineTextY));
-                delete pTextLayout;
-            }
-
-            /* Second layout: */
-            int iRightColumnHeight = 0;
-            if (!line.second.isEmpty())
-            {
-                QTextLayout *pTextLayout = prepareTextLayout(m_textFont, pPaintDevice,
-                                                             line.second, iRightColumnWidth, iRightColumnHeight);
-                pTextLayout->draw(pPainter, QPointF(iMachineTextX + iLeftColumnWidth + iSpacing, iMachineTextY));
-                delete pTextLayout;
-            }
-
-            /* Indent Y: */
-            iMachineTextY += qMax(iLeftColumnHeight, iRightColumnHeight);
-        }
-
-        /* Restore painter: */
-        pPainter->restore();
-    }
 }
 
@@ -782,11 +588,11 @@
     int iSpacing = data(ElementData_Spacing).toInt();
     int iNameHeight = m_nameSize.height();
-    int iMachineNameX = 2 * iMargin + m_pixmapSize.width() + iSpacing;
-    int iMachineNameY = iNameHeight == m_iMinimumHeaderHeight ?
+    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(iMachineNameX, iMachineNameY), m_nameSize).contains(point);
+    bool fNameHovered = QRect(QPoint(iElementNameX, iElementNameY), m_nameSize).contains(point);
     if (m_pSet->elementNameHoverable() && m_fNameHovered != fNameHovered)
     {
@@ -803,59 +609,4 @@
         unsetCursor();
     update();
-}
-
-/* static  */
-QTextLayout* UIGDetailsElement::prepareTextLayout(const QFont &font, QPaintDevice *pPaintDevice,
-                                                  const QString &strText, int iWidth, int &iHeight)
-{
-    /* Prepare variables: */
-    QFontMetrics fm(font, pPaintDevice);
-    int iLeading = fm.leading();
-
-    /* Only bold sub-strings are currently handled: */
-    QString strModifiedText(strText);
-    QRegExp boldRegExp("<b>([\\s\\S]+)</b>");
-    QList<QTextLayout::FormatRange> formatRangeList;
-    while (boldRegExp.indexIn(strModifiedText) != -1)
-    {
-        /* Prepare format: */
-        QTextLayout::FormatRange formatRange;
-        QFont font = formatRange.format.font();
-        font.setBold(true);
-        formatRange.format.setFont(font);
-        formatRange.start = boldRegExp.pos(0);
-        formatRange.length = boldRegExp.cap(1).size();
-        /* Add format range to list: */
-        formatRangeList << formatRange;
-        /* Replace sub-string: */
-        strModifiedText.replace(boldRegExp.cap(0), boldRegExp.cap(1));
-    }
-
-    /* Create layout; */
-    QTextLayout *pTextLayout = new QTextLayout(strModifiedText, font, pPaintDevice);
-    pTextLayout->setAdditionalFormats(formatRangeList);
-
-    /* Configure layout: */
-    QTextOption textOption;
-    textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
-    pTextLayout->setTextOption(textOption);
-
-    /* Build layout: */
-    pTextLayout->beginLayout();
-    while (1)
-    {
-        QTextLine line = pTextLayout->createLine();
-        if (!line.isValid())
-            break;
-
-        line.setLineWidth(iWidth);
-        iHeight += iLeading;
-        line.setPosition(QPointF(0, iHeight));
-        iHeight += line.height();
-    }
-    pTextLayout->endLayout();
-
-    /* Return layout: */
-    return pTextLayout;
 }
 
Index: /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElement.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElement.h	(revision 50842)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElement.h	(revision 50843)
@@ -31,4 +31,5 @@
 class CMachine;
 class UIGraphicsRotatorButton;
+class UIGraphicsTextPane;
 class QTextLayout;
 class QStateMachine;
@@ -38,5 +39,4 @@
 typedef QPair<QString, QString> UITextTableLine;
 typedef QList<UITextTableLine> UITextTable;
-Q_DECLARE_METATYPE(UITextTable);
 
 /* Details element
@@ -104,4 +104,7 @@
     };
 
+    /** This event handler is delivered after the widget has been resized. */
+    void resizeEvent(QGraphicsSceneResizeEvent *pEvent);
+
     /* Data provider: */
     QVariant data(int iKey) const;
@@ -110,6 +113,4 @@
     void updateMinimumHeaderWidth();
     void updateMinimumHeaderHeight();
-    void updateMinimumTextWidth();
-    void updateMinimumTextHeight();
 
     /* API: Icon stuff: */
@@ -120,5 +121,5 @@
 
     /* API: Text stuff: */
-    UITextTable text() const { return m_text; }
+    const UITextTable& text() const;
     void setText(const UITextTable &text);
 
@@ -156,4 +157,5 @@
     void prepareElement();
     void prepareButton();
+    void prepareTextPane();
 
     /* Helpers: Paint stuff: */
@@ -174,8 +176,4 @@
     void updateNameHoverLink();
 
-    /* Helper: Layout stuff: */
-    static QTextLayout* prepareTextLayout(const QFont &font, QPaintDevice *pPaintDevice,
-                                          const QString &strText, int iWidth, int &iHeight);
-
     /* Helper: Animation stuff: */
     void updateAnimationParameters();
@@ -186,5 +184,4 @@
     QPixmap m_pixmap;
     QString m_strName;
-    UITextTable m_text;
     int m_iCornerRadius;
     QFont m_nameFont;
@@ -195,12 +192,13 @@
     int m_iMinimumHeaderWidth;
     int m_iMinimumHeaderHeight;
-    int m_iMinimumTextWidth;
-    int m_iMinimumTextHeight;
-
-    /* Variables: Toggle stuff: */
+
+    /* Variables: Toggle-button stuff: */
+    UIGraphicsRotatorButton *m_pButton;
     bool m_fClosed;
-    UIGraphicsRotatorButton *m_pButton;
     int m_iAdditionalHeight;
     bool m_fAnimationRunning;
+
+    /* Variables: Text-pane stuff: */
+    UIGraphicsTextPane *m_pTextPane;
 
     /* Variables: Hover stuff: */
Index: /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElements.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElements.cpp	(revision 50842)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElements.cpp	(revision 50843)
@@ -29,4 +29,5 @@
 #include "UIIconPool.h"
 #include "UIConverter.h"
+#include "UIGraphicsTextPane.h"
 
 /* COM includes: */
Index: /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsSet.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsSet.cpp	(revision 50842)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsSet.cpp	(revision 50843)
@@ -515,6 +515,4 @@
                     /* Resize element to required width: */
                     pElement->resize(iWidth, pElement->geometry().height());
-                    /* Update minimum-height-hint: */
-                    pElement->updateMinimumTextHeight();
                 }
                 /* Acquire required height: */
Index: /trunk/src/VBox/Frontends/VirtualBox/src/widgets/graphics/UIGraphicsTextPane.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/widgets/graphics/UIGraphicsTextPane.cpp	(revision 50843)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/widgets/graphics/UIGraphicsTextPane.cpp	(revision 50843)
@@ -0,0 +1,341 @@
+/* $Id$ */
+/** @file
+ * VBox Qt GUI - UIGraphicsTextPane and UITask class implementation.
+ */
+
+/*
+ * Copyright (C) 2012-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.
+ */
+
+/* Qt includes: */
+#include <QFontMetrics>
+#include <QTextLayout>
+#include <QPainter>
+
+/* GUI includes: */
+#include "UIGraphicsTextPane.h"
+
+UIGraphicsTextPane::UIGraphicsTextPane(QIGraphicsWidget *pParent, QPaintDevice *pPaintDevice)
+    : QIGraphicsWidget(pParent)
+    , m_pPaintDevice(pPaintDevice)
+    , m_iMargin(0)
+    , m_iSpacing(10)
+    , m_iMinimumTextColumnWidth(100)
+    , m_iMinimumTextWidth(0)
+    , m_iMinimumTextHeight(0)
+{
+}
+
+void UIGraphicsTextPane::setText(const UITextTable &text)
+{
+    /* Clear text: */
+    m_text.clear();
+
+    /* For each the line of the passed table: */
+    foreach (const UITextTableLine &line, text)
+    {
+        /* Lines: */
+        QString strLeftLine = line.first;
+        QString strRightLine = line.second;
+
+        /* If 2nd line is NOT empty: */
+        if (!strRightLine.isEmpty())
+        {
+            /* Take both lines 'as is': */
+            m_text << UITextTableLine(strLeftLine, strRightLine);
+        }
+        /* If 2nd line is empty: */
+        else
+        {
+            /* Parse the 1st one to sub-lines: */
+            QStringList subLines = strLeftLine.split(QRegExp("\\n"));
+            foreach (const QString &strSubLine, subLines)
+                m_text << UITextTableLine(strSubLine, QString());
+        }
+    }
+
+    /* Update minimum text size-hint: */
+    updateMinimumTextWidthHint();
+    updateMinimumTextHeightHint();
+}
+
+void UIGraphicsTextPane::updateMinimumTextWidthHint()
+{
+    /* Prepare variables: */
+    QFontMetrics fm(font(), m_pPaintDevice);
+
+    /* Search for the maximum line widths: */
+    int iMaximumLeftLineWidth = 0;
+    int iMaximumRightLineWidth = 0;
+    bool fSingleColumnText = true;
+    foreach (const UITextTableLine &line, m_text)
+    {
+        bool fRightColumnPresent = !line.second.isEmpty();
+        if (fRightColumnPresent)
+            fSingleColumnText = false;
+        QString strLeftLine = fRightColumnPresent ? line.first + ":" : line.first;
+        QString strRightLine = line.second;
+        iMaximumLeftLineWidth = qMax(iMaximumLeftLineWidth, fm.width(strLeftLine));
+        iMaximumRightLineWidth = qMax(iMaximumRightLineWidth, fm.width(strRightLine));
+    }
+    iMaximumLeftLineWidth += 1;
+    iMaximumRightLineWidth += 1;
+
+    /* Calculate minimum-text-width: */
+    int iMinimumTextWidth = 0;
+    if (fSingleColumnText)
+    {
+        /* Take into account only left column: */
+        int iMinimumLeftColumnWidth = qMin(iMaximumLeftLineWidth, m_iMinimumTextColumnWidth);
+        iMinimumTextWidth = iMinimumLeftColumnWidth;
+    }
+    else
+    {
+        /* Take into account both columns, but wrap only right one: */
+        int iMinimumLeftColumnWidth = iMaximumLeftLineWidth;
+        int iMinimumRightColumnWidth = qMin(iMaximumRightLineWidth, m_iMinimumTextColumnWidth);
+        iMinimumTextWidth = iMinimumLeftColumnWidth + m_iSpacing + iMinimumRightColumnWidth;
+    }
+
+    /* Make sure something changed: */
+    if (m_iMinimumTextWidth == iMinimumTextWidth)
+        return;
+
+    /* Remember new value: */
+    m_iMinimumTextWidth = iMinimumTextWidth;
+
+    /* Notify layout if any: */
+    updateGeometry();
+}
+
+void UIGraphicsTextPane::updateMinimumTextHeightHint()
+{
+    /* Prepare variables: */
+    int iMaximumTextWidth = (int)size().width() - 2 * m_iMargin - m_iSpacing;
+    QFontMetrics fm(font(), m_pPaintDevice);
+
+    /* Search for the maximum line widths: */
+    int iMaximumLeftLineWidth = 0;
+    int iMaximumRightLineWidth = 0;
+    bool fSingleColumnText = true;
+    foreach (const UITextTableLine &line, m_text)
+    {
+        bool fRightColumnPresent = !line.second.isEmpty();
+        if (fRightColumnPresent)
+            fSingleColumnText = false;
+        QString strFirstLine = fRightColumnPresent ? line.first + ":" : line.first;
+        QString strSecondLine = line.second;
+        iMaximumLeftLineWidth = qMax(iMaximumLeftLineWidth, fm.width(strFirstLine));
+        iMaximumRightLineWidth = qMax(iMaximumRightLineWidth, fm.width(strSecondLine));
+    }
+    iMaximumLeftLineWidth += 1;
+    iMaximumRightLineWidth += 1;
+
+    /* Calculate column widths: */
+    int iLeftColumnWidth = 0;
+    int iRightColumnWidth = 0;
+    if (fSingleColumnText)
+    {
+        /* Take into account only left column: */
+        iLeftColumnWidth = qMax(m_iMinimumTextColumnWidth, iMaximumTextWidth);
+    }
+    else
+    {
+        /* Take into account both columns, but wrap only right one: */
+        iLeftColumnWidth = iMaximumLeftLineWidth;
+        iRightColumnWidth = iMaximumTextWidth - iLeftColumnWidth;
+    }
+
+    /* Calculate minimum-text-height: */
+    int iMinimumTextHeight = 0;
+    foreach (const UITextTableLine line, m_text)
+    {
+        /* First layout: */
+        int iLeftColumnHeight = 0;
+        if (!line.first.isEmpty())
+        {
+            bool fRightColumnPresent = !line.second.isEmpty();
+            QTextLayout *pTextLayout = buildTextLayout(font(), m_pPaintDevice,
+                                                       fRightColumnPresent ? line.first + ":" : line.first,
+                                                       iLeftColumnWidth, iLeftColumnHeight);
+            delete pTextLayout;
+        }
+
+        /* Second layout: */
+        int iRightColumnHeight = 0;
+        if (!line.second.isEmpty())
+        {
+            QTextLayout *pTextLayout = buildTextLayout(font(), m_pPaintDevice, line.second,
+                                                       iRightColumnWidth, iRightColumnHeight);
+            delete pTextLayout;
+        }
+
+        /* Append summary text height: */
+        iMinimumTextHeight += qMax(iLeftColumnHeight, iRightColumnHeight);
+    }
+
+    /* Make sure something changed: */
+    if (m_iMinimumTextHeight == iMinimumTextHeight)
+        return;
+
+    /* Remember new value: */
+    m_iMinimumTextHeight = iMinimumTextHeight;
+
+    /* Notify layout if any: */
+    updateGeometry();
+}
+
+QSizeF UIGraphicsTextPane::sizeHint(Qt::SizeHint which, const QSizeF &constraint /* = QSizeF() */) const
+{
+    /* Calculate minimum size-hint: */
+    if (which == Qt::MinimumSize)
+    {
+        int iWidth = 2 * m_iMargin + m_iMinimumTextWidth;
+        int iHeight = 2 * m_iMargin + m_iMinimumTextHeight;
+        return QSize(iWidth, iHeight);
+    }
+    /* Call to base-class: */
+    return QIGraphicsWidget::sizeHint(which, constraint);
+}
+
+void UIGraphicsTextPane::resizeEvent(QGraphicsSceneResizeEvent*)
+{
+    /* Update minimum text height-hint: */
+    updateMinimumTextHeightHint();
+}
+
+void UIGraphicsTextPane::paint(QPainter *pPainter, const QStyleOptionGraphicsItem*, QWidget*)
+{
+    /* Prepare variables: */
+    int iMaximumTextWidth = (int)size().width() - 2 * m_iMargin - m_iSpacing;
+    QFontMetrics fm(font(), m_pPaintDevice);
+
+    /* Where to paint? */
+    int iTextX = m_iMargin;
+    int iTextY = m_iMargin;
+
+    /* Search for the maximum line widths: */
+    int iMaximumLeftLineWidth = 0;
+    int iMaximumRightLineWidth = 0;
+    bool fSingleColumnText = true;
+    foreach (const UITextTableLine line, m_text)
+    {
+        bool fRightColumnPresent = !line.second.isEmpty();
+        if (fRightColumnPresent)
+            fSingleColumnText = false;
+        QString strFirstLine = fRightColumnPresent ? line.first + ":" : line.first;
+        QString strSecondLine = line.second;
+        iMaximumLeftLineWidth = qMax(iMaximumLeftLineWidth, fm.width(strFirstLine));
+        iMaximumRightLineWidth = qMax(iMaximumRightLineWidth, fm.width(strSecondLine));
+    }
+    iMaximumLeftLineWidth += 1;
+    iMaximumRightLineWidth += 1;
+
+    /* Calculate column widths: */
+    int iLeftColumnWidth = 0;
+    int iRightColumnWidth = 0;
+    if (fSingleColumnText)
+    {
+        /* Take into account only left column: */
+        iLeftColumnWidth = qMax(m_iMinimumTextColumnWidth, iMaximumTextWidth);
+    }
+    else
+    {
+        /* Take into account both columns, but wrap only right one: */
+        iLeftColumnWidth = iMaximumLeftLineWidth;
+        iRightColumnWidth = iMaximumTextWidth - iLeftColumnWidth;
+    }
+
+    /* For each the line: */
+    foreach (const UITextTableLine line, m_text)
+    {
+        /* First layout: */
+        int iLeftColumnHeight = 0;
+        if (!line.first.isEmpty())
+        {
+            bool fRightColumnPresent = !line.second.isEmpty();
+            QTextLayout *pTextLayout = buildTextLayout(font(), m_pPaintDevice,
+                                                       fRightColumnPresent ? line.first + ":" : line.first,
+                                                       iLeftColumnWidth, iLeftColumnHeight);
+            pTextLayout->draw(pPainter, QPointF(iTextX, iTextY));
+            delete pTextLayout;
+        }
+
+        /* Second layout: */
+        int iRightColumnHeight = 0;
+        if (!line.second.isEmpty())
+        {
+            QTextLayout *pTextLayout = buildTextLayout(font(), m_pPaintDevice,
+                                                       line.second, iRightColumnWidth, iRightColumnHeight);
+            pTextLayout->draw(pPainter, QPointF(iTextX + iLeftColumnWidth + m_iSpacing, iTextY));
+            delete pTextLayout;
+        }
+
+        /* Indent Y: */
+        iTextY += qMax(iLeftColumnHeight, iRightColumnHeight);
+    }
+}
+
+/* static  */
+QTextLayout* UIGraphicsTextPane::buildTextLayout(const QFont &font, QPaintDevice *pPaintDevice,
+                                                 const QString &strText, int iWidth, int &iHeight)
+{
+    /* Prepare variables: */
+    QFontMetrics fm(font, pPaintDevice);
+    int iLeading = fm.leading();
+
+    /* Only bold sub-strings are currently handled: */
+    QString strModifiedText(strText);
+    QRegExp boldRegExp("<b>([\\s\\S]+)</b>");
+    QList<QTextLayout::FormatRange> formatRangeList;
+    while (boldRegExp.indexIn(strModifiedText) != -1)
+    {
+        /* Prepare format: */
+        QTextLayout::FormatRange formatRange;
+        QFont font = formatRange.format.font();
+        font.setBold(true);
+        formatRange.format.setFont(font);
+        formatRange.start = boldRegExp.pos(0);
+        formatRange.length = boldRegExp.cap(1).size();
+        /* Add format range to list: */
+        formatRangeList << formatRange;
+        /* Replace sub-string: */
+        strModifiedText.replace(boldRegExp.cap(0), boldRegExp.cap(1));
+    }
+
+    /* Create layout; */
+    QTextLayout *pTextLayout = new QTextLayout(strModifiedText, font, pPaintDevice);
+    pTextLayout->setAdditionalFormats(formatRangeList);
+
+    /* Configure layout: */
+    QTextOption textOption;
+    textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
+    pTextLayout->setTextOption(textOption);
+
+    /* Build layout: */
+    pTextLayout->beginLayout();
+    while (1)
+    {
+        QTextLine line = pTextLayout->createLine();
+        if (!line.isValid())
+            break;
+
+        line.setLineWidth(iWidth);
+        iHeight += iLeading;
+        line.setPosition(QPointF(0, iHeight));
+        iHeight += line.height();
+    }
+    pTextLayout->endLayout();
+
+    /* Return layout: */
+    return pTextLayout;
+}
+
Index: /trunk/src/VBox/Frontends/VirtualBox/src/widgets/graphics/UIGraphicsTextPane.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/widgets/graphics/UIGraphicsTextPane.h	(revision 50843)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/widgets/graphics/UIGraphicsTextPane.h	(revision 50843)
@@ -0,0 +1,83 @@
+/** @file
+ * VBox Qt GUI - UIGraphicsTextPane class declaration.
+ */
+
+/*
+ * Copyright (C) 2012-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 ___UIGraphicsTextPane_h___
+#define ___UIGraphicsTextPane_h___
+
+/* GUI includes: */
+#include "QIGraphicsWidget.h"
+
+/* Typedefs: */
+typedef QPair<QString, QString> UITextTableLine;
+typedef QList<UITextTableLine> UITextTable;
+Q_DECLARE_METATYPE(UITextTable);
+
+/** QIGraphicsWidget reimplementation to draw QTextLayout content. */
+class UIGraphicsTextPane : public QIGraphicsWidget
+{
+    Q_OBJECT;
+
+public:
+
+    /** Graphics text-pane constructor. */
+    UIGraphicsTextPane(QIGraphicsWidget *pParent, QPaintDevice *pPaintDevice);
+
+    /** Returns whether contained text is empty. */
+    bool isEmpty() const { return m_text.isEmpty(); }
+    /** Returns contained text. */
+    const UITextTable& text() const { return m_text; }
+    /** Defines contained text. */
+    void setText(const UITextTable &text);
+
+private:
+
+    /** Updates minimum text width hint. */
+    void updateMinimumTextWidthHint();
+    /** Updates minimum text height hint. */
+    void updateMinimumTextHeightHint();
+    /** Returns the size-hint to constrain the content. */
+    QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
+
+    /** This event handler is delivered after the widget has been resized. */
+    void resizeEvent(QGraphicsSceneResizeEvent *pEvent);
+
+    /** Paints the contents in local coordinates. */
+    void paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption, QWidget *pWidget = 0);
+
+    /** Builds new text-layout. */
+    static QTextLayout* buildTextLayout(const QFont &font, QPaintDevice *pPaintDevice,
+                                        const QString &strText, int iWidth, int &iHeight);
+
+    /** Margin. */
+    const int m_iMargin;
+    /** Spacing. */
+    const int m_iSpacing;
+    /** Minimum text-column width: */
+    const int m_iMinimumTextColumnWidth;
+
+    /** Minimum text-width. */
+    int m_iMinimumTextWidth;
+    /** Minimum text-height. */
+    int m_iMinimumTextHeight;
+
+    /** Paint-device to scale to. */
+    QPaintDevice *m_pPaintDevice;
+
+    /** Contained text. */
+    UITextTable m_text;
+};
+
+#endif /* !___UIGraphicsTextPane_h___ */
