VirtualBox

Ignore:
Timestamp:
Mar 21, 2014 2:52:02 PM (11 years ago)
Author:
vboxsync
Message:

FE/Qt: Selector UI: Details pane: Moving text-layout build stuff into separate files.

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
5 edited
2 copied

Legend:

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

    r50463 r50843  
    396396        src/widgets/graphics/UIGraphicsZoomButton.h \
    397397        src/widgets/graphics/UIGraphicsToolBar.h \
     398        src/widgets/graphics/UIGraphicsTextPane.h \
    398399        src/wizards/UIWizard.h \
    399400        src/wizards/UIWizardPage.h \
     
    680681        src/widgets/graphics/UIGraphicsZoomButton.cpp \
    681682        src/widgets/graphics/UIGraphicsToolBar.cpp \
     683        src/widgets/graphics/UIGraphicsTextPane.cpp \
    682684        src/wizards/UIWizard.cpp \
    683685        src/wizards/UIWizardPage.cpp \
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElement.cpp

    r50041 r50843  
    2323#include <QPropertyAnimation>
    2424#include <QSignalTransition>
    25 #include <QTextLayout>
    2625#include <QStyleOptionGraphicsItem>
    2726#include <QGraphicsSceneMouseEvent>
     
    3231#include "UIGDetailsModel.h"
    3332#include "UIGraphicsRotatorButton.h"
     33#include "UIGraphicsTextPane.h"
    3434#include "UIIconPool.h"
    3535#include "UIConverter.h"
     
    4242    , m_iMinimumHeaderWidth(0)
    4343    , m_iMinimumHeaderHeight(0)
    44     , m_iMinimumTextWidth(0)
    45     , m_iMinimumTextHeight(0)
     44    , m_pButton(0)
    4645    , m_fClosed(!fOpened)
    47     , m_pButton(0)
    4846    , m_iAdditionalHeight(0)
    4947    , m_fAnimationRunning(false)
     48    , m_pTextPane(0)
    5049    , m_fHovered(false)
    5150    , m_fNameHovered(false)
     
    6261    /* Prepare button: */
    6362    prepareButton();
     63    /* Prepare text-pane: */
     64    prepareTextPane();
    6465
    6566    /* Setup size-policy: */
     
    130131    /* Notify about finishing: */
    131132    emit sigToggleElementFinished();
     133}
     134
     135void UIGDetailsElement::resizeEvent(QGraphicsSceneResizeEvent*)
     136{
     137    /* Update layout: */
     138    updateLayout();
    132139}
    133140
     
    165172}
    166173
    167 void UIGDetailsElement::updateMinimumTextWidth()
    168 {
    169     /* Prepare variables: */
    170     int iSpacing = data(ElementData_Spacing).toInt();
    171     int iMinimumTextColumnWidth = data(ElementData_MinimumTextColumnWidth).toInt();
    172     QFontMetrics fm(m_textFont, model()->paintDevice());
    173 
    174     /* Search for the maximum line widths: */
    175     int iMaximumLeftLineWidth = 0;
    176     int iMaximumRightLineWidth = 0;
    177     bool fSingleColumnText = true;
    178     foreach (const UITextTableLine line, m_text)
    179     {
    180         bool fRightColumnPresent = !line.second.isEmpty();
    181         if (fRightColumnPresent)
    182             fSingleColumnText = false;
    183         QString strLeftLine = fRightColumnPresent ? line.first + ":" : line.first;
    184         QString strRightLine = line.second;
    185         iMaximumLeftLineWidth = qMax(iMaximumLeftLineWidth, fm.width(strLeftLine));
    186         iMaximumRightLineWidth = qMax(iMaximumRightLineWidth, fm.width(strRightLine));
    187     }
    188     iMaximumLeftLineWidth += 1;
    189     iMaximumRightLineWidth += 1;
    190 
    191     /* Calculate minimum-text-width: */
    192     int iMinimumTextWidth = 0;
    193     if (fSingleColumnText)
    194     {
    195         /* Take into account only left column: */
    196         int iMinimumLeftColumnWidth = qMin(iMaximumLeftLineWidth, iMinimumTextColumnWidth);
    197         iMinimumTextWidth = iMinimumLeftColumnWidth;
    198     }
    199     else
    200     {
    201         /* Take into account both columns, but wrap only right one: */
    202         int iMinimumLeftColumnWidth = iMaximumLeftLineWidth;
    203         int iMinimumRightColumnWidth = qMin(iMaximumRightLineWidth, iMinimumTextColumnWidth);
    204         iMinimumTextWidth = iMinimumLeftColumnWidth + iSpacing + iMinimumRightColumnWidth;
    205     }
    206 
    207     /* Is there something changed? */
    208     if (m_iMinimumTextWidth != iMinimumTextWidth)
    209     {
    210         /* Remember new value: */
    211         m_iMinimumTextWidth = iMinimumTextWidth;
    212         /* Recursively update size-hint: */
    213         updateGeometry();
    214     }
    215 }
    216 
    217 void UIGDetailsElement::updateMinimumTextHeight()
    218 {
    219     /* Prepare variables: */
    220     int iMargin = data(ElementData_Margin).toInt();
    221     int iSpacing = data(ElementData_Spacing).toInt();
    222     int iMinimumTextColumnWidth = data(ElementData_MinimumTextColumnWidth).toInt();
    223     int iMaximumTextWidth = (int)geometry().width() - 3 * iMargin - iSpacing;
    224     QPaintDevice *pPaintDevice = model()->paintDevice();
    225     QFontMetrics fm(m_textFont, pPaintDevice);
    226 
    227     /* Search for the maximum line widths: */
    228     int iMaximumLeftLineWidth = 0;
    229     int iMaximumRightLineWidth = 0;
    230     bool fSingleColumnText = true;
    231     foreach (const UITextTableLine line, m_text)
    232     {
    233         bool fRightColumnPresent = !line.second.isEmpty();
    234         if (fRightColumnPresent)
    235             fSingleColumnText = false;
    236         QString strFirstLine = fRightColumnPresent ? line.first + ":" : line.first;
    237         QString strSecondLine = line.second;
    238         iMaximumLeftLineWidth = qMax(iMaximumLeftLineWidth, fm.width(strFirstLine));
    239         iMaximumRightLineWidth = qMax(iMaximumRightLineWidth, fm.width(strSecondLine));
    240     }
    241     iMaximumLeftLineWidth += 1;
    242     iMaximumRightLineWidth += 1;
    243 
    244     /* Calculate column widths: */
    245     int iLeftColumnWidth = 0;
    246     int iRightColumnWidth = 0;
    247     if (fSingleColumnText)
    248     {
    249         /* Take into account only left column: */
    250         iLeftColumnWidth = qMax(iMinimumTextColumnWidth, iMaximumTextWidth);
    251     }
    252     else
    253     {
    254         /* Take into account both columns, but wrap only right one: */
    255         iLeftColumnWidth = iMaximumLeftLineWidth;
    256         iRightColumnWidth = iMaximumTextWidth - iLeftColumnWidth;
    257     }
    258 
    259     /* Calculate minimum-text-height: */
    260     int iMinimumTextHeight = 0;
    261     foreach (const UITextTableLine line, m_text)
    262     {
    263         /* First layout: */
    264         int iLeftColumnHeight = 0;
    265         if (!line.first.isEmpty())
    266         {
    267             bool fRightColumnPresent = !line.second.isEmpty();
    268             QTextLayout *pTextLayout = prepareTextLayout(m_textFont, pPaintDevice,
    269                                                          fRightColumnPresent ? line.first + ":" : line.first,
    270                                                          iLeftColumnWidth, iLeftColumnHeight);
    271             delete pTextLayout;
    272         }
    273 
    274         /* Second layout: */
    275         int iRightColumnHeight = 0;
    276         if (!line.second.isEmpty())
    277         {
    278             QTextLayout *pTextLayout = prepareTextLayout(m_textFont, pPaintDevice, line.second,
    279                                                          iRightColumnWidth, iRightColumnHeight);
    280             delete pTextLayout;
    281         }
    282 
    283         /* Append summary text height: */
    284         iMinimumTextHeight += qMax(iLeftColumnHeight, iRightColumnHeight);
    285     }
    286 
    287     /* Is there something changed? */
    288     if (m_iMinimumTextHeight != iMinimumTextHeight)
    289     {
    290         /* Remember new value: */
    291         m_iMinimumTextHeight = iMinimumTextHeight;
    292         /* Recursively update size-hint: */
    293         updateGeometry();
    294     }
    295 }
    296 
    297174void UIGDetailsElement::setIcon(const QIcon &icon)
    298175{
     
    318195}
    319196
     197const UITextTable& UIGDetailsElement::text() const
     198{
     199    /* Retrieve text from text-pane: */
     200    return m_pTextPane->text();
     201}
     202
    320203void UIGDetailsElement::setText(const UITextTable &text)
    321204{
    322     /* Clear first: */
    323     m_text.clear();
    324     /* For each the line of the passed table: */
    325     foreach (const UITextTableLine &line, text)
    326     {
    327         /* Get lines: */
    328         QString strLeftLine = line.first;
    329         QString strRightLine = line.second;
    330         /* If 2nd line is empty: */
    331         if (strRightLine.isEmpty())
    332         {
    333             /* Parse the 1st one: */
    334             QStringList subLines = strLeftLine.split(QRegExp("\\n"));
    335             foreach (const QString &strSubLine, subLines)
    336                 m_text << UITextTableLine(strSubLine, QString());
    337         }
    338         else
    339             m_text << UITextTableLine(strLeftLine, strRightLine);
    340     }
    341 
    342     /* Update linked values: */
    343     updateMinimumTextWidth();
    344     updateMinimumTextHeight();
     205    /* Pass text to text-pane: */
     206    m_pTextPane->setText(text);
    345207}
    346208
     
    357219
    358220    /* Maximum width: */
    359     iMinimumWidthHint = qMax(m_iMinimumHeaderWidth, m_iMinimumTextWidth);
     221    iMinimumWidthHint = qMax(m_iMinimumHeaderWidth, (int)m_pTextPane->minimumSizeHint().width());
    360222
    361223    /* And 4 margins: 2 left and 2 right: */
     
    382244    {
    383245        /* Add text height: */
    384         if (!m_text.isEmpty())
    385             iMinimumHeightHint += 2 * iMargin + m_iMinimumTextHeight;
     246        if (!m_pTextPane->isEmpty())
     247            iMinimumHeightHint += 2 * iMargin + (int)m_pTextPane->minimumSizeHint().height();
    386248    }
    387249
     
    404266    QSize size = geometry().size().toSize();
    405267    int iMargin = data(ElementData_Margin).toInt();
     268
     269    /* Layout button: */
    406270    int iButtonWidth = m_buttonSize.width();
    407271    int iButtonHeight = m_buttonSize.height();
    408 
    409     /* Layout button: */
    410272    int iButtonX = size.width() - 2 * iMargin - iButtonWidth;
    411273    int iButtonY = iButtonHeight == m_iMinimumHeaderHeight ? iMargin :
    412274                   iMargin + (m_iMinimumHeaderHeight - iButtonHeight) / 2;
    413275    m_pButton->setPos(iButtonX, iButtonY);
     276
     277    /* If closed: */
     278    if (closed())
     279    {
     280        /* Hide text-pane if still visible: */
     281        if (m_pTextPane->isVisible())
     282            m_pTextPane->hide();
     283    }
     284    /* If opened: */
     285    else
     286    {
     287        /* Layout text-pane: */
     288        int iTextPaneX = 2 * iMargin;
     289        int iTextPaneY = iMargin + m_iMinimumHeaderHeight + 2 * iMargin;
     290        m_pTextPane->setPos(iTextPaneX, iTextPaneY);
     291        m_pTextPane->resize(size.width() - 4 * iMargin,
     292                            size.height() - 4 * iMargin - m_iMinimumHeaderHeight);
     293        /* Show text-pane if still invisible and animation finished: */
     294        if (!m_pTextPane->isVisible() && !isAnimationRunning())
     295            m_pTextPane->show();
     296    }
    414297}
    415298
     
    504387}
    505388
     389void UIGDetailsElement::prepareTextPane()
     390{
     391    /* Create text-pane: */
     392    m_pTextPane = new UIGraphicsTextPane(this, model()->paintDevice());
     393}
     394
    506395void UIGDetailsElement::paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption, QWidget*)
    507396{
     
    540429    QColor buttonTextColor = pal.color(QPalette::Active, QPalette::ButtonText);
    541430    QColor linkTextColor = pal.color(QPalette::Active, QPalette::Link);
    542     QColor baseTextColor = pal.color(QPalette::Active, QPalette::Text);
    543431
    544432    /* Paint pixmap: */
    545     int iMachinePixmapX = 2 * iMargin;
    546     int iMachinePixmapY = iPixmapHeight == iMaximumHeight ?
     433    int iElementPixmapX = 2 * iMargin;
     434    int iElementPixmapY = iPixmapHeight == iMaximumHeight ?
    547435                          iMargin : iMargin + (iMaximumHeight - iPixmapHeight) / 2;
    548436    paintPixmap(/* Painter: */
    549437                pPainter,
    550438                /* Rectangle to paint in: */
    551                 QRect(QPoint(iMachinePixmapX, iMachinePixmapY), m_pixmapSize),
     439                QRect(QPoint(iElementPixmapX, iElementPixmapY), m_pixmapSize),
    552440                /* Pixmap to paint: */
    553441                m_pixmap);
    554442
    555443    /* Paint name: */
    556     int iMachineNameX = iMachinePixmapX +
     444    int iMachineNameX = iElementPixmapX +
    557445                        m_pixmapSize.width() +
    558446                        iSpacing;
     
    571459              /* Name hovered? */
    572460              m_fNameHovered ? linkTextColor : buttonTextColor);
    573 
    574     /* Paint text: */
    575     if (!m_fClosed && !m_text.isEmpty() && !m_fAnimationRunning)
    576     {
    577         /* Prepare painter: */
    578         pPainter->save();
    579         pPainter->setPen(baseTextColor);
    580 
    581         /* Prepare variables: */
    582         int iMinimumTextColumnWidth = data(ElementData_MinimumTextColumnWidth).toInt();
    583         int iMaximumTextWidth = geometry().width() - 3 * iMargin - iSpacing;
    584         QPaintDevice *pPaintDevice = model()->paintDevice();
    585         QFontMetrics fm(m_textFont, pPaintDevice);
    586 
    587         /* Search for the maximum line widths: */
    588         int iMaximumLeftLineWidth = 0;
    589         int iMaximumRightLineWidth = 0;
    590         bool fSingleColumnText = true;
    591         foreach (const UITextTableLine line, m_text)
    592         {
    593             bool fRightColumnPresent = !line.second.isEmpty();
    594             if (fRightColumnPresent)
    595                 fSingleColumnText = false;
    596             QString strFirstLine = fRightColumnPresent ? line.first + ":" : line.first;
    597             QString strSecondLine = line.second;
    598             iMaximumLeftLineWidth = qMax(iMaximumLeftLineWidth, fm.width(strFirstLine));
    599             iMaximumRightLineWidth = qMax(iMaximumRightLineWidth, fm.width(strSecondLine));
    600         }
    601         iMaximumLeftLineWidth += 1;
    602         iMaximumRightLineWidth += 1;
    603 
    604         /* Calculate column widths: */
    605         int iLeftColumnWidth = 0;
    606         int iRightColumnWidth = 0;
    607         if (fSingleColumnText)
    608         {
    609             /* Take into account only left column: */
    610             iLeftColumnWidth = qMax(iMinimumTextColumnWidth, iMaximumTextWidth);
    611         }
    612         else
    613         {
    614             /* Take into account both columns, but wrap only right one: */
    615             iLeftColumnWidth = iMaximumLeftLineWidth;
    616             iRightColumnWidth = iMaximumTextWidth - iLeftColumnWidth;
    617         }
    618 
    619         /* Where to paint? */
    620         int iMachineTextX = iMachinePixmapX;
    621         int iMachineTextY = iMargin + m_iMinimumHeaderHeight + 2 * iMargin;
    622 
    623         /* For each the line: */
    624         foreach (const UITextTableLine line, m_text)
    625         {
    626             /* First layout: */
    627             int iLeftColumnHeight = 0;
    628             if (!line.first.isEmpty())
    629             {
    630                 bool fRightColumnPresent = !line.second.isEmpty();
    631                 QTextLayout *pTextLayout = prepareTextLayout(m_textFont, pPaintDevice,
    632                                                              fRightColumnPresent ? line.first + ":" : line.first,
    633                                                              iLeftColumnWidth, iLeftColumnHeight);
    634                 pTextLayout->draw(pPainter, QPointF(iMachineTextX, iMachineTextY));
    635                 delete pTextLayout;
    636             }
    637 
    638             /* Second layout: */
    639             int iRightColumnHeight = 0;
    640             if (!line.second.isEmpty())
    641             {
    642                 QTextLayout *pTextLayout = prepareTextLayout(m_textFont, pPaintDevice,
    643                                                              line.second, iRightColumnWidth, iRightColumnHeight);
    644                 pTextLayout->draw(pPainter, QPointF(iMachineTextX + iLeftColumnWidth + iSpacing, iMachineTextY));
    645                 delete pTextLayout;
    646             }
    647 
    648             /* Indent Y: */
    649             iMachineTextY += qMax(iLeftColumnHeight, iRightColumnHeight);
    650         }
    651 
    652         /* Restore painter: */
    653         pPainter->restore();
    654     }
    655461}
    656462
     
    782588    int iSpacing = data(ElementData_Spacing).toInt();
    783589    int iNameHeight = m_nameSize.height();
    784     int iMachineNameX = 2 * iMargin + m_pixmapSize.width() + iSpacing;
    785     int iMachineNameY = iNameHeight == m_iMinimumHeaderHeight ?
     590    int iElementNameX = 2 * iMargin + m_pixmapSize.width() + iSpacing;
     591    int iElementNameY = iNameHeight == m_iMinimumHeaderHeight ?
    786592                        iMargin : iMargin + (m_iMinimumHeaderHeight - iNameHeight) / 2;
    787593
    788594    /* Simulate hyperlink hovering: */
    789595    QPoint point = pEvent->pos().toPoint();
    790     bool fNameHovered = QRect(QPoint(iMachineNameX, iMachineNameY), m_nameSize).contains(point);
     596    bool fNameHovered = QRect(QPoint(iElementNameX, iElementNameY), m_nameSize).contains(point);
    791597    if (m_pSet->elementNameHoverable() && m_fNameHovered != fNameHovered)
    792598    {
     
    803609        unsetCursor();
    804610    update();
    805 }
    806 
    807 /* static  */
    808 QTextLayout* UIGDetailsElement::prepareTextLayout(const QFont &font, QPaintDevice *pPaintDevice,
    809                                                   const QString &strText, int iWidth, int &iHeight)
    810 {
    811     /* Prepare variables: */
    812     QFontMetrics fm(font, pPaintDevice);
    813     int iLeading = fm.leading();
    814 
    815     /* Only bold sub-strings are currently handled: */
    816     QString strModifiedText(strText);
    817     QRegExp boldRegExp("<b>([\\s\\S]+)</b>");
    818     QList<QTextLayout::FormatRange> formatRangeList;
    819     while (boldRegExp.indexIn(strModifiedText) != -1)
    820     {
    821         /* Prepare format: */
    822         QTextLayout::FormatRange formatRange;
    823         QFont font = formatRange.format.font();
    824         font.setBold(true);
    825         formatRange.format.setFont(font);
    826         formatRange.start = boldRegExp.pos(0);
    827         formatRange.length = boldRegExp.cap(1).size();
    828         /* Add format range to list: */
    829         formatRangeList << formatRange;
    830         /* Replace sub-string: */
    831         strModifiedText.replace(boldRegExp.cap(0), boldRegExp.cap(1));
    832     }
    833 
    834     /* Create layout; */
    835     QTextLayout *pTextLayout = new QTextLayout(strModifiedText, font, pPaintDevice);
    836     pTextLayout->setAdditionalFormats(formatRangeList);
    837 
    838     /* Configure layout: */
    839     QTextOption textOption;
    840     textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
    841     pTextLayout->setTextOption(textOption);
    842 
    843     /* Build layout: */
    844     pTextLayout->beginLayout();
    845     while (1)
    846     {
    847         QTextLine line = pTextLayout->createLine();
    848         if (!line.isValid())
    849             break;
    850 
    851         line.setLineWidth(iWidth);
    852         iHeight += iLeading;
    853         line.setPosition(QPointF(0, iHeight));
    854         iHeight += line.height();
    855     }
    856     pTextLayout->endLayout();
    857 
    858     /* Return layout: */
    859     return pTextLayout;
    860611}
    861612
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElement.h

    r50041 r50843  
    3131class CMachine;
    3232class UIGraphicsRotatorButton;
     33class UIGraphicsTextPane;
    3334class QTextLayout;
    3435class QStateMachine;
     
    3839typedef QPair<QString, QString> UITextTableLine;
    3940typedef QList<UITextTableLine> UITextTable;
    40 Q_DECLARE_METATYPE(UITextTable);
    4141
    4242/* Details element
     
    104104    };
    105105
     106    /** This event handler is delivered after the widget has been resized. */
     107    void resizeEvent(QGraphicsSceneResizeEvent *pEvent);
     108
    106109    /* Data provider: */
    107110    QVariant data(int iKey) const;
     
    110113    void updateMinimumHeaderWidth();
    111114    void updateMinimumHeaderHeight();
    112     void updateMinimumTextWidth();
    113     void updateMinimumTextHeight();
    114115
    115116    /* API: Icon stuff: */
     
    120121
    121122    /* API: Text stuff: */
    122     UITextTable text() const { return m_text; }
     123    const UITextTable& text() const;
    123124    void setText(const UITextTable &text);
    124125
     
    156157    void prepareElement();
    157158    void prepareButton();
     159    void prepareTextPane();
    158160
    159161    /* Helpers: Paint stuff: */
     
    174176    void updateNameHoverLink();
    175177
    176     /* Helper: Layout stuff: */
    177     static QTextLayout* prepareTextLayout(const QFont &font, QPaintDevice *pPaintDevice,
    178                                           const QString &strText, int iWidth, int &iHeight);
    179 
    180178    /* Helper: Animation stuff: */
    181179    void updateAnimationParameters();
     
    186184    QPixmap m_pixmap;
    187185    QString m_strName;
    188     UITextTable m_text;
    189186    int m_iCornerRadius;
    190187    QFont m_nameFont;
     
    195192    int m_iMinimumHeaderWidth;
    196193    int m_iMinimumHeaderHeight;
    197     int m_iMinimumTextWidth;
    198     int m_iMinimumTextHeight;
    199 
    200     /* Variables: Toggle stuff: */
     194
     195    /* Variables: Toggle-button stuff: */
     196    UIGraphicsRotatorButton *m_pButton;
    201197    bool m_fClosed;
    202     UIGraphicsRotatorButton *m_pButton;
    203198    int m_iAdditionalHeight;
    204199    bool m_fAnimationRunning;
     200
     201    /* Variables: Text-pane stuff: */
     202    UIGraphicsTextPane *m_pTextPane;
    205203
    206204    /* Variables: Hover stuff: */
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsElements.cpp

    r50041 r50843  
    2929#include "UIIconPool.h"
    3030#include "UIConverter.h"
     31#include "UIGraphicsTextPane.h"
    3132
    3233/* COM includes: */
  • trunk/src/VBox/Frontends/VirtualBox/src/selector/graphics/details/UIGDetailsSet.cpp

    r50041 r50843  
    515515                    /* Resize element to required width: */
    516516                    pElement->resize(iWidth, pElement->geometry().height());
    517                     /* Update minimum-height-hint: */
    518                     pElement->updateMinimumTextHeight();
    519517                }
    520518                /* Acquire required height: */
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/graphics/UIGraphicsTextPane.cpp

    r50824 r50843  
    11/* $Id$ */
    22/** @file
    3  *
    4  * VBox frontends: Qt GUI ("VirtualBox"):
    5  * UIGDetailsElement class implementation
     3 * VBox Qt GUI - UIGraphicsTextPane and UITask class implementation.
    64 */
    75
    86/*
    9  * Copyright (C) 2012 Oracle Corporation
     7 * Copyright (C) 2012-2014 Oracle Corporation
    108 *
    119 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1917
    2018/* Qt includes: */
    21 #include <QGraphicsView>
    22 #include <QStateMachine>
    23 #include <QPropertyAnimation>
    24 #include <QSignalTransition>
     19#include <QFontMetrics>
    2520#include <QTextLayout>
    26 #include <QStyleOptionGraphicsItem>
    27 #include <QGraphicsSceneMouseEvent>
     21#include <QPainter>
    2822
    2923/* GUI includes: */
    30 #include "UIGDetailsElement.h"
    31 #include "UIGDetailsSet.h"
    32 #include "UIGDetailsModel.h"
    33 #include "UIGraphicsRotatorButton.h"
    34 #include "UIIconPool.h"
    35 #include "UIConverter.h"
    36 
    37 UIGDetailsElement::UIGDetailsElement(UIGDetailsSet *pParent, DetailsElementType type, bool fOpened)
    38     : UIGDetailsItem(pParent)
    39     , m_pSet(pParent)
    40     , m_type(type)
    41     , m_iCornerRadius(10)
    42     , m_iMinimumHeaderWidth(0)
    43     , m_iMinimumHeaderHeight(0)
     24#include "UIGraphicsTextPane.h"
     25
     26UIGraphicsTextPane::UIGraphicsTextPane(QIGraphicsWidget *pParent, QPaintDevice *pPaintDevice)
     27    : QIGraphicsWidget(pParent)
     28    , m_pPaintDevice(pPaintDevice)
     29    , m_iMargin(0)
     30    , m_iSpacing(10)
     31    , m_iMinimumTextColumnWidth(100)
    4432    , m_iMinimumTextWidth(0)
    4533    , m_iMinimumTextHeight(0)
    46     , m_fClosed(!fOpened)
    47     , m_pButton(0)
    48     , m_iAdditionalHeight(0)
    49     , m_fAnimationRunning(false)
    50     , m_fHovered(false)
    51     , m_fNameHovered(false)
    52     , m_pHighlightMachine(0)
    53     , m_pForwardAnimation(0)
    54     , m_pBackwardAnimation(0)
    55     , m_iAnimationDuration(400)
    56     , m_iDefaultDarkness(100)
    57     , m_iHighlightDarkness(90)
    58     , m_iAnimationDarkness(m_iDefaultDarkness)
    59 {
    60     /* Prepare element: */
    61     prepareElement();
    62     /* Prepare button: */
    63     prepareButton();
    64 
    65     /* Setup size-policy: */
    66     setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
    67 
    68     /* Add item to the parent: */
    69     AssertMsg(parentItem(), ("No parent set for details element!"));
    70     parentItem()->addItem(this);
    71 }
    72 
    73 UIGDetailsElement::~UIGDetailsElement()
    74 {
    75     /* Remove item from the parent: */
    76     AssertMsg(parentItem(), ("No parent set for details element!"));
    77     parentItem()->removeItem(this);
    78 }
    79 
    80 void UIGDetailsElement::close(bool fAnimated /* = true */)
    81 {
    82     m_pButton->setToggled(false, fAnimated);
    83 }
    84 
    85 void UIGDetailsElement::open(bool fAnimated /* = true */)
    86 {
    87     m_pButton->setToggled(true, fAnimated);
    88 }
    89 
    90 void UIGDetailsElement::updateAppearance()
    91 {
    92     /* Reset name hover state: */
    93     m_fNameHovered = false;
    94     updateNameHoverLink();
    95 }
    96 
    97 void UIGDetailsElement::markAnimationFinished()
    98 {
    99     /* Mark animation as non-running: */
    100     m_fAnimationRunning = false;
    101 
    102     /* Recursively update size-hint: */
    103     updateGeometry();
    104     /* Repaint: */
    105     update();
    106 }
    107 
    108 void UIGDetailsElement::sltToggleButtonClicked()
    109 {
    110     emit sigToggleElement(m_type, closed());
    111 }
    112 
    113 void UIGDetailsElement::sltElementToggleStart()
    114 {
    115     /* Mark animation running: */
    116     m_fAnimationRunning = true;
    117 
    118     /* Setup animation: */
    119     updateAnimationParameters();
    120 
    121     /* Invert toggle-state: */
    122     m_fClosed = !m_fClosed;
    123 }
    124 
    125 void UIGDetailsElement::sltElementToggleFinish(bool fToggled)
    126 {
    127     /* Update toggle-state: */
    128     m_fClosed = !fToggled;
    129 
    130     /* Notify about finishing: */
    131     emit sigToggleElementFinished();
    132 }
    133 
    134 QVariant UIGDetailsElement::data(int iKey) const
    135 {
    136     /* Provide other members with required data: */
    137     switch (iKey)
    138     {
    139         /* Hints: */
    140         case ElementData_Margin: return 5;
    141         case ElementData_Spacing: return 10;
    142         case ElementData_MinimumTextColumnWidth: return 100;
    143         /* Default: */
    144         default: break;
    145     }
    146     return QVariant();
    147 }
    148 
    149 void UIGDetailsElement::updateMinimumHeaderWidth()
     34{
     35}
     36
     37void UIGraphicsTextPane::setText(const UITextTable &text)
     38{
     39    /* Clear text: */
     40    m_text.clear();
     41
     42    /* For each the line of the passed table: */
     43    foreach (const UITextTableLine &line, text)
     44    {
     45        /* Lines: */
     46        QString strLeftLine = line.first;
     47        QString strRightLine = line.second;
     48
     49        /* If 2nd line is NOT empty: */
     50        if (!strRightLine.isEmpty())
     51        {
     52            /* Take both lines 'as is': */
     53            m_text << UITextTableLine(strLeftLine, strRightLine);
     54        }
     55        /* If 2nd line is empty: */
     56        else
     57        {
     58            /* Parse the 1st one to sub-lines: */
     59            QStringList subLines = strLeftLine.split(QRegExp("\\n"));
     60            foreach (const QString &strSubLine, subLines)
     61                m_text << UITextTableLine(strSubLine, QString());
     62        }
     63    }
     64
     65    /* Update minimum text size-hint: */
     66    updateMinimumTextWidthHint();
     67    updateMinimumTextHeightHint();
     68}
     69
     70void UIGraphicsTextPane::updateMinimumTextWidthHint()
    15071{
    15172    /* Prepare variables: */
    152     int iSpacing = data(ElementData_Spacing).toInt();
    153 
    154     /* Update minimum-header-width: */
    155     m_iMinimumHeaderWidth = m_pixmapSize.width() +
    156                             iSpacing + m_nameSize.width() +
    157                             iSpacing + m_buttonSize.width();
    158 }
    159 
    160 void UIGDetailsElement::updateMinimumHeaderHeight()
    161 {
    162     /* Update minimum-header-height: */
    163     m_iMinimumHeaderHeight = qMax(m_pixmapSize.height(), m_nameSize.height());
    164     m_iMinimumHeaderHeight = qMax(m_iMinimumHeaderHeight, m_buttonSize.height());
    165 }
    166 
    167 void UIGDetailsElement::updateMinimumTextWidth()
    168 {
    169     /* Prepare variables: */
    170     int iSpacing = data(ElementData_Spacing).toInt();
    171     int iMinimumTextColumnWidth = data(ElementData_MinimumTextColumnWidth).toInt();
    172     QFontMetrics fm(m_textFont, model()->paintDevice());
     73    QFontMetrics fm(font(), m_pPaintDevice);
    17374
    17475    /* Search for the maximum line widths: */
     
    17677    int iMaximumRightLineWidth = 0;
    17778    bool fSingleColumnText = true;
    178     foreach (const UITextTableLine line, m_text)
     79    foreach (const UITextTableLine &line, m_text)
    17980    {
    18081        bool fRightColumnPresent = !line.second.isEmpty();
     
    19495    {
    19596        /* Take into account only left column: */
    196         int iMinimumLeftColumnWidth = qMin(iMaximumLeftLineWidth, iMinimumTextColumnWidth);
     97        int iMinimumLeftColumnWidth = qMin(iMaximumLeftLineWidth, m_iMinimumTextColumnWidth);
    19798        iMinimumTextWidth = iMinimumLeftColumnWidth;
    19899    }
     
    201102        /* Take into account both columns, but wrap only right one: */
    202103        int iMinimumLeftColumnWidth = iMaximumLeftLineWidth;
    203         int iMinimumRightColumnWidth = qMin(iMaximumRightLineWidth, iMinimumTextColumnWidth);
    204         iMinimumTextWidth = iMinimumLeftColumnWidth + iSpacing + iMinimumRightColumnWidth;
    205     }
    206 
    207     /* Is there something changed? */
    208     if (m_iMinimumTextWidth != iMinimumTextWidth)
    209     {
    210         /* Remember new value: */
    211         m_iMinimumTextWidth = iMinimumTextWidth;
    212         /* Recursively update size-hint: */
    213         updateGeometry();
    214     }
    215 }
    216 
    217 void UIGDetailsElement::updateMinimumTextHeight()
     104        int iMinimumRightColumnWidth = qMin(iMaximumRightLineWidth, m_iMinimumTextColumnWidth);
     105        iMinimumTextWidth = iMinimumLeftColumnWidth + m_iSpacing + iMinimumRightColumnWidth;
     106    }
     107
     108    /* Make sure something changed: */
     109    if (m_iMinimumTextWidth == iMinimumTextWidth)
     110        return;
     111
     112    /* Remember new value: */
     113    m_iMinimumTextWidth = iMinimumTextWidth;
     114
     115    /* Notify layout if any: */
     116    updateGeometry();
     117}
     118
     119void UIGraphicsTextPane::updateMinimumTextHeightHint()
    218120{
    219121    /* Prepare variables: */
    220     int iMargin = data(ElementData_Margin).toInt();
    221     int iSpacing = data(ElementData_Spacing).toInt();
    222     int iMinimumTextColumnWidth = data(ElementData_MinimumTextColumnWidth).toInt();
    223     int iMaximumTextWidth = (int)geometry().width() - 3 * iMargin - iSpacing;
    224     QPaintDevice *pPaintDevice = model()->paintDevice();
    225     QFontMetrics fm(m_textFont, pPaintDevice);
     122    int iMaximumTextWidth = (int)size().width() - 2 * m_iMargin - m_iSpacing;
     123    QFontMetrics fm(font(), m_pPaintDevice);
    226124
    227125    /* Search for the maximum line widths: */
     
    229127    int iMaximumRightLineWidth = 0;
    230128    bool fSingleColumnText = true;
    231     foreach (const UITextTableLine line, m_text)
     129    foreach (const UITextTableLine &line, m_text)
    232130    {
    233131        bool fRightColumnPresent = !line.second.isEmpty();
     
    248146    {
    249147        /* Take into account only left column: */
    250         iLeftColumnWidth = qMax(iMinimumTextColumnWidth, iMaximumTextWidth);
     148        iLeftColumnWidth = qMax(m_iMinimumTextColumnWidth, iMaximumTextWidth);
    251149    }
    252150    else
     
    266164        {
    267165            bool fRightColumnPresent = !line.second.isEmpty();
    268             QTextLayout *pTextLayout = prepareTextLayout(m_textFont, pPaintDevice,
    269                                                          fRightColumnPresent ? line.first + ":" : line.first,
    270                                                          iLeftColumnWidth, iLeftColumnHeight);
     166            QTextLayout *pTextLayout = buildTextLayout(font(), m_pPaintDevice,
     167                                                       fRightColumnPresent ? line.first + ":" : line.first,
     168                                                       iLeftColumnWidth, iLeftColumnHeight);
    271169            delete pTextLayout;
    272170        }
     
    276174        if (!line.second.isEmpty())
    277175        {
    278             QTextLayout *pTextLayout = prepareTextLayout(m_textFont, pPaintDevice, line.second,
    279                                                          iRightColumnWidth, iRightColumnHeight);
     176            QTextLayout *pTextLayout = buildTextLayout(font(), m_pPaintDevice, line.second,
     177                                                       iRightColumnWidth, iRightColumnHeight);
    280178            delete pTextLayout;
    281179        }
     
    285183    }
    286184
    287     /* Is there something changed? */
    288     if (m_iMinimumTextHeight != iMinimumTextHeight)
    289     {
    290         /* Remember new value: */
    291         m_iMinimumTextHeight = iMinimumTextHeight;
    292         /* Recursively update size-hint: */
    293         updateGeometry();
    294     }
    295 }
    296 
    297 void UIGDetailsElement::setIcon(const QIcon &icon)
    298 {
    299     /* Cache icon: */
    300     m_pixmapSize = icon.isNull() ? QSize(0, 0) : icon.availableSizes().first();
    301     m_pixmap = icon.pixmap(m_pixmapSize);
    302 
    303     /* Update linked values: */
    304     updateMinimumHeaderWidth();
    305     updateMinimumHeaderHeight();
    306 }
    307 
    308 void UIGDetailsElement::setName(const QString &strName)
    309 {
    310     /* Cache name: */
    311     m_strName = strName;
    312     QFontMetrics fm(m_nameFont, model()->paintDevice());
    313     m_nameSize = QSize(fm.width(m_strName), fm.height());
    314 
    315     /* Update linked values: */
    316     updateMinimumHeaderWidth();
    317     updateMinimumHeaderHeight();
    318 }
    319 
    320 void UIGDetailsElement::setText(const UITextTable &text)
    321 {
    322     /* Clear first: */
    323     m_text.clear();
    324     /* For each the line of the passed table: */
    325     foreach (const UITextTableLine &line, text)
    326     {
    327         /* Get lines: */
    328         QString strLeftLine = line.first;
    329         QString strRightLine = line.second;
    330         /* If 2nd line is empty: */
    331         if (strRightLine.isEmpty())
    332         {
    333             /* Parse the 1st one: */
    334             QStringList subLines = strLeftLine.split(QRegExp("\\n"));
    335             foreach (const QString &strSubLine, subLines)
    336                 m_text << UITextTableLine(strSubLine, QString());
    337         }
    338         else
    339             m_text << UITextTableLine(strLeftLine, strRightLine);
    340     }
    341 
    342     /* Update linked values: */
    343     updateMinimumTextWidth();
    344     updateMinimumTextHeight();
    345 }
    346 
    347 const CMachine& UIGDetailsElement::machine()
    348 {
    349     return m_pSet->machine();
    350 }
    351 
    352 int UIGDetailsElement::minimumWidthHint() const
     185    /* Make sure something changed: */
     186    if (m_iMinimumTextHeight == iMinimumTextHeight)
     187        return;
     188
     189    /* Remember new value: */
     190    m_iMinimumTextHeight = iMinimumTextHeight;
     191
     192    /* Notify layout if any: */
     193    updateGeometry();
     194}
     195
     196QSizeF UIGraphicsTextPane::sizeHint(Qt::SizeHint which, const QSizeF &constraint /* = QSizeF() */) const
     197{
     198    /* Calculate minimum size-hint: */
     199    if (which == Qt::MinimumSize)
     200    {
     201        int iWidth = 2 * m_iMargin + m_iMinimumTextWidth;
     202        int iHeight = 2 * m_iMargin + m_iMinimumTextHeight;
     203        return QSize(iWidth, iHeight);
     204    }
     205    /* Call to base-class: */
     206    return QIGraphicsWidget::sizeHint(which, constraint);
     207}
     208
     209void UIGraphicsTextPane::resizeEvent(QGraphicsSceneResizeEvent*)
     210{
     211    /* Update minimum text height-hint: */
     212    updateMinimumTextHeightHint();
     213}
     214
     215void UIGraphicsTextPane::paint(QPainter *pPainter, const QStyleOptionGraphicsItem*, QWidget*)
    353216{
    354217    /* Prepare variables: */
    355     int iMargin = data(ElementData_Margin).toInt();
    356     int iMinimumWidthHint = 0;
    357 
    358     /* Maximum width: */
    359     iMinimumWidthHint = qMax(m_iMinimumHeaderWidth, m_iMinimumTextWidth);
    360 
    361     /* And 4 margins: 2 left and 2 right: */
    362     iMinimumWidthHint += 4 * iMargin;
    363 
    364     /* Return result: */
    365     return iMinimumWidthHint;
    366 }
    367 
    368 int UIGDetailsElement::minimumHeightHint(bool fClosed) const
    369 {
    370     /* Prepare variables: */
    371     int iMargin = data(ElementData_Margin).toInt();
    372     int iMinimumHeightHint = 0;
    373 
    374     /* Two margins: */
    375     iMinimumHeightHint += 2 * iMargin;
    376 
    377     /* Header height: */
    378     iMinimumHeightHint += m_iMinimumHeaderHeight;
    379 
    380     /* Element is opened? */
    381     if (!fClosed)
    382     {
    383         /* Add text height: */
    384         if (!m_text.isEmpty())
    385             iMinimumHeightHint += 2 * iMargin + m_iMinimumTextHeight;
    386     }
    387 
    388     /* Additional height during animation: */
    389     if (m_fAnimationRunning)
    390         iMinimumHeightHint += m_iAdditionalHeight;
    391 
    392     /* Return value: */
    393     return iMinimumHeightHint;
    394 }
    395 
    396 int UIGDetailsElement::minimumHeightHint() const
    397 {
    398     return minimumHeightHint(m_fClosed);
    399 }
    400 
    401 void UIGDetailsElement::updateLayout()
    402 {
    403     /* Prepare variables: */
    404     QSize size = geometry().size().toSize();
    405     int iMargin = data(ElementData_Margin).toInt();
    406     int iButtonWidth = m_buttonSize.width();
    407     int iButtonHeight = m_buttonSize.height();
    408 
    409     /* Layout button: */
    410     int iButtonX = size.width() - 2 * iMargin - iButtonWidth;
    411     int iButtonY = iButtonHeight == m_iMinimumHeaderHeight ? iMargin :
    412                    iMargin + (m_iMinimumHeaderHeight - iButtonHeight) / 2;
    413     m_pButton->setPos(iButtonX, iButtonY);
    414 }
    415 
    416 void UIGDetailsElement::setAdditionalHeight(int iAdditionalHeight)
    417 {
    418     /* Cache new value: */
    419     m_iAdditionalHeight = iAdditionalHeight;
    420     /* Update layout: */
    421     updateLayout();
    422     /* Repaint: */
    423     update();
    424 }
    425 
    426 void UIGDetailsElement::addItem(UIGDetailsItem*)
    427 {
    428     AssertMsgFailed(("Details element do NOT support children!"));
    429 }
    430 
    431 void UIGDetailsElement::removeItem(UIGDetailsItem*)
    432 {
    433     AssertMsgFailed(("Details element do NOT support children!"));
    434 }
    435 
    436 QList<UIGDetailsItem*> UIGDetailsElement::items(UIGDetailsItemType) const
    437 {
    438     AssertMsgFailed(("Details element do NOT support children!"));
    439     return QList<UIGDetailsItem*>();
    440 }
    441 
    442 bool UIGDetailsElement::hasItems(UIGDetailsItemType) const
    443 {
    444     AssertMsgFailed(("Details element do NOT support children!"));
    445     return false;
    446 }
    447 
    448 void UIGDetailsElement::clearItems(UIGDetailsItemType)
    449 {
    450     AssertMsgFailed(("Details element do NOT support children!"));
    451 }
    452 
    453 void UIGDetailsElement::prepareElement()
    454 {
    455     /* Initialization: */
    456     m_nameFont = font();
    457     m_nameFont.setWeight(QFont::Bold);
    458     m_textFont = font();
    459 
    460     /* Create highlight machine: */
    461     m_pHighlightMachine = new QStateMachine(this);
    462     /* Create 'default' state: */
    463     QState *pStateDefault = new QState(m_pHighlightMachine);
    464     /* Create 'highlighted' state: */
    465     QState *pStateHighlighted = new QState(m_pHighlightMachine);
    466 
    467     /* Forward animation: */
    468     m_pForwardAnimation = new QPropertyAnimation(this, "animationDarkness", this);
    469     m_pForwardAnimation->setDuration(m_iAnimationDuration);
    470     m_pForwardAnimation->setStartValue(m_iDefaultDarkness);
    471     m_pForwardAnimation->setEndValue(m_iHighlightDarkness);
    472 
    473     /* Backward animation: */
    474     m_pBackwardAnimation = new QPropertyAnimation(this, "animationDarkness", this);
    475     m_pBackwardAnimation->setDuration(m_iAnimationDuration);
    476     m_pBackwardAnimation->setStartValue(m_iHighlightDarkness);
    477     m_pBackwardAnimation->setEndValue(m_iDefaultDarkness);
    478 
    479     /* Add state transitions: */
    480     QSignalTransition *pDefaultToHighlighted = pStateDefault->addTransition(this, SIGNAL(sigHoverEnter()), pStateHighlighted);
    481     pDefaultToHighlighted->addAnimation(m_pForwardAnimation);
    482     QSignalTransition *pHighlightedToDefault = pStateHighlighted->addTransition(this, SIGNAL(sigHoverLeave()), pStateDefault);
    483     pHighlightedToDefault->addAnimation(m_pBackwardAnimation);
    484 
    485     /* Initial state is 'default': */
    486     m_pHighlightMachine->setInitialState(pStateDefault);
    487     /* Start state-machine: */
    488     m_pHighlightMachine->start();
    489 
    490     connect(this, SIGNAL(sigToggleElement(DetailsElementType, bool)), model(), SLOT(sltToggleElements(DetailsElementType, bool)));
    491     connect(this, SIGNAL(sigLinkClicked(const QString&, const QString&, const QString&)),
    492             model(), SIGNAL(sigLinkClicked(const QString&, const QString&, const QString&)));
    493 }
    494 
    495 void UIGDetailsElement::prepareButton()
    496 {
    497     /* Setup toggle-button: */
    498     m_pButton = new UIGraphicsRotatorButton(this, "additionalHeight", !m_fClosed, true /* reflected */);
    499     m_pButton->setAutoHandleButtonClick(false);
    500     connect(m_pButton, SIGNAL(sigButtonClicked()), this, SLOT(sltToggleButtonClicked()));
    501     connect(m_pButton, SIGNAL(sigRotationStart()), this, SLOT(sltElementToggleStart()));
    502     connect(m_pButton, SIGNAL(sigRotationFinish(bool)), this, SLOT(sltElementToggleFinish(bool)));
    503     m_buttonSize = m_pButton->minimumSizeHint().toSize();
    504 }
    505 
    506 void UIGDetailsElement::paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption, QWidget*)
    507 {
    508     /* Update button visibility: */
    509     updateButtonVisibility();
    510 
    511     /* Configure painter shape: */
    512     configurePainterShape(pPainter, pOption, m_iCornerRadius);
    513 
    514     /* Paint decorations: */
    515     paintDecorations(pPainter, pOption);
    516 
    517     /* Paint element info: */
    518     paintElementInfo(pPainter, pOption);
    519 }
    520 
    521 void UIGDetailsElement::paintDecorations(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption)
    522 {
    523     /* Paint background: */
    524     paintBackground(pPainter, pOption);
    525 }
    526 
    527 void UIGDetailsElement::paintElementInfo(QPainter *pPainter, const QStyleOptionGraphicsItem*)
    528 {
    529     /* Initialize some necessary variables: */
    530     int iMargin = data(ElementData_Margin).toInt();
    531     int iSpacing = data(ElementData_Spacing).toInt();
    532 
    533     /* Calculate attributes: */
    534     int iPixmapHeight = m_pixmapSize.height();
    535     int iNameHeight = m_nameSize.height();
    536     int iMaximumHeight = qMax(iPixmapHeight, iNameHeight);
    537 
    538     /* Prepare color: */
    539     QPalette pal = palette();
    540     QColor buttonTextColor = pal.color(QPalette::Active, QPalette::ButtonText);
    541     QColor linkTextColor = pal.color(QPalette::Active, QPalette::Link);
    542     QColor baseTextColor = pal.color(QPalette::Active, QPalette::Text);
    543 
    544     /* Paint pixmap: */
    545     int iMachinePixmapX = 2 * iMargin;
    546     int iMachinePixmapY = iPixmapHeight == iMaximumHeight ?
    547                           iMargin : iMargin + (iMaximumHeight - iPixmapHeight) / 2;
    548     paintPixmap(/* Painter: */
    549                 pPainter,
    550                 /* Rectangle to paint in: */
    551                 QRect(QPoint(iMachinePixmapX, iMachinePixmapY), m_pixmapSize),
    552                 /* Pixmap to paint: */
    553                 m_pixmap);
    554 
    555     /* Paint name: */
    556     int iMachineNameX = iMachinePixmapX +
    557                         m_pixmapSize.width() +
    558                         iSpacing;
    559     int iMachineNameY = iNameHeight == iMaximumHeight ?
    560                         iMargin : iMargin + (iMaximumHeight - iNameHeight) / 2;
    561     paintText(/* Painter: */
    562               pPainter,
    563               /* Rectangle to paint in: */
    564               QPoint(iMachineNameX, iMachineNameY),
    565               /* Font to paint text: */
    566               m_nameFont,
    567               /* Paint device: */
    568               model()->paintDevice(),
    569               /* Text to paint: */
    570               m_strName,
    571               /* Name hovered? */
    572               m_fNameHovered ? linkTextColor : buttonTextColor);
    573 
    574     /* Paint text: */
    575     if (!m_fClosed && !m_text.isEmpty() && !m_fAnimationRunning)
    576     {
    577         /* Prepare painter: */
    578         pPainter->save();
    579         pPainter->setPen(baseTextColor);
    580 
    581         /* Prepare variables: */
    582         int iMinimumTextColumnWidth = data(ElementData_MinimumTextColumnWidth).toInt();
    583         int iMaximumTextWidth = geometry().width() - 3 * iMargin - iSpacing;
    584         QPaintDevice *pPaintDevice = model()->paintDevice();
    585         QFontMetrics fm(m_textFont, pPaintDevice);
    586 
    587         /* Search for the maximum line widths: */
    588         int iMaximumLeftLineWidth = 0;
    589         int iMaximumRightLineWidth = 0;
    590         bool fSingleColumnText = true;
    591         foreach (const UITextTableLine line, m_text)
     218    int iMaximumTextWidth = (int)size().width() - 2 * m_iMargin - m_iSpacing;
     219    QFontMetrics fm(font(), m_pPaintDevice);
     220
     221    /* Where to paint? */
     222    int iTextX = m_iMargin;
     223    int iTextY = m_iMargin;
     224
     225    /* Search for the maximum line widths: */
     226    int iMaximumLeftLineWidth = 0;
     227    int iMaximumRightLineWidth = 0;
     228    bool fSingleColumnText = true;
     229    foreach (const UITextTableLine line, m_text)
     230    {
     231        bool fRightColumnPresent = !line.second.isEmpty();
     232        if (fRightColumnPresent)
     233            fSingleColumnText = false;
     234        QString strFirstLine = fRightColumnPresent ? line.first + ":" : line.first;
     235        QString strSecondLine = line.second;
     236        iMaximumLeftLineWidth = qMax(iMaximumLeftLineWidth, fm.width(strFirstLine));
     237        iMaximumRightLineWidth = qMax(iMaximumRightLineWidth, fm.width(strSecondLine));
     238    }
     239    iMaximumLeftLineWidth += 1;
     240    iMaximumRightLineWidth += 1;
     241
     242    /* Calculate column widths: */
     243    int iLeftColumnWidth = 0;
     244    int iRightColumnWidth = 0;
     245    if (fSingleColumnText)
     246    {
     247        /* Take into account only left column: */
     248        iLeftColumnWidth = qMax(m_iMinimumTextColumnWidth, iMaximumTextWidth);
     249    }
     250    else
     251    {
     252        /* Take into account both columns, but wrap only right one: */
     253        iLeftColumnWidth = iMaximumLeftLineWidth;
     254        iRightColumnWidth = iMaximumTextWidth - iLeftColumnWidth;
     255    }
     256
     257    /* For each the line: */
     258    foreach (const UITextTableLine line, m_text)
     259    {
     260        /* First layout: */
     261        int iLeftColumnHeight = 0;
     262        if (!line.first.isEmpty())
    592263        {
    593264            bool fRightColumnPresent = !line.second.isEmpty();
    594             if (fRightColumnPresent)
    595                 fSingleColumnText = false;
    596             QString strFirstLine = fRightColumnPresent ? line.first + ":" : line.first;
    597             QString strSecondLine = line.second;
    598             iMaximumLeftLineWidth = qMax(iMaximumLeftLineWidth, fm.width(strFirstLine));
    599             iMaximumRightLineWidth = qMax(iMaximumRightLineWidth, fm.width(strSecondLine));
    600         }
    601         iMaximumLeftLineWidth += 1;
    602         iMaximumRightLineWidth += 1;
    603 
    604         /* Calculate column widths: */
    605         int iLeftColumnWidth = 0;
    606         int iRightColumnWidth = 0;
    607         if (fSingleColumnText)
    608         {
    609             /* Take into account only left column: */
    610             iLeftColumnWidth = qMax(iMinimumTextColumnWidth, iMaximumTextWidth);
    611         }
    612         else
    613         {
    614             /* Take into account both columns, but wrap only right one: */
    615             iLeftColumnWidth = iMaximumLeftLineWidth;
    616             iRightColumnWidth = iMaximumTextWidth - iLeftColumnWidth;
    617         }
    618 
    619         /* Where to paint? */
    620         int iMachineTextX = iMachinePixmapX;
    621         int iMachineTextY = iMargin + m_iMinimumHeaderHeight + 2 * iMargin;
    622 
    623         /* For each the line: */
    624         foreach (const UITextTableLine line, m_text)
    625         {
    626             /* First layout: */
    627             int iLeftColumnHeight = 0;
    628             if (!line.first.isEmpty())
    629             {
    630                 bool fRightColumnPresent = !line.second.isEmpty();
    631                 QTextLayout *pTextLayout = prepareTextLayout(m_textFont, pPaintDevice,
    632                                                              fRightColumnPresent ? line.first + ":" : line.first,
    633                                                              iLeftColumnWidth, iLeftColumnHeight);
    634                 pTextLayout->draw(pPainter, QPointF(iMachineTextX, iMachineTextY));
    635                 delete pTextLayout;
    636             }
    637 
    638             /* Second layout: */
    639             int iRightColumnHeight = 0;
    640             if (!line.second.isEmpty())
    641             {
    642                 QTextLayout *pTextLayout = prepareTextLayout(m_textFont, pPaintDevice,
    643                                                              line.second, iRightColumnWidth, iRightColumnHeight);
    644                 pTextLayout->draw(pPainter, QPointF(iMachineTextX + iLeftColumnWidth + iSpacing, iMachineTextY));
    645                 delete pTextLayout;
    646             }
    647 
    648             /* Indent Y: */
    649             iMachineTextY += qMax(iLeftColumnHeight, iRightColumnHeight);
    650         }
    651 
    652         /* Restore painter: */
    653         pPainter->restore();
    654     }
    655 }
    656 
    657 void UIGDetailsElement::paintBackground(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption)
    658 {
    659     /* Save painter: */
    660     pPainter->save();
    661 
    662     /* Prepare variables: */
    663     int iMargin = data(ElementData_Margin).toInt();
    664     int iHeaderHeight = 2 * iMargin + m_iMinimumHeaderHeight;
    665     QRect optionRect = pOption->rect;
    666     QRect fullRect = !m_fAnimationRunning ? optionRect :
    667                      QRect(optionRect.topLeft(), QSize(optionRect.width(), iHeaderHeight + m_iAdditionalHeight));
    668     int iFullHeight = fullRect.height();
    669 
    670     /* Prepare color: */
    671     QPalette pal = palette();
    672     QColor headerColor = pal.color(QPalette::Active, QPalette::Button);
    673     QColor strokeColor = pal.color(QPalette::Active, QPalette::Mid);
    674     QColor bodyColor = pal.color(QPalette::Active, QPalette::Base);
    675 
    676     /* Add clipping: */
    677     QPainterPath path;
    678     path.moveTo(m_iCornerRadius, 0);
    679     path.arcTo(QRectF(path.currentPosition(), QSizeF(2 * m_iCornerRadius, 2 * m_iCornerRadius)).translated(-m_iCornerRadius, 0), 90, 90);
    680     path.lineTo(path.currentPosition().x(), iFullHeight - m_iCornerRadius);
    681     path.arcTo(QRectF(path.currentPosition(), QSizeF(2 * m_iCornerRadius, 2 * m_iCornerRadius)).translated(0, -m_iCornerRadius), 180, 90);
    682     path.lineTo(fullRect.width() - m_iCornerRadius, path.currentPosition().y());
    683     path.arcTo(QRectF(path.currentPosition(), QSizeF(2 * m_iCornerRadius, 2 * m_iCornerRadius)).translated(-m_iCornerRadius, -2 * m_iCornerRadius), 270, 90);
    684     path.lineTo(path.currentPosition().x(), m_iCornerRadius);
    685     path.arcTo(QRectF(path.currentPosition(), QSizeF(2 * m_iCornerRadius, 2 * m_iCornerRadius)).translated(-2 * m_iCornerRadius, -m_iCornerRadius), 0, 90);
    686     path.closeSubpath();
    687     pPainter->setClipPath(path);
    688 
    689     /* Calculate top rectangle: */
    690     QRect tRect = fullRect;
    691     tRect.setBottom(tRect.top() + iHeaderHeight);
    692     /* Calculate bottom rectangle: */
    693     QRect bRect = fullRect;
    694     bRect.setTop(tRect.bottom());
    695 
    696     /* Prepare top gradient: */
    697     QLinearGradient tGradient(tRect.bottomLeft(), tRect.topLeft());
    698     tGradient.setColorAt(0, headerColor.darker(110));
    699     tGradient.setColorAt(1, headerColor.darker(animationDarkness()));
    700 
    701     /* Paint all the stuff: */
    702     pPainter->fillRect(tRect, tGradient);
    703     pPainter->fillRect(bRect, bodyColor);
    704 
    705     /* Stroke path: */
    706     pPainter->setClipping(false);
    707     pPainter->strokePath(path, strokeColor);
    708 
    709     /* Restore painter: */
    710     pPainter->restore();
    711 }
    712 
    713 void UIGDetailsElement::hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent)
    714 {
    715     /* Update hover state: */
    716     if (!m_fHovered)
    717     {
    718         m_fHovered = true;
    719         emit sigHoverEnter();
    720     }
    721 
    722     /* Update name-hover state: */
    723     handleHoverEvent(pEvent);
    724 }
    725 
    726 void UIGDetailsElement::hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent)
    727 {
    728     /* Update hover state: */
    729     if (m_fHovered)
    730     {
    731         m_fHovered = false;
    732         emit sigHoverLeave();
    733     }
    734 
    735     /* Update name-hover state: */
    736     handleHoverEvent(pEvent);
    737 }
    738 
    739 void UIGDetailsElement::mousePressEvent(QGraphicsSceneMouseEvent *pEvent)
    740 {
    741     /* Only for hovered header: */
    742     if (!m_fNameHovered)
    743         return;
    744 
    745     /* Process link click: */
    746     pEvent->accept();
    747     QString strCategory;
    748     if (m_type >= DetailsElementType_General &&
    749         m_type <= DetailsElementType_SF)
    750         strCategory = QString("#%1").arg(gpConverter->toInternalString(m_type));
    751     else if (m_type == DetailsElementType_Description)
    752         strCategory = QString("#%1%%mTeDescription").arg(gpConverter->toInternalString(m_type));
    753     emit sigLinkClicked(strCategory, QString(), machine().GetId());
    754 }
    755 
    756 void UIGDetailsElement::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *pEvent)
    757 {
    758     /* Only for left-button: */
    759     if (pEvent->button() != Qt::LeftButton)
    760         return;
    761 
    762     /* Process left-button double-click: */
    763     emit sigToggleElement(m_type, closed());
    764 }
    765 
    766 void UIGDetailsElement::updateButtonVisibility()
    767 {
    768     if (m_fHovered && !m_pButton->isVisible())
    769         m_pButton->show();
    770     else if (!m_fHovered && m_pButton->isVisible())
    771         m_pButton->hide();
    772 }
    773 
    774 void UIGDetailsElement::handleHoverEvent(QGraphicsSceneHoverEvent *pEvent)
    775 {
    776     /* Not for 'preview' element type: */
    777     if (m_type == DetailsElementType_Preview)
    778         return;
    779 
    780     /* Prepare variables: */
    781     int iMargin = data(ElementData_Margin).toInt();
    782     int iSpacing = data(ElementData_Spacing).toInt();
    783     int iNameHeight = m_nameSize.height();
    784     int iMachineNameX = 2 * iMargin + m_pixmapSize.width() + iSpacing;
    785     int iMachineNameY = iNameHeight == m_iMinimumHeaderHeight ?
    786                         iMargin : iMargin + (m_iMinimumHeaderHeight - iNameHeight) / 2;
    787 
    788     /* Simulate hyperlink hovering: */
    789     QPoint point = pEvent->pos().toPoint();
    790     bool fNameHovered = QRect(QPoint(iMachineNameX, iMachineNameY), m_nameSize).contains(point);
    791     if (m_pSet->elementNameHoverable() && m_fNameHovered != fNameHovered)
    792     {
    793         m_fNameHovered = fNameHovered;
    794         updateNameHoverLink();
    795     }
    796 }
    797 
    798 void UIGDetailsElement::updateNameHoverLink()
    799 {
    800     if (m_fNameHovered)
    801         setCursor(Qt::PointingHandCursor);
    802     else
    803         unsetCursor();
    804     update();
     265            QTextLayout *pTextLayout = buildTextLayout(font(), m_pPaintDevice,
     266                                                       fRightColumnPresent ? line.first + ":" : line.first,
     267                                                       iLeftColumnWidth, iLeftColumnHeight);
     268            pTextLayout->draw(pPainter, QPointF(iTextX, iTextY));
     269            delete pTextLayout;
     270        }
     271
     272        /* Second layout: */
     273        int iRightColumnHeight = 0;
     274        if (!line.second.isEmpty())
     275        {
     276            QTextLayout *pTextLayout = buildTextLayout(font(), m_pPaintDevice,
     277                                                       line.second, iRightColumnWidth, iRightColumnHeight);
     278            pTextLayout->draw(pPainter, QPointF(iTextX + iLeftColumnWidth + m_iSpacing, iTextY));
     279            delete pTextLayout;
     280        }
     281
     282        /* Indent Y: */
     283        iTextY += qMax(iLeftColumnHeight, iRightColumnHeight);
     284    }
    805285}
    806286
    807287/* static  */
    808 QTextLayout* UIGDetailsElement::prepareTextLayout(const QFont &font, QPaintDevice *pPaintDevice,
    809                                                   const QString &strText, int iWidth, int &iHeight)
     288QTextLayout* UIGraphicsTextPane::buildTextLayout(const QFont &font, QPaintDevice *pPaintDevice,
     289                                                 const QString &strText, int iWidth, int &iHeight)
    810290{
    811291    /* Prepare variables: */
     
    860340}
    861341
    862 void UIGDetailsElement::updateAnimationParameters()
    863 {
    864     /* Recalculate animation parameters: */
    865     int iOpenedHeight = minimumHeightHint(false);
    866     int iClosedHeight = minimumHeightHint(true);
    867     int iAdditionalHeight = iOpenedHeight - iClosedHeight;
    868     if (m_fClosed)
    869         m_iAdditionalHeight = 0;
    870     else
    871         m_iAdditionalHeight = iAdditionalHeight;
    872     m_pButton->setAnimationRange(0, iAdditionalHeight);
    873 }
    874 
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/graphics/UIGraphicsTextPane.h

    r50824 r50843  
    11/** @file
    2  *
    3  * VBox frontends: Qt GUI ("VirtualBox"):
    4  * UIGDetailsElement class declaration
     2 * VBox Qt GUI - UIGraphicsTextPane class declaration.
    53 */
    64
    75/*
    8  * Copyright (C) 2012 Oracle Corporation
     6 * Copyright (C) 2012-2014 Oracle Corporation
    97 *
    108 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1715 */
    1816
    19 #ifndef __UIGDetailsElement_h__
    20 #define __UIGDetailsElement_h__
    21 
    22 /* Qt includes: */
    23 #include <QIcon>
     17#ifndef ___UIGraphicsTextPane_h___
     18#define ___UIGraphicsTextPane_h___
    2419
    2520/* GUI includes: */
    26 #include "UIGDetailsItem.h"
    27 #include "UIDefs.h"
    28 
    29 /* Forward declarations: */
    30 class UIGDetailsSet;
    31 class CMachine;
    32 class UIGraphicsRotatorButton;
    33 class QTextLayout;
    34 class QStateMachine;
    35 class QPropertyAnimation;
     21#include "QIGraphicsWidget.h"
    3622
    3723/* Typedefs: */
     
    4026Q_DECLARE_METATYPE(UITextTable);
    4127
    42 /* Details element
    43  * for graphics details model/view architecture: */
    44 class UIGDetailsElement : public UIGDetailsItem
     28/** QIGraphicsWidget reimplementation to draw QTextLayout content. */
     29class UIGraphicsTextPane : public QIGraphicsWidget
    4530{
    4631    Q_OBJECT;
    47     Q_PROPERTY(int animationDarkness READ animationDarkness WRITE setAnimationDarkness);
    48     Q_PROPERTY(int additionalHeight READ additionalHeight WRITE setAdditionalHeight);
    49 
    50 signals:
    51 
    52     /* Notifiers: Hover stuff: */
    53     void sigHoverEnter();
    54     void sigHoverLeave();
    55 
    56     /* Notifiers: Toggle stuff: */
    57     void sigToggleElement(DetailsElementType type, bool fToggled);
    58     void sigToggleElementFinished();
    59 
    60     /* Notifier: Link-click stuff: */
    61     void sigLinkClicked(const QString &strCategory, const QString &strControl, const QString &strId);
    6232
    6333public:
    6434
    65     /* Graphics-item type: */
    66     enum { Type = UIGDetailsItemType_Element };
    67     int type() const { return Type; }
     35    /** Graphics text-pane constructor. */
     36    UIGraphicsTextPane(QIGraphicsWidget *pParent, QPaintDevice *pPaintDevice);
    6837
    69     /* Constructor/destructor: */
    70     UIGDetailsElement(UIGDetailsSet *pParent, DetailsElementType type, bool fOpened);
    71     ~UIGDetailsElement();
    72 
    73     /* API: Element type: */
    74     DetailsElementType elementType() const { return m_type; }
    75 
    76     /* API: Open/close stuff: */
    77     bool closed() const { return m_fClosed; }
    78     bool opened() const { return !m_fClosed; }
    79     void close(bool fAnimated = true);
    80     void open(bool fAnimated = true);
    81 
    82     /* API: Update stuff: */
    83     virtual void updateAppearance();
    84 
    85     /* API: Animation stuff: */
    86     void markAnimationFinished();
    87 
    88 protected slots:
    89 
    90     /* Handlers: Toggle stuff: */
    91     void sltToggleButtonClicked();
    92     void sltElementToggleStart();
    93     void sltElementToggleFinish(bool fToggled);
    94 
    95 protected:
    96 
    97     /* Data enumerator: */
    98     enum ElementData
    99     {
    100         /* Hints: */
    101         ElementData_Margin,
    102         ElementData_Spacing,
    103         ElementData_MinimumTextColumnWidth
    104     };
    105 
    106     /* Data provider: */
    107     QVariant data(int iKey) const;
    108 
    109     /* Helpers: Update stuff: */
    110     void updateMinimumHeaderWidth();
    111     void updateMinimumHeaderHeight();
    112     void updateMinimumTextWidth();
    113     void updateMinimumTextHeight();
    114 
    115     /* API: Icon stuff: */
    116     void setIcon(const QIcon &icon);
    117 
    118     /* API: Name stuff: */
    119     void setName(const QString &strName);
    120 
    121     /* API: Text stuff: */
    122     UITextTable text() const { return m_text; }
     38    /** Returns whether contained text is empty. */
     39    bool isEmpty() const { return m_text.isEmpty(); }
     40    /** Returns contained text. */
     41    const UITextTable& text() const { return m_text; }
     42    /** Defines contained text. */
    12343    void setText(const UITextTable &text);
    124 
    125     /* API: Machine stuff: */
    126     const CMachine& machine();
    127 
    128     /* Helpers: Layout stuff: */
    129     int minimumHeaderWidth() const { return m_iMinimumHeaderWidth; }
    130     int minimumHeaderHeight() const { return m_iMinimumHeaderHeight; }
    131     int minimumWidthHint() const;
    132     virtual int minimumHeightHint(bool fClosed) const;
    133     int minimumHeightHint() const;
    134     void updateLayout();
    135 
    136     /* Helpers: Hover stuff: */
    137     int animationDarkness() const { return m_iAnimationDarkness; }
    138     void setAnimationDarkness(int iAnimationDarkness) { m_iAnimationDarkness = iAnimationDarkness; update(); }
    139 
    140     /* Helpers: Animation stuff: */
    141     void setAdditionalHeight(int iAdditionalHeight);
    142     int additionalHeight() const { return m_iAdditionalHeight; }
    143     UIGraphicsRotatorButton* button() const { return m_pButton; }
    144     bool isAnimationRunning() const { return m_fAnimationRunning; }
    14544
    14645private:
    14746
    148     /* API: Children stuff: */
    149     void addItem(UIGDetailsItem *pItem);
    150     void removeItem(UIGDetailsItem *pItem);
    151     QList<UIGDetailsItem*> items(UIGDetailsItemType type) const;
    152     bool hasItems(UIGDetailsItemType type) const;
    153     void clearItems(UIGDetailsItemType type);
     47    /** Updates minimum text width hint. */
     48    void updateMinimumTextWidthHint();
     49    /** Updates minimum text height hint. */
     50    void updateMinimumTextHeightHint();
     51    /** Returns the size-hint to constrain the content. */
     52    QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const;
    15453
    155     /* Helpers: Prepare stuff: */
    156     void prepareElement();
    157     void prepareButton();
     54    /** This event handler is delivered after the widget has been resized. */
     55    void resizeEvent(QGraphicsSceneResizeEvent *pEvent);
    15856
    159     /* Helpers: Paint stuff: */
     57    /** Paints the contents in local coordinates. */
    16058    void paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption, QWidget *pWidget = 0);
    161     void paintDecorations(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption);
    162     void paintElementInfo(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption);
    163     void paintBackground(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption);
    16459
    165     /* Handlers: Mouse stuff: */
    166     void hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent);
    167     void hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent);
    168     void mousePressEvent(QGraphicsSceneMouseEvent *pEvent);
    169     void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *pEvent);
     60    /** Builds new text-layout. */
     61    static QTextLayout* buildTextLayout(const QFont &font, QPaintDevice *pPaintDevice,
     62                                        const QString &strText, int iWidth, int &iHeight);
    17063
    171     /* Helpers: Mouse stuff: */
    172     void updateButtonVisibility();
    173     void handleHoverEvent(QGraphicsSceneHoverEvent *pEvent);
    174     void updateNameHoverLink();
     64    /** Margin. */
     65    const int m_iMargin;
     66    /** Spacing. */
     67    const int m_iSpacing;
     68    /** Minimum text-column width: */
     69    const int m_iMinimumTextColumnWidth;
    17570
    176     /* Helper: Layout stuff: */
    177     static QTextLayout* prepareTextLayout(const QFont &font, QPaintDevice *pPaintDevice,
    178                                           const QString &strText, int iWidth, int &iHeight);
    179 
    180     /* Helper: Animation stuff: */
    181     void updateAnimationParameters();
    182 
    183     /* Variables: */
    184     UIGDetailsSet *m_pSet;
    185     DetailsElementType m_type;
    186     QPixmap m_pixmap;
    187     QString m_strName;
    188     UITextTable m_text;
    189     int m_iCornerRadius;
    190     QFont m_nameFont;
    191     QFont m_textFont;
    192     QSize m_pixmapSize;
    193     QSize m_nameSize;
    194     QSize m_buttonSize;
    195     int m_iMinimumHeaderWidth;
    196     int m_iMinimumHeaderHeight;
     71    /** Minimum text-width. */
    19772    int m_iMinimumTextWidth;
     73    /** Minimum text-height. */
    19874    int m_iMinimumTextHeight;
    19975
    200     /* Variables: Toggle stuff: */
    201     bool m_fClosed;
    202     UIGraphicsRotatorButton *m_pButton;
    203     int m_iAdditionalHeight;
    204     bool m_fAnimationRunning;
     76    /** Paint-device to scale to. */
     77    QPaintDevice *m_pPaintDevice;
    20578
    206     /* Variables: Hover stuff: */
    207     bool m_fHovered;
    208     bool m_fNameHovered;
    209     QStateMachine *m_pHighlightMachine;
    210     QPropertyAnimation *m_pForwardAnimation;
    211     QPropertyAnimation *m_pBackwardAnimation;
    212     int m_iAnimationDuration;
    213     int m_iDefaultDarkness;
    214     int m_iHighlightDarkness;
    215     int m_iAnimationDarkness;
    216 
    217     /* Friends: */
    218     friend class UIGDetailsSet;
     79    /** Contained text. */
     80    UITextTable m_text;
    21981};
    22082
    221 #endif /* __UIGDetailsElement_h__ */
    222 
     83#endif /* !___UIGraphicsTextPane_h___ */
Note: See TracChangeset for help on using the changeset viewer.

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