void QConsolePrivate::updateConsoleSize (bool sync)
{
  QFontMetrics fm (m_consoleView->font());
  QSize winSize = m_consoleView->size ();

  m_charSize.rwidth () = fm.averageCharWidth();
  m_charSize.rheight () = fm.lineSpacing ();

  m_consoleRect.setWidth (int(double(winSize.width ()) / double(fm.averageCharWidth())));
  m_consoleRect.setHeight (int(double(winSize.height ()) / double(fm.lineSpacing ())));

  m_bufferSize.rwidth () = m_consoleRect.width ();
  m_bufferSize.rheight () = qMax (m_bufferSize.height (),
                                  m_consoleRect.height ());

  m_consoleRect.moveLeft (0);
  if (m_consoleRect.bottom () >= m_bufferSize.height ())
    m_consoleRect.moveTop (m_bufferSize.height () - m_consoleRect.height ());

  log ("Console resized:\n");
  log ("  widget size: %d x %d\n", winSize.width (), winSize.height ());
  log ("  buffer size: %d x %d\n", m_bufferSize.width (),
       m_bufferSize.height ());
  log ("  window: (%d, %d) -> (%d, %d) [%d x %d]\n",
       m_consoleRect.left (), m_consoleRect.top (),
       m_consoleRect.right (), m_consoleRect.bottom (),
       m_consoleRect.width (), m_consoleRect.height ());

  if (sync)
    syncConsoleParameters ();

  updateScrollBar ();
}
QSize FastSizeHintItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    int lineCount=1;
    int nPos=20;
    if (index.column()!=TMDBModel::Filepath && index.column()!=TMDBModel::TransationStatus)
    {
        QString text=index.data().toString();
        nPos=text.indexOf('\n');
        if (nPos==-1)
            nPos=text.size();
        else
            lineCount+=text.count('\n');
    }
    static QFontMetrics metrics(option.font);
    return QSize(metrics.averageCharWidth()*nPos, metrics.height()*lineCount);
}
QSize FastSizeHintItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
    int lineCount=1;
    int nPos=20;
    int column=qMax(index.column(),0);
    if (!singleLineColumns.at(column))
    {
        QString text=index.data().toString();
        nPos=text.indexOf('\n');
        if (nPos==-1)
            nPos=text.size();
        else
            lineCount+=text.count('\n');
    }
    static QFontMetrics metrics(option.font);
    return QSize(metrics.averageCharWidth()*nPos, metrics.height()*lineCount);
}
Exemple #4
0
// set proper grid size for the QListView based on current view mode, icon size, and font size.
void FolderView::updateGridSize() {
  if(mode == DetailedListMode || !view)
    return;
  FolderViewListView* listView = static_cast<FolderViewListView*>(view);
  QSize icon = iconSize(mode); // size of the icon
  QFontMetrics fm = fontMetrics(); // size of current font
  QSize grid; // the final grid size
  switch(mode) {
    case IconMode:
    case ThumbnailMode: {
      // NOTE by PCMan about finding the optimal text label size:
      // The average filename length on my root filesystem is roughly 18-20 chars.
      // So, a reasonable size for the text label is about 10 chars each line since string of this length
      // can be shown in two lines. If you consider word wrap, then the result is around 10 chars per word.
      // In average, 10 char per line should be enough to display a "word" in the filename without breaking.
      // The values can be estimated with this command:
      // > find / | xargs  basename -a | sed -e s'/[_-]/ /g' | wc -mcw
      // However, this average only applies to English. For some Asian characters, such as Chinese chars,
      // each char actually takes doubled space. To be safe, we use 13 chars per line x average char width
      // to get a nearly optimal width for the text label. As most of the filenames have less than 40 chars
      // 13 chars x 3 lines should be enough to show the full filenames for most files.
      int textWidth = fm.averageCharWidth() * 13;
      int textHeight = fm.lineSpacing() * 3;
      grid.setWidth(qMax(icon.width(), textWidth) + 4); // a margin of 2 px for selection rects
      grid.setHeight(icon.height() + textHeight + 4); // a margin of 2 px for selection rects
      break;
    }
    default:
      ; // do not use grid size
  }
  if(mode == IconMode || mode == ThumbnailMode)
    listView->setGridSize(grid + QSize(6, 6)); // a margin of 6 px for every cell
  else
    listView->setGridSize(grid);
  FolderItemDelegate* delegate = static_cast<FolderItemDelegate*>(listView->itemDelegateForColumn(FolderModel::ColumnFileName));
  delegate->setGridSize(grid);
}
Exemple #5
0
void LXQtConfig::MainWindow::setSizing()
{
    // consult the style to know the icon size
    int iconSize = qBound(16, view->decorationSize().height(), 256);
    // DPR is automatically taken into account in setIconSize()
    // but wee need to consider it explicitly below
    int dpr = qApp->devicePixelRatio();
    if (dpr < 1) dpr = 1;
    iconSize *= dpr;
    /* To have an appropriate grid size, we suppose that
     *
     * (1) The text has 3 lines and each line has 16 chars (for languages like German), at most;
     * (2) The selection rect has a margin of 2 px, at most;
     * (3) There is, at most, a 3-px spacing between text and icon; and
     * (4) There is a 4-px margin around each cell.
     */
    QFontMetrics fm = fontMetrics();
    int textWidth = fm.averageCharWidth() * 16;
    int textHeight = fm.lineSpacing() * 3;
    QSize grid;
    grid.setWidth(qMax(iconSize, textWidth) + 4);
    grid.setHeight(iconSize + textHeight + 4 + 3);
    view->setGridSize(grid + QSize(8, 8));
}
void QWinTerminalImpl::viewPaintEvent (QConsoleView* w, QPaintEvent* event, bool cursor)
{
  //d->updateConsoleSize(true);
  QPainter p (w);
  int cw, ch;
  QFontMetrics fm (d->m_font);
  cw = fm.averageCharWidth();
  ch = fm.lineSpacing();
  int ascent, stride;
  double cx1, cy1, cx2, cy2, x, y;
  WORD attr = 0;
  QString s;
  bool hasChar = false;

  QRect updateRect = event->rect ();

  cx1 = updateRect.left () / cw;
  cy1 = updateRect.top () / ch;
  cx2 = qMin (d->m_consoleRect.width () - 1, qRound(updateRect.right () / cw));
  cy2 = qMin (d->m_consoleRect.height () - 1, qRound(updateRect.bottom () / ch));

  if (cx1 > d->m_consoleRect.width () - 1
      || cy1 > d->m_consoleRect.height () - 1)
    return;

  p.setFont (d->m_font);
  p.setPen (Qt::black);

  ascent = p.fontMetrics ().ascent ();
  stride = d->m_consoleRect.width ();

  s.reserve (cx2 - cx1 + 1);
  y = ascent + cy1 * ch;

  for (int j = cy1; j <= cy2; j++)
    {
      // Reset string buffer and starting X coordinate
      s.clear ();
      hasChar = false;
      x = cx1 * cw;


      for (int i = cx1; i <= cx2; i++)
        {
          CHAR_INFO* ci = &(d->m_buffer[stride*j+i]);

          if ((ci->Attributes & 0x00ff) != attr)
            {
              // Character attributes changed
              if (! s.isEmpty ())
                {
                  // String buffer not empty -> draw it
                  if (hasChar || (attr & 0x00f0))
                    {
                      if (attr & 0x00f0)
                        p.fillRect (x, y-ascent, s.length () * cw, ch,
                                    p.brush ());
                      p.drawText (x, y, s);
                    }
                  x += (s.length () * cw);
                  s.clear ();
                  hasChar = false;
                }
              // Update current pen and store current attributes
              // FIXME: what about background?
              attr = (ci->Attributes & 0x00ff);
              //p.setPen (d->m_colors[attr & 0x000f]);
              //p.setBrush (d->m_colors[(attr >> 4) & 0x000f]);
            }

          // Append current character to the string buffer
          s.append (ci->Char.UnicodeChar);
          if (ci->Char.UnicodeChar != L' ')
            hasChar = true;
        }

      if (! s.isEmpty () && (hasChar || (attr & 0x00f0)))
        {
          // Line end reached, but string buffer not empty -> draw it
          // No need to update s or x, they will be reset on the next
          // for-loop iteration
          if (attr & 0x00f0)
            p.fillRect (x, y-ascent, s.length () * cw, ch, p.brush ());
          p.drawText (x, y, s);
        }

      y += ch;
    }

  // Draw cursor
  //p.setCompositionMode (QPainter::RasterOp_SourceXorDestination);
  if (cursor)
  {
  p.fillRect ((d->m_cursorPos.x () - d->m_consoleRect.x ()) * cw,
              (d->m_cursorPos.y () - d->m_consoleRect.y ()) * ch,
              3, ch, QBrush(Qt::blue));//d->m_colors[7]);
  }
  else
  {
  p.fillRect ((d->m_cursorPos.x () - d->m_consoleRect.x ()) * cw,
                 (d->m_cursorPos.y () - d->m_consoleRect.y ()) * ch,
                 3, ch, QBrush(Qt::red));//d->m_colors[7]);
  }
}
Exemple #7
0
/*!
    Returns the size that will be used if the width of the label is \a
    w. If \a w is -1, the sizeHint() is returned. If \a w is 0 minimumSizeHint() is returned
*/
QSize QLabelPrivate::sizeForWidth(int w) const
{
    Q_Q(const QLabel);
    if(q->minimumWidth() > 0)
        w = qMax(w, q->minimumWidth());
    QSize contentsMargin(leftmargin + rightmargin, topmargin + bottommargin);

    QRect br;

    int hextra = 2 * margin;
    int vextra = hextra;
    QFontMetrics fm = q->fontMetrics();

    if (pixmap && !pixmap->isNull()) {
        br = pixmap->rect();
        br.setSize(br.size() / pixmap->devicePixelRatio());
#ifndef QT_NO_PICTURE
    } else if (picture && !picture->isNull()) {
        br = picture->boundingRect();
#endif
#if QT_CONFIG(movie)
    } else if (movie && !movie->currentPixmap().isNull()) {
        br = movie->currentPixmap().rect();
        br.setSize(br.size() / movie->currentPixmap().devicePixelRatio());
#endif
    } else if (isTextLabel) {
        int align = QStyle::visualAlignment(textDirection(), QFlag(this->align));
        // Add indentation
        int m = indent;

        if (m < 0 && q->frameWidth()) // no indent, but we do have a frame
            m = fm.width(QLatin1Char('x')) - margin*2;
        if (m > 0) {
            if ((align & Qt::AlignLeft) || (align & Qt::AlignRight))
                hextra += m;
            if ((align & Qt::AlignTop) || (align & Qt::AlignBottom))
                vextra += m;
        }

        if (control) {
            ensureTextLayouted();
            const qreal oldTextWidth = control->textWidth();
            // Calculate the length of document if w is the width
            if (align & Qt::TextWordWrap) {
                if (w >= 0) {
                    w = qMax(w-hextra-contentsMargin.width(), 0); // strip margin and indent
                    control->setTextWidth(w);
                } else {
                    control->adjustSize();
                }
            } else {
                control->setTextWidth(-1);
            }

            QSizeF controlSize = control->size();
            br = QRect(QPoint(0, 0), QSize(qCeil(controlSize.width()), qCeil(controlSize.height())));

            // restore state
            control->setTextWidth(oldTextWidth);
        } else {
            // Turn off center alignment in order to avoid rounding errors for centering,
            // since centering involves a division by 2. At the end, all we want is the size.
            int flags = align & ~(Qt::AlignVCenter | Qt::AlignHCenter);
            if (hasShortcut) {
                flags |= Qt::TextShowMnemonic;
                QStyleOption opt;
                opt.initFrom(q);
                if (!q->style()->styleHint(QStyle::SH_UnderlineShortcut, &opt, q))
                    flags |= Qt::TextHideMnemonic;
            }

            bool tryWidth = (w < 0) && (align & Qt::TextWordWrap);
            if (tryWidth)
                w = qMin(fm.averageCharWidth() * 80, q->maximumSize().width());
            else if (w < 0)
                w = 2000;
            w -= (hextra + contentsMargin.width());
            br = fm.boundingRect(0, 0, w ,2000, flags, text);
            if (tryWidth && br.height() < 4*fm.lineSpacing() && br.width() > w/2)
                br = fm.boundingRect(0, 0, w/2, 2000, flags, text);
            if (tryWidth && br.height() < 2*fm.lineSpacing() && br.width() > w/4)
                br = fm.boundingRect(0, 0, w/4, 2000, flags, text);
        }
    } else {
        br = QRect(QPoint(0, 0), QSize(fm.averageCharWidth(), fm.lineSpacing()));
    }

    const QSize contentsSize(br.width() + hextra, br.height() + vextra);
    return (contentsSize + contentsMargin).expandedTo(q->minimumSize());
}
Exemple #8
0
void PlIconViewItemDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
    QString title = VLCModel::getMeta( index, COLUMN_TITLE );
    QString artist = VLCModel::getMeta( index, COLUMN_ARTIST );

    QFont font( index.data( Qt::FontRole ).value<QFont>() );
    font.setPointSize( __MAX( font.pointSize() + i_zoom, 4 ) );
    font.setBold( index.data( PLModel::IsCurrentRole ).toBool() );
    painter->setFont( font );
    QFontMetrics fm = painter->fontMetrics();

    int averagewidth = fm.averageCharWidth();
    QSize rectSize = option.rect.size();
    int art_width = averagewidth * ICON_SCALER;
    int art_height = averagewidth * ICON_SCALER;

    QPixmap artPix = VLCModel::getArtPixmap( index, QSize( art_width, art_height) );

    paintBackground( painter, option, index );

    painter->save();

    QRect artRect( option.rect.x() + ( rectSize.width() - artPix.width() ) / 2,
                   option.rect.y() - averagewidth*3 + ( rectSize.height() - artPix.height() ) / 2,
                   artPix.width(), artPix.height() );

    // Draw the drop shadow
    painter->save();
    painter->setOpacity( 0.7 );
    painter->setBrush( QBrush( Qt::darkGray ) );
    painter->setPen( Qt::NoPen );
    painter->drawRoundedRect( artRect.adjusted( 0, 0, 2, 2 ), ART_RADIUS, ART_RADIUS );
    painter->restore();

    // Draw the art pixmap
    QPainterPath artRectPath;
    artRectPath.addRoundedRect( artRect, ART_RADIUS, ART_RADIUS );
    painter->setClipPath( artRectPath );
    painter->drawPixmap( artRect, artPix );
    painter->setClipping( false );

    if( option.state & QStyle::State_Selected )
        painter->setPen( option.palette.color( QPalette::HighlightedText ) );


    //Draw children indicator
    if( !index.data( PLModel::IsLeafNodeRole ).toBool() )
    {
        QRect r( option.rect );
        r.setSize( QSize( 25, 25 ) );
        r.translate( 5, 5 );
        if( index.data( PLModel::IsCurrentsParentNodeRole ).toBool() )
        {
            painter->setOpacity( 0.75 );
            QPainterPath nodeRectPath;
            nodeRectPath.addRoundedRect( r, 4, 4 );
            painter->fillPath( nodeRectPath, option.palette.color( QPalette::Highlight ) );
            painter->setOpacity( 1.0 );
        }
        QPixmap dirPix( ":/type/node" );
        QRect r2( dirPix.rect() );
        r2.moveCenter( r.center() );
        painter->drawPixmap( r2, dirPix );
    }

    // Draw title
    font.setItalic( true );

    QRect textRect;
    textRect.setRect( option.rect.x() , artRect.bottom() + fm.height()/2, option.rect.width(), fm.height() );

    painter->drawText( textRect,
                      fm.elidedText( title, Qt::ElideRight, textRect.width() ),
                      QTextOption( Qt::AlignCenter ) );

    // Draw artist
    painter->setPen( painter->pen().color().lighter( 150 ) );
    font.setItalic( false );
    painter->setFont( font );
    fm = painter->fontMetrics();

    textRect.moveTop( textRect.bottom() + 1 );

    painter->drawText(  textRect,
                        fm.elidedText( artist, Qt::ElideRight, textRect.width() ),
                        QTextOption( Qt::AlignCenter ) );

    painter->restore();
}
Exemple #9
0
/*!
    Returns the size that will be used if the width of the label is \a
    w. If \a w is -1, the sizeHint() is returned. If \a w is 0 minimumSizeHint() is returned
*/
QSize QLabelPrivate::sizeForWidth(int w) const
{
    Q_Q(const QLabel);
    QSize contentsMargin(leftmargin + rightmargin, topmargin + bottommargin);

    QRect br;

    int hextra = 2 * margin;
    int vextra = hextra;
    QFontMetrics fm = q->fontMetrics();

    if (pixmap)
        br = pixmap->rect();
#ifndef QT_NO_PICTURE
    else if (picture)
        br = picture->boundingRect();
#endif
#ifndef QT_NO_MOVIE
    else if (movie)
        br = movie->currentPixmap().rect();
#endif
    else if (isTextLabel) {
        int align = QStyle::visualAlignment(q->layoutDirection(), QFlag(this->align));
        // Add indentation
        int m = indent;

        if (m < 0 && q->frameWidth()) // no indent, but we do have a frame
            m = fm.width(QLatin1Char('x')) - margin*2;
        if (m > 0) {
            if ((align & Qt::AlignLeft) || (align & Qt::AlignRight))
                hextra += m;
            if ((align & Qt::AlignTop) || (align & Qt::AlignBottom))
                vextra += m;
        }

        if (control) {
            ensureTextLayouted();
            const qreal oldTextWidth = control->textWidth();
            // Calculate the length of document if w is the width
            if (align & Qt::TextWordWrap) {
                if (w >= 0) {
                    w = qMax(w-hextra-contentsMargin.width(), 0); // strip margin and indent
                    control->setTextWidth(w);
                } else {
                    control->adjustSize();
                }
            } else {
                control->setTextWidth(-1);
            }
            br = QRect(QPoint(0, 0), control->size().toSize());

            // restore state
            control->setTextWidth(oldTextWidth);
        } else {
            int flags = align;
            if (hasShortcut) {
                flags |= Qt::TextShowMnemonic;
                QStyleOption opt;
                opt.initFrom(q);
                if (!q->style()->styleHint(QStyle::SH_UnderlineShortcut, &opt, q))
                    flags |= Qt::TextHideMnemonic;
            }

            bool tryWidth = (w < 0) && (align & Qt::TextWordWrap);
            if (tryWidth)
                w = fm.averageCharWidth() * 80;
            else if (w < 0)
                w = 2000;
            w -= (hextra + contentsMargin.width());
            br = fm.boundingRect(0, 0, w ,2000, flags, text);
            if (tryWidth && br.height() < 4*fm.lineSpacing() && br.width() > w/2)
                br = fm.boundingRect(0, 0, w/2, 2000, flags, text);
            if (tryWidth && br.height() < 2*fm.lineSpacing() && br.width() > w/4)
                br = fm.boundingRect(0, 0, w/4, 2000, flags, text);
        }
    } else {
        br = QRect(QPoint(0, 0), QSize(fm.averageCharWidth(), fm.lineSpacing()));
    }

    const QSize contentsSize(br.width() + hextra, br.height() + vextra);
    return contentsSize + contentsMargin;
}
Exemple #10
0
void TimelineBar::paintEvent(QPaintEvent *e)
{
  QPainter p(viewport());

  p.setFont(font());
  p.setRenderHint(QPainter::TextAntialiasing);

  // draw boundaries and background
  {
    QRectF r = viewport()->rect();

    p.fillRect(r, palette().brush(QPalette::Window));

    r = r.marginsRemoved(QMargins(borderWidth + margin, borderWidth + margin, borderWidth + margin,
                                  borderWidth + margin));

    p.fillRect(r, palette().brush(QPalette::Base));
    p.drawRect(r);
  }

  QTextOption to;

  to.setWrapMode(QTextOption::NoWrap);
  to.setAlignment(Qt::AlignLeft | Qt::AlignVCenter);

  QFontMetrics fm = p.fontMetrics();

  {
    QRectF titleRect = m_eidAxisRect;
    titleRect.setLeft(titleRect.left() - m_titleWidth);
    titleRect.setWidth(m_titleWidth);

    p.setPen(QPen(palette().brush(QPalette::Text), 1.0));

    // add an extra margin for the text
    p.drawText(titleRect.marginsRemoved(QMarginsF(margin, 0, 0, 0)), eidAxisTitle, to);

    titleRect.setLeft(titleRect.left() - margin);
    titleRect.setTop(titleRect.top() - margin);
    p.drawLine(titleRect.bottomLeft(), titleRect.bottomRight());
    p.drawLine(titleRect.topRight(), titleRect.bottomRight());
  }

  QRectF eidAxisRect = m_eidAxisRect;

  p.drawLine(eidAxisRect.bottomLeft(), eidAxisRect.bottomRight() + QPointF(margin, 0));

  p.drawLine(m_highlightingRect.topLeft(), m_highlightingRect.topRight());

  if(m_Draws.isEmpty())
    return;

  eidAxisRect.setLeft(m_eidAxisRect.left() + m_pan);

  uint32_t maxEID = m_Draws.isEmpty() ? 0 : m_Draws.back();

  to.setAlignment(Qt::AlignCenter | Qt::AlignVCenter);

  p.setFont(Formatter::PreferredFont());

  QRectF hoverRect = eidAxisRect;

  // clip labels to the visible section
  p.setClipRect(m_eidAxisRect.marginsAdded(QMargins(0, margin, margin, 0)));

  // draw where we're hovering
  {
    QPoint pos = viewport()->mapFromGlobal(QCursor::pos());

    if(m_dataArea.contains(pos))
    {
      uint32_t hoverEID = eventAt(pos.x());

      hoverRect.setLeft(offsetOf(hoverEID));
      hoverRect.setWidth(m_eidAxisLabelWidth);

      // recentre
      hoverRect.moveLeft(hoverRect.left() - m_eidAxisLabelWidth / 2 + m_eidWidth / 2);

      QColor backCol = palette().color(QPalette::Base);

      if(getLuminance(backCol) < 0.2f)
        backCol = backCol.lighter(120);
      else
        backCol = backCol.darker(120);

      QRectF backRect = hoverRect.marginsAdded(QMargins(0, margin - borderWidth, 0, 0));

      backRect.setLeft(qMax(backRect.left(), m_eidAxisRect.left() + 1));

      p.fillRect(backRect, backCol);

      p.drawText(hoverRect, QString::number(hoverEID), to);

      // re-add the top margin so the lines match up with the border around the EID axis
      hoverRect = hoverRect.marginsAdded(QMargins(0, margin, 0, 0));

      if(hoverRect.left() >= m_eidAxisRect.left())
        p.drawLine(hoverRect.topLeft(), hoverRect.bottomLeft());
      p.drawLine(hoverRect.topRight(), hoverRect.bottomRight());

      // shrink the rect a bit for clipping against labels below
      hoverRect.setX(qRound(hoverRect.x() + 0.5));
      hoverRect.setWidth(int(hoverRect.width()));
    }
    else
    {
      hoverRect = QRectF();
    }
  }

  QRectF labelRect = eidAxisRect;
  labelRect.setWidth(m_eidAxisLabelWidth);

  // iterate through the EIDs from 0, starting from possible a negative offset if the user has
  // panned to the right.
  for(uint32_t i = 0; i <= maxEID; i += m_eidAxisLabelStep)
  {
    labelRect.moveLeft(offsetOf(i) - labelRect.width() / 2 + m_eidWidth / 2);

    // check if this label is visible at all, but don't draw labels that intersect with the hovered
    // number
    if(labelRect.right() >= 0 && !labelRect.intersects(hoverRect))
      p.drawText(labelRect, QString::number(i), to);

    // check if labelRect is off the edge of the screen
    if(labelRect.left() >= m_eidAxisRect.right())
      break;
  }

  // stop clipping
  p.setClipRect(viewport()->rect());

  // clip the markers
  p.setClipRect(m_markerRect);

  {
    QPen pen = p.pen();
    paintMarkers(p, m_RootMarkers, m_RootDraws, m_markerRect);
    p.setPen(pen);
  }

  // stop clipping
  p.setClipRect(viewport()->rect());

  QRectF currentRect = eidAxisRect;

  // draw the current label and line
  {
    uint32_t curEID = m_Ctx.CurEvent();

    currentRect.setLeft(offsetOf(curEID));
    currentRect.setWidth(
        qMax(m_eidAxisLabelWidth, m_eidAxisLabelTextWidth + dataBarHeight + margin * 2));

    // recentre
    currentRect.moveLeft(currentRect.left() - currentRect.width() / 2 + m_eidWidth / 2);

    // remember where the middle would have been, without clamping
    qreal realMiddle = currentRect.center().x();

    // clamp the position from the left or right side
    if(currentRect.left() < eidAxisRect.left())
      currentRect.moveLeft(eidAxisRect.left());
    else if(currentRect.right() > eidAxisRect.right())
      currentRect.moveRight(eidAxisRect.right());

    // re-add the top margin so the lines match up with the border around the EID axis
    QRectF currentBackRect = currentRect.marginsAdded(QMargins(0, margin, 0, 0));

    p.fillRect(currentBackRect, palette().brush(QPalette::Base));
    p.drawRect(currentBackRect);

    // draw the 'current marker' pixmap
    const QPixmap &px = Pixmaps::flag_green(devicePixelRatio());
    p.drawPixmap(currentRect.topLeft() + QPointF(margin, 1), px, px.rect());

    // move to where the text should be and draw it
    currentRect.setLeft(currentRect.left() + margin * 2 + dataBarHeight);
    p.drawText(currentRect, QString::number(curEID), to);

    // draw a line from the bottom of the shadow downwards
    QPointF currentTop = currentRect.center();
    currentTop.setX(int(qBound(eidAxisRect.left(), realMiddle, eidAxisRect.right() - 2.0)) + 0.5);
    currentTop.setY(currentRect.bottom());

    QPointF currentBottom = currentTop;
    currentBottom.setY(m_markerRect.bottom());

    p.drawLine(currentTop, currentBottom);
  }

  to.setAlignment(Qt::AlignLeft | Qt::AlignTop);

  if(!m_UsageTarget.isEmpty() || !m_HistoryTarget.isEmpty())
  {
    p.setRenderHint(QPainter::Antialiasing);

    QRectF highlightLabel = m_highlightingRect.marginsRemoved(uniformMargins(margin));

    highlightLabel.setX(highlightLabel.x() + margin);

    QString text;

    if(!m_HistoryTarget.isEmpty())
      text = tr("Pixel history for %1").arg(m_HistoryTarget);
    else
      text = tr("Usage for %1:").arg(m_UsageTarget);

    p.drawText(highlightLabel, text, to);

    const int triRadius = fm.averageCharWidth();
    const int triHeight = fm.ascent();

    QPainterPath triangle;
    triangle.addPolygon(
        QPolygonF({QPoint(0, triHeight), QPoint(triRadius * 2, triHeight), QPoint(triRadius, 0)}));
    triangle.closeSubpath();

    enum
    {
      ReadUsage,
      WriteUsage,
      ReadWriteUsage,
      ClearUsage,
      BarrierUsage,

      HistoryPassed,
      HistoryFailed,

      UsageCount,
    };

    const QColor colors[UsageCount] = {
        // read
        QColor(Qt::red),
        // write
        QColor(Qt::green),
        // read/write
        QColor(Qt::yellow),
        // clear
        QColor(Qt::blue),
        // barrier
        QColor(Qt::magenta),

        // pass
        QColor(Qt::green),
        // fail
        QColor(Qt::red),
    };

    // draw the key
    if(m_HistoryTarget.isEmpty())
    {
      // advance past the first text to draw the key
      highlightLabel.setLeft(highlightLabel.left() + fm.width(text));

      text = lit(" Reads ( ");
      p.drawText(highlightLabel, text, to);
      highlightLabel.setLeft(highlightLabel.left() + fm.width(text));

      QPainterPath path = triangle.translated(aliasAlign(highlightLabel.topLeft()));
      p.fillPath(path, colors[ReadUsage]);
      p.drawPath(path);
      highlightLabel.setLeft(highlightLabel.left() + triRadius * 2);

      text = lit(" ), Writes ( ");
      p.drawText(highlightLabel, text, to);
      highlightLabel.setLeft(highlightLabel.left() + fm.width(text));

      path = triangle.translated(aliasAlign(highlightLabel.topLeft()));
      p.fillPath(path, colors[WriteUsage]);
      p.drawPath(path);
      highlightLabel.setLeft(highlightLabel.left() + triRadius * 2);

      text = lit(" ), Read/Write ( ");
      p.drawText(highlightLabel, text, to);
      highlightLabel.setLeft(highlightLabel.left() + fm.width(text));

      path = triangle.translated(aliasAlign(highlightLabel.topLeft()));
      p.fillPath(path, colors[ReadWriteUsage]);
      p.drawPath(path);
      highlightLabel.setLeft(highlightLabel.left() + triRadius * 2);

      if(m_Ctx.CurPipelineState().SupportsBarriers())
      {
        text = lit(" ) Barriers ( ");
        p.drawText(highlightLabel, text, to);
        highlightLabel.setLeft(highlightLabel.left() + fm.width(text));

        path = triangle.translated(aliasAlign(highlightLabel.topLeft()));
        p.fillPath(path, colors[BarrierUsage]);
        p.drawPath(path);
        highlightLabel.setLeft(highlightLabel.left() + triRadius * 2);
      }

      text = lit(" ), and Clears ( ");
      p.drawText(highlightLabel, text, to);
      highlightLabel.setLeft(highlightLabel.left() + fm.width(text));

      path = triangle.translated(aliasAlign(highlightLabel.topLeft()));
      p.fillPath(path, colors[ClearUsage]);
      p.drawPath(path);
      highlightLabel.setLeft(highlightLabel.left() + triRadius * 2);

      text = lit(" )");
      p.drawText(highlightLabel, text, to);
    }

    PipRanges pipranges[UsageCount];

    QRectF pipsRect = m_highlightingRect.marginsRemoved(uniformMargins(margin));

    pipsRect.setX(pipsRect.x() + margin + m_titleWidth);
    pipsRect.setHeight(triHeight + margin);
    pipsRect.moveBottom(m_highlightingRect.bottom());

    p.setClipRect(pipsRect);

    qreal leftClip = -triRadius * 2.0;
    qreal rightClip = pipsRect.width() + triRadius * 10.0;

    if(!m_HistoryEvents.isEmpty())
    {
      for(const PixelModification &mod : m_HistoryEvents)
      {
        qreal pos = offsetOf(mod.eventId) + m_eidWidth / 2 - triRadius;

        if(pos < leftClip || pos > rightClip)
          continue;

        if(mod.Passed())
          pipranges[HistoryPassed].push(pos, triRadius);
        else
          pipranges[HistoryFailed].push(pos, triRadius);
      }
    }
    else
    {
      for(const EventUsage &use : m_UsageEvents)
      {
        qreal pos = offsetOf(use.eventId) + m_eidWidth / 2 - triRadius;

        if(pos < leftClip || pos > rightClip)
          continue;

        if(((int)use.usage >= (int)ResourceUsage::VS_RWResource &&
            (int)use.usage <= (int)ResourceUsage::All_RWResource) ||
           use.usage == ResourceUsage::GenMips || use.usage == ResourceUsage::Copy ||
           use.usage == ResourceUsage::Resolve)
        {
          pipranges[ReadWriteUsage].push(pos, triRadius);
        }
        else if(use.usage == ResourceUsage::StreamOut || use.usage == ResourceUsage::ResolveDst ||
                use.usage == ResourceUsage::ColorTarget ||
                use.usage == ResourceUsage::DepthStencilTarget || use.usage == ResourceUsage::CopyDst)
        {
          pipranges[WriteUsage].push(pos, triRadius);
        }
        else if(use.usage == ResourceUsage::Clear)
        {
          pipranges[ClearUsage].push(pos, triRadius);
        }
        else if(use.usage == ResourceUsage::Barrier)
        {
          pipranges[BarrierUsage].push(pos, triRadius);
        }
        else
        {
          pipranges[ReadUsage].push(pos, triRadius);
        }
      }
    }

    for(int i = 0; i < UsageCount; i++)
    {
      QPainterPath path = pipranges[i].makePath(triRadius, triHeight, pipsRect.y());

      if(!path.isEmpty())
      {
        p.drawPath(path);
        p.fillPath(path, colors[i]);
      }
    }
  }
  else
  {
    QRectF highlightLabel = m_highlightingRect;
    highlightLabel = highlightLabel.marginsRemoved(uniformMargins(margin));

    highlightLabel.setX(highlightLabel.x() + margin);

    p.drawText(highlightLabel, tr("No resource selected for highlighting."), to);
  }
}