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 | |
15 | KateCategoryDrawer::KateCategoryDrawer() |
16 | : KCategoryDrawer(nullptr) |
17 | { |
18 | } |
19 | |
20 | void 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 | |
244 | int 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 | |
256 | int KateCategoryDrawer::leftMargin() const |
257 | { |
258 | return 7; |
259 | } |
260 | |
261 | int KateCategoryDrawer::rightMargin() const |
262 | { |
263 | return 7; |
264 | } |
265 | |