1/*
2 SPDX-FileCopyrightText: 2009 Rafael Fernández López <ereslibre@kde.org>
3 SPDX-FileCopyrightText: 2013 Dominik Haumann <dhaumann@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-or-later
6*/
7
8#include "katecategorydrawer.h"
9
10#include <QApplication>
11#include <QPainter>
12#include <QPainterPath>
13#include <QStyleOption>
14
15KateCategoryDrawer::KateCategoryDrawer()
16 : KCategoryDrawer(nullptr)
17{
18}
19
20void KateCategoryDrawer::drawCategory(const QModelIndex &index, int sortRole, const QStyleOption &option, QPainter *painter) const
21{
22 Q_UNUSED(sortRole)
23
24 painter->setRenderHint(hint: QPainter::Antialiasing);
25
26 const QRect optRect = option.rect;
27 QFont font(QApplication::font());
28 font.setBold(true);
29 const int height = categoryHeight(index, option);
30 const bool leftToRight = painter->layoutDirection() == Qt::LeftToRight;
31
32 // BEGIN: decoration gradient
33 {
34 QPainterPath path(optRect.bottomLeft());
35
36 path.lineTo(p: QPoint(optRect.topLeft().x(), optRect.topLeft().y() - 3));
37 const QPointF topLeft(optRect.topLeft());
38 QRectF arc(topLeft, QSizeF(4, 4));
39 path.arcTo(rect: arc, startAngle: 180, arcLength: -90);
40 path.lineTo(p: optRect.topRight());
41 path.lineTo(p: optRect.bottomRight());
42 path.lineTo(p: optRect.bottomLeft());
43
44 QColor window(option.palette.window().color());
45 const QColor base(option.palette.base().color());
46
47 window.setAlphaF(0.4);
48
49 QLinearGradient decoGradient1;
50 if (leftToRight) {
51 decoGradient1.setStart(optRect.topLeft());
52 decoGradient1.setFinalStop(optRect.bottomLeft());
53 } else {
54 decoGradient1.setStart(optRect.topRight());
55 decoGradient1.setFinalStop(optRect.bottomRight());
56 }
57 decoGradient1.setColorAt(pos: 0, color: window);
58 decoGradient1.setColorAt(pos: 1, color: Qt::transparent);
59
60 QLinearGradient decoGradient2;
61 if (leftToRight) {
62 decoGradient2.setStart(optRect.topLeft());
63 decoGradient2.setFinalStop(optRect.topRight());
64 } else {
65 decoGradient2.setStart(optRect.topRight());
66 decoGradient2.setFinalStop(optRect.topLeft());
67 }
68 decoGradient2.setColorAt(pos: 0, color: Qt::transparent);
69 decoGradient2.setColorAt(pos: 1, color: base);
70
71 painter->fillPath(path, brush: decoGradient1);
72 painter->fillPath(path, brush: decoGradient2);
73 }
74 // END: decoration gradient
75
76 {
77 QRect newOptRect(optRect);
78
79 if (leftToRight) {
80 newOptRect.translate(dx: 1, dy: 1);
81 } else {
82 newOptRect.translate(dx: -1, dy: 1);
83 }
84
85 // BEGIN: inner top left corner
86 {
87 painter->save();
88 painter->setPen(option.palette.base().color());
89 QRectF arc;
90 if (leftToRight) {
91 const QPointF topLeft(newOptRect.topLeft());
92 arc = QRectF(topLeft, QSizeF(4, 4));
93 arc.translate(dx: 0.5, dy: 0.5);
94 painter->drawArc(rect: arc, a: 1440, alen: 1440);
95 } else {
96 QPointF topRight(newOptRect.topRight());
97 topRight.rx() -= 4;
98 arc = QRectF(topRight, QSizeF(4, 4));
99 arc.translate(dx: -0.5, dy: 0.5);
100 painter->drawArc(rect: arc, a: 0, alen: 1440);
101 }
102 painter->restore();
103 }
104 // END: inner top left corner
105
106 // BEGIN: inner left vertical line
107 {
108 QPoint start;
109 QPoint verticalGradBottom;
110 if (leftToRight) {
111 start = newOptRect.topLeft();
112 verticalGradBottom = newOptRect.topLeft();
113 } else {
114 start = newOptRect.topRight();
115 verticalGradBottom = newOptRect.topRight();
116 }
117 start.ry() += 3;
118 verticalGradBottom.ry() += newOptRect.height() - 3;
119 QLinearGradient gradient(start, verticalGradBottom);
120 gradient.setColorAt(pos: 0, color: option.palette.base().color());
121 gradient.setColorAt(pos: 1, color: Qt::transparent);
122 painter->fillRect(QRect(start, QSize(1, newOptRect.height() - 3)), gradient);
123 }
124 // END: inner left vertical line
125
126 // BEGIN: inner horizontal line
127 {
128 QPoint start;
129 QPoint horizontalGradTop;
130 if (leftToRight) {
131 start = newOptRect.topLeft();
132 horizontalGradTop = newOptRect.topLeft();
133 start.rx() += 3;
134 horizontalGradTop.rx() += newOptRect.width() - 3;
135 } else {
136 start = newOptRect.topRight();
137 horizontalGradTop = newOptRect.topRight();
138 start.rx() -= 3;
139 horizontalGradTop.rx() -= newOptRect.width() - 3;
140 }
141 QLinearGradient gradient(start, horizontalGradTop);
142 gradient.setColorAt(pos: 0, color: option.palette.base().color());
143 gradient.setColorAt(pos: 1, color: Qt::transparent);
144 QSize rectSize;
145 if (leftToRight) {
146 rectSize = QSize(newOptRect.width() - 3, 1);
147 } else {
148 rectSize = QSize(-newOptRect.width() + 3, 1);
149 }
150 painter->fillRect(QRect(start, rectSize), gradient);
151 }
152 // END: inner horizontal line
153 }
154
155 QColor outlineColor = option.palette.text().color();
156 outlineColor.setAlphaF(0.35);
157
158 // BEGIN: top left corner
159 {
160 painter->save();
161 painter->setPen(outlineColor);
162 QRectF arc;
163 if (leftToRight) {
164 const QPointF topLeft(optRect.topLeft());
165 arc = QRectF(topLeft, QSizeF(4, 4));
166 arc.translate(dx: 0.5, dy: 0.5);
167 painter->drawArc(rect: arc, a: 1440, alen: 1440);
168 } else {
169 QPointF topRight(optRect.topRight());
170 topRight.rx() -= 4;
171 arc = QRectF(topRight, QSizeF(4, 4));
172 arc.translate(dx: -0.5, dy: 0.5);
173 painter->drawArc(rect: arc, a: 0, alen: 1440);
174 }
175 painter->restore();
176 }
177 // END: top left corner
178
179 // BEGIN: left vertical line
180 {
181 QPoint start;
182 QPoint verticalGradBottom;
183 if (leftToRight) {
184 start = optRect.topLeft();
185 verticalGradBottom = optRect.topLeft();
186 } else {
187 start = optRect.topRight();
188 verticalGradBottom = optRect.topRight();
189 }
190 start.ry() += 3;
191 verticalGradBottom.ry() += optRect.height() - 3;
192 QLinearGradient gradient(start, verticalGradBottom);
193 gradient.setColorAt(pos: 0, color: outlineColor);
194 gradient.setColorAt(pos: 1, color: option.palette.base().color());
195 painter->fillRect(QRect(start, QSize(1, optRect.height() - 3)), gradient);
196 }
197 // END: left vertical line
198
199 // BEGIN: horizontal line
200 {
201 QPoint start;
202 QPoint horizontalGradTop;
203 if (leftToRight) {
204 start = optRect.topLeft();
205 horizontalGradTop = optRect.topLeft();
206 start.rx() += 3;
207 horizontalGradTop.rx() += optRect.width() - 3;
208 } else {
209 start = optRect.topRight();
210 horizontalGradTop = optRect.topRight();
211 start.rx() -= 3;
212 horizontalGradTop.rx() -= optRect.width() - 3;
213 }
214 QLinearGradient gradient(start, horizontalGradTop);
215 gradient.setColorAt(pos: 0, color: outlineColor);
216 gradient.setColorAt(pos: 1, color: option.palette.base().color());
217 QSize rectSize;
218 if (leftToRight) {
219 rectSize = QSize(optRect.width() - 3, 1);
220 } else {
221 rectSize = QSize(-optRect.width() + 3, 1);
222 }
223 painter->fillRect(QRect(start, rectSize), gradient);
224 }
225 // END: horizontal line
226
227 // BEGIN: draw text
228 {
229 const QString category = index.model()->data(index, role: Qt::DisplayRole).toString(); // KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString();
230 QRect textRect = QRect(option.rect.topLeft(), QSize(option.rect.width() - 2 - 3 - 3, height));
231 textRect.setTop(textRect.top() + 2 + 3 /* corner */);
232 textRect.setLeft(textRect.left() + 2 + 3 /* corner */ + 3 /* a bit of margin */);
233 painter->save();
234 painter->setFont(font);
235 QColor penColor(option.palette.text().color());
236 penColor.setAlphaF(0.6);
237 painter->setPen(penColor);
238 painter->drawText(r: textRect, flags: Qt::AlignLeft | Qt::AlignTop, text: category);
239 painter->restore();
240 }
241 // END: draw text
242}
243
244int KateCategoryDrawer::categoryHeight(const QModelIndex &index, const QStyleOption &option) const
245{
246 Q_UNUSED(index);
247 Q_UNUSED(option);
248
249 QFont font(QApplication::font());
250 font.setBold(true);
251 const QFontMetrics fontMetrics = QFontMetrics(font);
252
253 return fontMetrics.height() + 2 + 12 /* vertical spacing */;
254}
255
256int KateCategoryDrawer::leftMargin() const
257{
258 return 7;
259}
260
261int KateCategoryDrawer::rightMargin() const
262{
263 return 7;
264}
265

source code of ktexteditor/src/syntax/katecategorydrawer.cpp