File indexing completed on 2024-04-21 03:57:51
0001 /* 0002 SPDX-FileCopyrightText: 2017-18 Friedrich W. H. Kossebau <kossebau@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "kateannotationitemdelegate.h" 0008 0009 #include <ktexteditor/annotationinterface.h> 0010 #include <ktexteditor/view.h> 0011 0012 #include <QHelpEvent> 0013 #include <QPainter> 0014 #include <QToolTip> 0015 0016 #include <math.h> 0017 0018 KateAnnotationItemDelegate::KateAnnotationItemDelegate(QObject *parent) 0019 : KTextEditor::AbstractAnnotationItemDelegate(parent) 0020 , m_cachedDataContentFontMetrics(QFont()) 0021 { 0022 } 0023 0024 KateAnnotationItemDelegate::~KateAnnotationItemDelegate() = default; 0025 0026 void KateAnnotationItemDelegate::paint(QPainter *painter, 0027 const KTextEditor::StyleOptionAnnotationItem &option, 0028 KTextEditor::AnnotationModel *model, 0029 int line) const 0030 { 0031 Q_ASSERT(painter); 0032 Q_ASSERT(model); 0033 if (!painter || !model) { 0034 return; 0035 } 0036 // TODO: also test line for validity for sake of completeness? 0037 0038 painter->save(); 0039 0040 const int margin = 3; 0041 0042 const QVariant background = model->data(line, Qt::BackgroundRole); 0043 // Fill the background 0044 if (background.isValid()) { 0045 painter->fillRect(option.rect, background.value<QBrush>()); 0046 } 0047 0048 const QVariant foreground = model->data(line, Qt::ForegroundRole); 0049 // Set the pen for drawing the foreground 0050 if (foreground.isValid() && foreground.canConvert<QPen>()) { 0051 painter->setPen(foreground.value<QPen>()); 0052 } 0053 0054 // Draw a border around all adjacent entries that have the same text as the currently hovered one 0055 if ((option.state & QStyle::State_MouseOver) && (option.annotationItemGroupingPosition & KTextEditor::StyleOptionAnnotationItem::InGroup)) { 0056 // Use floating point coordinates to support scaled rendering 0057 QRectF rect(option.rect); 0058 rect.adjust(0.5, 0.5, -0.5, -0.5); 0059 0060 // draw left and right highlight borders 0061 painter->drawLine(rect.topLeft(), rect.bottomLeft()); 0062 painter->drawLine(rect.topRight(), rect.bottomRight()); 0063 0064 if ((option.annotationItemGroupingPosition & KTextEditor::StyleOptionAnnotationItem::GroupBegin) && (option.wrappedLine == 0)) { 0065 painter->drawLine(rect.topLeft(), rect.topRight()); 0066 } 0067 0068 if ((option.annotationItemGroupingPosition & KTextEditor::StyleOptionAnnotationItem::GroupEnd) 0069 && (option.wrappedLine == (option.wrappedLineCount - 1))) { 0070 painter->drawLine(rect.bottomLeft(), rect.bottomRight()); 0071 } 0072 } 0073 // reset pen 0074 if (foreground.isValid()) { 0075 QPen pen = painter->pen(); 0076 pen.setWidth(1); 0077 painter->setPen(pen); 0078 } 0079 0080 // Now draw the normal text 0081 const QVariant text = model->data(line, Qt::DisplayRole); 0082 if ((option.wrappedLine == 0) && text.isValid() && text.canConvert<QString>()) { 0083 painter->drawText(option.rect.x() + margin, 0084 option.rect.y(), 0085 option.rect.width() - 2 * margin, 0086 option.rect.height(), 0087 Qt::AlignLeft | Qt::AlignVCenter, 0088 text.toString()); 0089 } 0090 0091 painter->restore(); 0092 } 0093 0094 bool KateAnnotationItemDelegate::helpEvent(QHelpEvent *event, 0095 KTextEditor::View *view, 0096 const KTextEditor::StyleOptionAnnotationItem &option, 0097 KTextEditor::AnnotationModel *model, 0098 int line) 0099 { 0100 Q_UNUSED(option); 0101 0102 if (!model || event->type() != QEvent::ToolTip) { 0103 return false; 0104 } 0105 0106 const QVariant data = model->data(line, Qt::ToolTipRole); 0107 if (!data.isValid()) { 0108 return false; 0109 } 0110 0111 const QString toolTipText = data.toString(); 0112 if (toolTipText.isEmpty()) { 0113 return false; 0114 } 0115 0116 QToolTip::showText(event->globalPos(), toolTipText, view, option.rect); 0117 0118 return true; 0119 } 0120 0121 void KateAnnotationItemDelegate::hideTooltip(KTextEditor::View *view) 0122 { 0123 Q_UNUSED(view); 0124 QToolTip::hideText(); 0125 } 0126 0127 QSize KateAnnotationItemDelegate::sizeHint(const KTextEditor::StyleOptionAnnotationItem &option, KTextEditor::AnnotationModel *model, int line) const 0128 { 0129 Q_ASSERT(model); 0130 if (!model) { 0131 return QSize(0, 0); 0132 } 0133 0134 // recalculate m_maxCharWidth if needed 0135 if (m_maxCharWidth == 0.0 || (option.contentFontMetrics != m_cachedDataContentFontMetrics)) { 0136 // based on old code written when just a hash was shown, could see an update 0137 // Loop to determine the widest numeric character in the current font. 0138 m_maxCharWidth = 0.0; 0139 for (char c = '0'; c <= '9'; ++c) { 0140 const qreal charWidth = ceil(option.contentFontMetrics.horizontalAdvance(QLatin1Char(c))); 0141 m_maxCharWidth = qMax(m_maxCharWidth, charWidth); 0142 } 0143 0144 m_cachedDataContentFontMetrics = option.contentFontMetrics; 0145 } 0146 0147 const QString annotationText = model->data(line, Qt::DisplayRole).toString(); 0148 return QSize(annotationText.length() * m_maxCharWidth + 8, option.contentFontMetrics.height()); 0149 }