Changeset 50868 in vbox
- Timestamp:
- Mar 25, 2014 4:03:42 PM (11 years ago)
- 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 17 17 18 18 /* Qt includes: */ 19 #include <QApplication> 19 20 #include <QFontMetrics> 20 21 #include <QTextLayout> 21 22 #include <QPainter> 23 #include <QGraphicsSceneHoverEvent> 22 24 23 25 /* GUI includes: */ … … 33 35 , m_iMinimumTextWidth(0) 34 36 , m_iMinimumTextHeight(0) 35 { 37 , m_fAnchorCanBeHovered(true) 38 { 39 /* We do support hover-events: */ 40 setAcceptHoverEvents(true); 36 41 } 37 42 … … 157 162 m_leftList << buildTextLayout(font(), m_pPaintDevice, 158 163 fRightColumnPresent ? line.first + ":" : line.first, 159 iLeftColumnWidth, iLeftColumnHeight); 164 iLeftColumnWidth, iLeftColumnHeight, 165 m_strHoveredAnchor); 160 166 m_leftList.last()->setPosition(QPointF(iTextX, iTextY)); 161 167 } … … 167 173 m_rightList << buildTextLayout(font(), m_pPaintDevice, 168 174 line.second, 169 iRightColumnWidth, iRightColumnHeight); 175 iRightColumnWidth, iRightColumnHeight, 176 m_strHoveredAnchor); 170 177 m_rightList.last()->setPosition(QPointF(iTextX + iLeftColumnWidth + m_iSpacing, iTextY)); 171 178 } … … 220 227 /* Update minimum size-hint: */ 221 228 updateGeometry(); 229 } 230 231 void UIGraphicsTextPane::hoverLeaveEvent(QGraphicsSceneHoverEvent *pEvent) 232 { 233 /* Redirect to common handler: */ 234 handleHoverEvent(pEvent); 235 } 236 237 void UIGraphicsTextPane::hoverMoveEvent(QGraphicsSceneHoverEvent *pEvent) 238 { 239 /* Redirect to common handler: */ 240 handleHoverEvent(pEvent); 241 } 242 243 void 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 288 void 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 303 void 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; 222 324 } 223 325 … … 233 335 /* static */ 234 336 QTextLayout* 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) 236 339 { 237 340 /* Prepare variables: */ 238 341 QFontMetrics fm(font, pPaintDevice); 239 342 int iLeading = fm.leading(); 240 241 /* Only bold sub-strings are currently handled: */242 343 QString strModifiedText(strText); 344 QList<QTextLayout::FormatRange> formatRangeList; 345 346 /* Handle bold sub-strings: */ 243 347 QRegExp boldRegExp("<b>([\\s\\S]+)</b>"); 244 QList<QTextLayout::FormatRange> formatRangeList;348 boldRegExp.setMinimal(true); 245 349 while (boldRegExp.indexIn(strModifiedText) != -1) 246 350 { … … 258 362 } 259 363 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 260 383 /* Create layout; */ 261 384 QTextLayout *pTextLayout = new QTextLayout(strModifiedText, font, pPaintDevice); … … 286 409 } 287 410 411 /* static */ 412 QString 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 39 39 void sigGeometryChanged(); 40 40 41 /** Notifies listeners about anchor clicked. */ 42 void sigAnchorClicked(const QString &strAnchor); 43 41 44 public: 42 45 … … 66 69 void resizeEvent(QGraphicsSceneResizeEvent *pEvent); 67 70 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 68 83 /** Paints the contents in local coordinates. */ 69 84 void paint(QPainter *pPainter, const QStyleOptionGraphicsItem *pOption, QWidget *pWidget = 0); … … 71 86 /** Builds new text-layout. */ 72 87 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); 74 93 75 94 /** Paint-device to scale to. */ … … 98 117 /** Right text-layout list. */ 99 118 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; 100 124 }; 101 125
Note:
See TracChangeset
for help on using the changeset viewer.