VirtualBox

Changeset 50868 in vbox


Ignore:
Timestamp:
Mar 25, 2014 4:03:42 PM (11 years ago)
Author:
vboxsync
Message:

FE/Qt: UIGraphicsTextPane: Anchor-hovering support.

Location:
trunk/src/VBox/Frontends/VirtualBox/src/widgets/graphics
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/graphics/UIGraphicsTextPane.cpp

    r50847 r50868  
    1717
    1818/* Qt includes: */
     19#include <QApplication>
    1920#include <QFontMetrics>
    2021#include <QTextLayout>
    2122#include <QPainter>
     23#include <QGraphicsSceneHoverEvent>
    2224
    2325/* GUI includes: */
     
    3335    , m_iMinimumTextWidth(0)
    3436    , m_iMinimumTextHeight(0)
    35 {
     37    , m_fAnchorCanBeHovered(true)
     38{
     39    /* We do support hover-events: */
     40    setAcceptHoverEvents(true);
    3641}
    3742
     
    157162            m_leftList << buildTextLayout(font(), m_pPaintDevice,
    158163                                          fRightColumnPresent ? line.first + ":" : line.first,
    159                                           iLeftColumnWidth, iLeftColumnHeight);
     164                                          iLeftColumnWidth, iLeftColumnHeight,
     165                                          m_strHoveredAnchor);
    160166            m_leftList.last()->setPosition(QPointF(iTextX, iTextY));
    161167        }
     
    167173            m_rightList << buildTextLayout(font(), m_pPaintDevice,
    168174                                           line.second,
    169                                            iRightColumnWidth, iRightColumnHeight);
     175                                           iRightColumnWidth, iRightColumnHeight,
     176                                           m_strHoveredAnchor);
    170177            m_rightList.last()->setPosition(QPointF(iTextX + iLeftColumnWidth + m_iSpacing, iTextY));
    171178        }
     
    220227    /* Update minimum size-hint: */
    221228    updateGeometry();
     229}
     230
     231void UIGraphicsTextPane::hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent)
     232{
     233    /* Redirect to common handler: */
     234    handleHoverEvent(pEvent);
     235}
     236
     237void UIGraphicsTextPane::hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent)
     238{
     239    /* Redirect to common handler: */
     240    handleHoverEvent(pEvent);
     241}
     242
     243void UIGraphicsTextPane::handleHoverEvent(QGraphicsSceneHoverEvent *pEvent)
     244{
     245    /* Ignore if anchor can't be hovered: */
     246    if (!m_fAnchorCanBeHovered)
     247        return;
     248
     249    /* Prepare variables: */
     250    QPoint mousePosition = pEvent->pos().toPoint();
     251
     252    /* If we currently have no anchor hovered: */
     253    if (m_strHoveredAnchor.isNull())
     254    {
     255        /* Search it in the left list: */
     256        m_strHoveredAnchor = searchForHoveredAnchor(m_pPaintDevice, m_leftList, mousePosition);
     257        if (!m_strHoveredAnchor.isNull())
     258            return updateHoverStuff();
     259        /* Then search it in the right one: */
     260        m_strHoveredAnchor = searchForHoveredAnchor(m_pPaintDevice, m_rightList, mousePosition);
     261        if (!m_strHoveredAnchor.isNull())
     262            return updateHoverStuff();
     263    }
     264    /* If we currently have some anchor hovered: */
     265    else
     266    {
     267        QString strHoveredAnchorName;
     268        /* Validate it through the left list: */
     269        strHoveredAnchorName = searchForHoveredAnchor(m_pPaintDevice, m_leftList, mousePosition);
     270        if (!strHoveredAnchorName.isNull())
     271        {
     272            m_strHoveredAnchor = strHoveredAnchorName;
     273            return updateHoverStuff();
     274        }
     275        /* Then validate it through the right one: */
     276        strHoveredAnchorName = searchForHoveredAnchor(m_pPaintDevice, m_rightList, mousePosition);
     277        if (!strHoveredAnchorName.isNull())
     278        {
     279            m_strHoveredAnchor = strHoveredAnchorName;
     280            return updateHoverStuff();
     281        }
     282        /* Finally clear it for good: */
     283        m_strHoveredAnchor.clear();
     284        return updateHoverStuff();
     285    }
     286}
     287
     288void UIGraphicsTextPane::updateHoverStuff()
     289{
     290    /* Update mouse-cursor: */
     291    if (m_strHoveredAnchor.isNull())
     292        unsetCursor();
     293    else
     294        setCursor(Qt::PointingHandCursor);
     295
     296    /* Update text-layout: */
     297    updateTextLayout();
     298
     299    /* Update text-pane: */
     300    update();
     301}
     302
     303void UIGraphicsTextPane::mousePressEvent(QGraphicsSceneMouseEvent*)
     304{
     305    /* Make sure some anchor hovered: */
     306    if (m_strHoveredAnchor.isNull())
     307        return;
     308
     309    /* Restrict anchor hovering: */
     310    m_fAnchorCanBeHovered = false;
     311
     312    /* Cache clicked anchor: */
     313    QString strClickedAnchor = m_strHoveredAnchor;
     314
     315    /* Clear hovered anchor: */
     316    m_strHoveredAnchor.clear();
     317    updateHoverStuff();
     318
     319    /* Notify listeners about anchor clicked: */
     320    emit sigAnchorClicked(strClickedAnchor);
     321
     322    /* Allow anchor hovering again: */
     323    m_fAnchorCanBeHovered = true;
    222324}
    223325
     
    233335/* static  */
    234336QTextLayout* UIGraphicsTextPane::buildTextLayout(const QFont &font, QPaintDevice *pPaintDevice,
    235                                                  const QString &strText, int iWidth, int &iHeight)
     337                                                 const QString &strText, int iWidth, int &iHeight,
     338                                                 const QString &strHoveredAnchor)
    236339{
    237340    /* Prepare variables: */
    238341    QFontMetrics fm(font, pPaintDevice);
    239342    int iLeading = fm.leading();
    240 
    241     /* Only bold sub-strings are currently handled: */
    242343    QString strModifiedText(strText);
     344    QList<QTextLayout::FormatRange> formatRangeList;
     345
     346    /* Handle bold sub-strings: */
    243347    QRegExp boldRegExp("<b>([\\s\\S]+)</b>");
    244     QList<QTextLayout::FormatRange> formatRangeList;
     348    boldRegExp.setMinimal(true);
    245349    while (boldRegExp.indexIn(strModifiedText) != -1)
    246350    {
     
    258362    }
    259363
     364    /* Handle anchored sub-strings: */
     365    QRegExp anchoredRegExp("<a href=([^>]+)>([^<>]+)</a>");
     366    anchoredRegExp.setMinimal(true);
     367    while (anchoredRegExp.indexIn(strModifiedText) != -1)
     368    {
     369        /* Prepare format: */
     370        QTextLayout::FormatRange formatRange;
     371        formatRange.format.setAnchor(true);
     372        formatRange.format.setAnchorHref(anchoredRegExp.cap(1));
     373        if (formatRange.format.anchorHref() == strHoveredAnchor)
     374            formatRange.format.setForeground(qApp->palette().color(QPalette::Link));
     375        formatRange.start = anchoredRegExp.pos(0);
     376        formatRange.length = anchoredRegExp.cap(2).size();
     377        /* Add format range to list: */
     378        formatRangeList << formatRange;
     379        /* Replace sub-string: */
     380        strModifiedText.replace(anchoredRegExp.cap(0), anchoredRegExp.cap(2));
     381    }
     382
    260383    /* Create layout; */
    261384    QTextLayout *pTextLayout = new QTextLayout(strModifiedText, font, pPaintDevice);
     
    286409}
    287410
     411/* static */
     412QString UIGraphicsTextPane::searchForHoveredAnchor(QPaintDevice *pPaintDevice, const QList<QTextLayout*> &list, const QPoint &mousePosition)
     413{
     414    /* Analyze passed text-layouts: */
     415    foreach (QTextLayout *pTextLayout, list)
     416    {
     417        /* Prepare variables: */
     418        QFontMetrics fm(pTextLayout->font(), pPaintDevice);
     419
     420        /* Text-layout attributes: */
     421        const QPoint layoutPosition = pTextLayout->position().toPoint();
     422        const QString strLayoutText = pTextLayout->text();
     423
     424        /* Enumerate format ranges: */
     425        foreach (const QTextLayout::FormatRange &range, pTextLayout->additionalFormats())
     426        {
     427            /* Skip unrelated formats: */
     428            if (!range.format.isAnchor())
     429                continue;
     430
     431            /* Parse 'anchor' format: */
     432            const int iStart = range.start;
     433            const int iLength = range.length;
     434            QRegion formatRegion;
     435            for (int iTextPosition = iStart; iTextPosition < iStart + iLength; ++iTextPosition)
     436            {
     437                QTextLine layoutLine = pTextLayout->lineForTextPosition(iTextPosition);
     438                QPoint linePosition = layoutLine.position().toPoint();
     439                int iSymbolX = (int)layoutLine.cursorToX(iTextPosition);
     440                QRect symbolRect = QRect(layoutPosition.x() + linePosition.x() + iSymbolX,
     441                                         layoutPosition.y() + linePosition.y(),
     442                                         fm.width(strLayoutText[iTextPosition]) + 1, fm.height());
     443                formatRegion += symbolRect;
     444            }
     445
     446            /* Is that something we looking for? */
     447            if (formatRegion.contains(mousePosition))
     448                return range.format.anchorHref();
     449        }
     450    }
     451
     452    /* Null string by default: */
     453    return QString();
     454}
     455
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/graphics/UIGraphicsTextPane.h

    r50847 r50868  
    3939    void sigGeometryChanged();
    4040
     41    /** Notifies listeners about anchor clicked. */
     42    void sigAnchorClicked(const QString &strAnchor);
     43
    4144public:
    4245
     
    6669    void resizeEvent(QGraphicsSceneResizeEvent *pEvent);
    6770
     71    /** This event handler called when mouse hovers widget. */
     72    void hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent);
     73    /** This event handler called when mouse leaves widget. */
     74    void hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent);
     75    /** Summarize two hover-event handlers above. */
     76    void handleHoverEvent(QGraphicsSceneHoverEvent *pEvent);
     77    /** Update hover stuff. */
     78    void updateHoverStuff();
     79
     80    /** This event handler called when mouse press widget. */
     81    void mousePressEvent(QGraphicsSceneMouseEvent *pEvent);
     82
    6883    /** Paints the contents in local coordinates. */
    6984    void paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption, QWidget *pWidget = 0);
     
    7186    /** Builds new text-layout. */
    7287    static QTextLayout* buildTextLayout(const QFont &font, QPaintDevice *pPaintDevice,
    73                                         const QString &strText, int iWidth, int &iHeight);
     88                                        const QString &strText, int iWidth, int &iHeight,
     89                                        const QString &strHoveredAnchor);
     90
     91    /** Search for hovered anchor in passed text-layout @a list. */
     92    static QString searchForHoveredAnchor(QPaintDevice *pPaintDevice, const QList<QTextLayout*> &list, const QPoint &mousePosition);
    7493
    7594    /** Paint-device to scale to. */
     
    98117    /** Right text-layout list. */
    99118    QList<QTextLayout*> m_rightList;
     119
     120    /** Holds whether anchor can be hovered. */
     121    bool m_fAnchorCanBeHovered;
     122    /** Holds currently hovered anchor. */
     123    QString m_strHoveredAnchor;
    100124};
    101125
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