Changeset View
Changeset View
Standalone View
Standalone View
src/view/kateannotationitemdelegate.cpp
- This file was added.
1 | /* This file is part of the KDE libraries | ||||
---|---|---|---|---|---|
2 | Copyright (C) 2008, 2009 Matthew Woehlke <mw_triad@users.sourceforge.net> | ||||
3 | Copyright (C) 2007 Mirko Stocker <me@misto.ch> | ||||
4 | Copyright (C) 2002 John Firebaugh <jfirebaugh@kde.org> | ||||
5 | Copyright (C) 2001 Anders Lund <anders@alweb.dk> | ||||
6 | Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org> | ||||
7 | Copyright (C) 2011 Svyatoslav Kuzmich <svatoslav1@gmail.com> | ||||
8 | Copyright (C) 2012 Kåre Särs <kare.sars@iki.fi> (Minimap) | ||||
9 | Copyright (C) 2018 Friedrich W. H. Kossebau <kossebau@kde.org> | ||||
10 | | ||||
11 | This library is free software; you can redistribute it and/or | ||||
12 | modify it under the terms of the GNU Library General Public | ||||
13 | License version 2 as published by the Free Software Foundation. | ||||
14 | | ||||
15 | This library is distributed in the hope that it will be useful, | ||||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
18 | Library General Public License for more details. | ||||
19 | | ||||
20 | You should have received a copy of the GNU Library General Public License | ||||
21 | along with this library; see the file COPYING.LIB. If not, write to | ||||
22 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||||
23 | Boston, MA 02110-1301, USA. | ||||
24 | */ | ||||
25 | | ||||
26 | #include "kateannotationitemdelegate.h" | ||||
27 | | ||||
28 | #include "kateviewinternal.h" | ||||
29 | | ||||
30 | #include <KLocalizedString> | ||||
31 | | ||||
32 | #include <QPainter> | ||||
33 | #include <QAction> | ||||
34 | #include <QMenu> | ||||
35 | #include <QToolTip> | ||||
36 | #include <QFontMetricsF> | ||||
37 | | ||||
38 | #include <math.h> | ||||
39 | | ||||
40 | | ||||
41 | KateAnnotationItemDelegate::KateAnnotationItemDelegate(KateViewInternal *internalView, QObject *parent) | ||||
42 | : KTextEditor::AbstractAnnotationItemDelegate(parent) | ||||
43 | , m_internalView(internalView) | ||||
44 | , m_view(internalView->m_view) | ||||
45 | , m_cachedDataContentFontMetrics(QFont()) | ||||
46 | { | ||||
47 | } | ||||
48 | | ||||
49 | KateAnnotationItemDelegate::~KateAnnotationItemDelegate() = default; | ||||
50 | | ||||
51 | void KateAnnotationItemDelegate::paint(QPainter *painter, const KTextEditor::StyleOptionAnnotationItem &option, | ||||
52 | KTextEditor::AnnotationModel *model, int line) const | ||||
53 | { | ||||
54 | Q_ASSERT(painter); | ||||
dhaumann: Given you check for a valid pointers here, would it also be an option to pass references? Or… | |||||
It is following QAbstractItemDelegate ::paint(...) signature here. So I would lean to stay with the current code. But as you prefer. kossebau: It is following [[ http://doc.qt.io/qt-5/qabstractitemdelegate.html#paint |… | |||||
55 | Q_ASSERT(model); | ||||
56 | if (!painter || !model) { | ||||
57 | return; | ||||
58 | } | ||||
dhaumann: validness --> validity :-) | |||||
59 | // TODO: also test line for validness for sake of completeness? | ||||
60 | | ||||
61 | painter->save(); | ||||
62 | | ||||
63 | const int margin = 3; | ||||
64 | | ||||
65 | const QVariant background = model->data(line, Qt::BackgroundRole); | ||||
66 | // Fill the background | ||||
67 | if (background.isValid()) { | ||||
68 | painter->fillRect(option.rect, background.value<QBrush>()); | ||||
69 | } | ||||
70 | | ||||
71 | const QVariant foreground = model->data(line, Qt::ForegroundRole); | ||||
72 | // Set the pen for drawing the foreground | ||||
73 | if (foreground.isValid() && foreground.canConvert<QPen>()) { | ||||
74 | painter->setPen(foreground.value<QPen>()); | ||||
75 | } | ||||
76 | | ||||
77 | // Draw a border around all adjacent entries that have the same text as the currently hovered one | ||||
78 | if ((option.state & QStyle::State_MouseOver) && | ||||
79 | (option.annotationItemGroupingPosition & KTextEditor::StyleOptionAnnotationItem::InGroup)) { | ||||
80 | // draw left and right highlight borders | ||||
81 | painter->drawLine(option.rect.topLeft(), option.rect.bottomLeft()); | ||||
82 | painter->drawLine(option.rect.topRight(), option.rect.bottomRight()); | ||||
83 | | ||||
84 | if ((option.annotationItemGroupingPosition & KTextEditor::StyleOptionAnnotationItem::GroupBegin) && | ||||
85 | (option.wrappedLine == 0)) { | ||||
86 | painter->drawLine(option.rect.topLeft(), option.rect.topRight()); | ||||
87 | } | ||||
88 | | ||||
89 | if ((option.annotationItemGroupingPosition & KTextEditor::StyleOptionAnnotationItem::GroupEnd) && | ||||
90 | (option.wrappedLine == (option.wrappedLineCount-1))) { | ||||
91 | painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight()); | ||||
92 | } | ||||
93 | } | ||||
94 | // reset pen | ||||
95 | if (foreground.isValid()) { | ||||
96 | QPen pen = painter->pen(); | ||||
97 | pen.setWidth(1); | ||||
98 | painter->setPen(pen); | ||||
99 | } | ||||
100 | | ||||
101 | // Now draw the normal text | ||||
102 | const QVariant text = model->data(line, Qt::DisplayRole); | ||||
103 | if ((option.wrappedLine == 0) && text.isValid() && text.canConvert<QString>()) { | ||||
104 | painter->drawText(option.rect.x() + margin, option.rect.y(), | ||||
105 | option.rect.width() - 2*margin, option.rect.height(), | ||||
106 | Qt::AlignLeft | Qt::AlignVCenter, text.toString()); | ||||
107 | } | ||||
108 | | ||||
109 | painter->restore(); | ||||
110 | } | ||||
111 | | ||||
112 | bool KateAnnotationItemDelegate::helpEvent(QHelpEvent *event, KTextEditor::View *view, | ||||
113 | const KTextEditor::StyleOptionAnnotationItem &option, | ||||
114 | KTextEditor::AnnotationModel *model, int line) | ||||
115 | { | ||||
116 | Q_UNUSED(option); | ||||
117 | | ||||
118 | if (!model || event->type() != QEvent::ToolTip) { | ||||
119 | return false; | ||||
120 | } | ||||
121 | | ||||
122 | const QVariant data = model->data(line, Qt::ToolTipRole); | ||||
123 | if (!data.isValid()) { | ||||
124 | return false; | ||||
125 | } | ||||
126 | | ||||
127 | const QString toolTipText = data.toString(); | ||||
128 | if (toolTipText.isEmpty()) { | ||||
129 | return false; | ||||
130 | } | ||||
131 | | ||||
132 | QToolTip::showText(event->globalPos(), toolTipText, view); | ||||
133 | return true; | ||||
134 | } | ||||
135 | | ||||
136 | void KateAnnotationItemDelegate::hideTooltip(KTextEditor::View *view) | ||||
137 | { | ||||
138 | Q_UNUSED(view); | ||||
139 | QToolTip::hideText(); | ||||
140 | } | ||||
141 | | ||||
142 | void KateAnnotationItemDelegate::contextMenuRequested(KTextEditor::View *view, const QPoint &pos, | ||||
143 | const KTextEditor::StyleOptionAnnotationItem &option, | ||||
144 | KTextEditor::AnnotationModel *model, int line) | ||||
145 | { | ||||
146 | Q_UNUSED(model); | ||||
147 | Q_UNUSED(option); | ||||
148 | | ||||
149 | QMenu menu; | ||||
150 | QAction a(i18n("Disable Annotation Bar"), &menu); | ||||
151 | a.setIcon(QIcon::fromTheme(QStringLiteral("dialog-close"))); | ||||
152 | menu.addAction(&a); | ||||
153 | emit m_view->annotationContextMenuAboutToShow(m_view, &menu, line); | ||||
154 | if (menu.exec(view->mapToGlobal(pos)) == &a) { | ||||
155 | m_view->setAnnotationBorderVisible(false); | ||||
156 | } | ||||
157 | } | ||||
158 | | ||||
159 | QSize KateAnnotationItemDelegate::sizeHint(const KTextEditor::StyleOptionAnnotationItem &option, | ||||
160 | KTextEditor::AnnotationModel *model, int line) const | ||||
161 | { | ||||
162 | Q_ASSERT(model); | ||||
163 | if (!model) { | ||||
164 | return QSize(0, 0); | ||||
165 | } | ||||
166 | | ||||
167 | // recalculate m_maxCharWidth if needed | ||||
168 | if (m_maxCharWidth == 0.0 || (option.contentFontMetrics != m_cachedDataContentFontMetrics)) { | ||||
169 | m_maxCharWidth = 0.0; | ||||
170 | // based on old code written when just a hash was shown, could see an update | ||||
171 | // Loop to determine the widest numeric character in the current font. | ||||
172 | for (char c = '0'; c <= '9'; ++c) { | ||||
173 | const qreal charWidth = ceil(option.contentFontMetrics.width(QLatin1Char(c))); | ||||
174 | m_maxCharWidth = qMax(m_maxCharWidth, charWidth); | ||||
175 | } | ||||
176 | | ||||
177 | m_cachedDataContentFontMetrics = option.contentFontMetrics; | ||||
178 | } | ||||
179 | | ||||
180 | const QString annotationText = model->data(line, Qt::DisplayRole).toString(); | ||||
181 | return QSize(annotationText.length() * m_maxCharWidth + 8, option.contentFontMetrics.height()); | ||||
182 | } |
Given you check for a valid pointers here, would it also be an option to pass references? Or would that violate Qt style API?