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) 2017 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 | { | ||||
46 | } | ||||
47 | | ||||
48 | KateAnnotationItemDelegate::~KateAnnotationItemDelegate() | ||||
49 | { | ||||
50 | } | ||||
51 | | ||||
52 | void KateAnnotationItemDelegate::paint(QPainter *painter, const KTextEditor::StyleOptionAnnotationItem &option, | ||||
53 | KTextEditor::AnnotationModel *model, int line) const | ||||
54 | { | ||||
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(painter); | ||||
56 | Q_ASSERT(model); | ||||
57 | if (!painter || !model) { | ||||
58 | return; | ||||
dhaumann: validness --> validity :-) | |||||
59 | } | ||||
60 | // TODO: also test line for sake of completeness | ||||
61 | | ||||
62 | painter->save(); | ||||
63 | | ||||
64 | const int margin = 3; | ||||
65 | | ||||
66 | const QVariant background = model->data(line, Qt::BackgroundRole); | ||||
67 | // Fill the background | ||||
68 | if (background.isValid()) { | ||||
69 | painter->fillRect(option.rect, background.value<QBrush>()); | ||||
70 | } | ||||
71 | | ||||
72 | const QVariant foreground = model->data(line, Qt::ForegroundRole); | ||||
73 | // Set the pen for drawing the foreground | ||||
74 | if (foreground.isValid() && foreground.canConvert<QPen>()) { | ||||
75 | painter->setPen(foreground.value<QPen>()); | ||||
76 | } | ||||
77 | | ||||
78 | // Draw a border around all adjacent entries that have the same text as the currently hovered one | ||||
79 | if (option.highlight) { | ||||
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::Beginning) || | ||||
85 | (option.annotationItemGroupingPosition == KTextEditor::StyleOptionAnnotationItem::OnlyOne)) && | ||||
86 | (option.wrappedLine == 0)) { | ||||
87 | painter->drawLine(option.rect.topLeft(), option.rect.topRight()); | ||||
88 | } | ||||
89 | | ||||
90 | if (((option.annotationItemGroupingPosition == KTextEditor::StyleOptionAnnotationItem::End) || | ||||
91 | (option.annotationItemGroupingPosition == KTextEditor::StyleOptionAnnotationItem::OnlyOne)) && | ||||
92 | (option.wrappedLine == (option.wrappedLineCount-1))) { | ||||
93 | painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight()); | ||||
94 | } | ||||
95 | } | ||||
96 | // reset pen | ||||
97 | if (foreground.isValid()) { | ||||
98 | QPen pen = painter->pen(); | ||||
99 | pen.setWidth(1); | ||||
100 | painter->setPen(pen); | ||||
101 | } | ||||
102 | | ||||
103 | // Now draw the normal text | ||||
104 | const QVariant text = model->data(line, Qt::DisplayRole); | ||||
105 | if ((option.wrappedLine == 0) && text.isValid() && text.canConvert<QString>()) { | ||||
106 | painter->drawText(option.rect.x() + margin, option.rect.y(), | ||||
107 | option.rect.width() - 2*margin, option.rect.height(), | ||||
108 | Qt::AlignLeft | Qt::AlignVCenter, text.toString()); | ||||
109 | } | ||||
110 | | ||||
111 | painter->restore(); | ||||
112 | } | ||||
113 | | ||||
114 | bool KateAnnotationItemDelegate::helpEvent(QHelpEvent *event, KTextEditor::View *view, | ||||
115 | KTextEditor::AnnotationModel *model, int line) | ||||
116 | { | ||||
117 | if (!model || event->type() != QEvent::ToolTip) { | ||||
118 | return false; | ||||
119 | } | ||||
120 | | ||||
121 | const QVariant data = model->data(line, Qt::ToolTipRole); | ||||
122 | if (!data.isValid()) { | ||||
123 | return false; | ||||
124 | } | ||||
125 | | ||||
126 | const QString toolTipText = data.toString(); | ||||
127 | if (!toolTipText.isEmpty()) { | ||||
128 | QToolTip::showText(event->globalPos(), toolTipText, view); | ||||
129 | } | ||||
130 | return true; | ||||
131 | } | ||||
132 | | ||||
133 | void KateAnnotationItemDelegate::contextMenuRequested(const QPoint &pos, | ||||
134 | KTextEditor::AnnotationModel *model, int line) | ||||
135 | { | ||||
136 | Q_UNUSED(model); | ||||
137 | | ||||
138 | QMenu menu; | ||||
139 | QAction a(i18n("Disable Annotation Bar"), &menu); | ||||
140 | a.setIcon(QIcon::fromTheme(QStringLiteral("dialog-close"))); | ||||
141 | menu.addAction(&a); | ||||
142 | emit m_view->annotationContextMenuAboutToShow(m_view, &menu, line); | ||||
143 | if (menu.exec(m_view->mapToGlobal(pos)) == &a) { | ||||
144 | m_view->setAnnotationBorderVisible(false); | ||||
145 | } | ||||
146 | } | ||||
147 | | ||||
148 | QSize KateAnnotationItemDelegate::sizeHint(const KTextEditor::StyleOptionAnnotationItem &option, | ||||
149 | KTextEditor::AnnotationModel *model, int line) const | ||||
150 | { | ||||
151 | Q_ASSERT(model); | ||||
152 | if (!model) { | ||||
153 | return QSize(0, 0); | ||||
154 | } | ||||
155 | | ||||
156 | // TODO: cache maxCharWidth for given font | ||||
157 | qreal maxCharWidth = 0.0; | ||||
158 | // TODO: why only decimal digits? | ||||
159 | // Loop to determine the widest numeric character in the current font. | ||||
160 | // 48 is ascii '0' | ||||
161 | for (int i = 48; i < 58; ++i) { | ||||
162 | const qreal charWidth = ceil(option.contentFontMetrics.width(QChar(i))); | ||||
163 | maxCharWidth = qMax(maxCharWidth, charWidth); | ||||
164 | } | ||||
165 | QVariant data = model->data(line, Qt::DisplayRole); | ||||
166 | return QSize(data.toString().length() * maxCharWidth + 8, option.fontMetrics.height()); | ||||
167 | } |
Given you check for a valid pointers here, would it also be an option to pass references? Or would that violate Qt style API?