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 | { |
33 | QRect newOptRect(optRect); |
34 | |
35 | if (leftToRight) { |
36 | newOptRect.translate(dx: 1, dy: 1); |
37 | } else { |
38 | newOptRect.translate(dx: -1, dy: 1); |
39 | } |
40 | |
41 | // BEGIN: inner top left corner |
42 | { |
43 | painter->save(); |
44 | painter->setPen(option.palette.base().color()); |
45 | QRectF arc; |
46 | if (leftToRight) { |
47 | const QPointF topLeft(newOptRect.topLeft()); |
48 | arc = QRectF(topLeft, QSizeF(4, 4)); |
49 | arc.translate(dx: 0.5, dy: 0.5); |
50 | painter->drawArc(rect: arc, a: 1440, alen: 1440); |
51 | } else { |
52 | QPointF topRight(newOptRect.topRight()); |
53 | topRight.rx() -= 4; |
54 | arc = QRectF(topRight, QSizeF(4, 4)); |
55 | arc.translate(dx: -0.5, dy: 0.5); |
56 | painter->drawArc(rect: arc, a: 0, alen: 1440); |
57 | } |
58 | painter->restore(); |
59 | } |
60 | // END: inner top left corner |
61 | |
62 | // BEGIN: inner left vertical line |
63 | { |
64 | QPoint start; |
65 | QPoint verticalGradBottom; |
66 | if (leftToRight) { |
67 | start = newOptRect.topLeft(); |
68 | verticalGradBottom = newOptRect.topLeft(); |
69 | } else { |
70 | start = newOptRect.topRight(); |
71 | verticalGradBottom = newOptRect.topRight(); |
72 | } |
73 | start.ry() += 3; |
74 | verticalGradBottom.ry() += newOptRect.height() - 3; |
75 | QLinearGradient gradient(start, verticalGradBottom); |
76 | gradient.setColorAt(pos: 0, color: option.palette.base().color()); |
77 | gradient.setColorAt(pos: 1, color: Qt::transparent); |
78 | painter->fillRect(QRect(start, QSize(1, newOptRect.height() - 3)), gradient); |
79 | } |
80 | // END: inner left vertical line |
81 | |
82 | // BEGIN: inner horizontal line |
83 | { |
84 | QPoint start; |
85 | QPoint horizontalGradTop; |
86 | if (leftToRight) { |
87 | start = newOptRect.topLeft(); |
88 | horizontalGradTop = newOptRect.topLeft(); |
89 | start.rx() += 3; |
90 | horizontalGradTop.rx() += newOptRect.width() - 3; |
91 | } else { |
92 | start = newOptRect.topRight(); |
93 | horizontalGradTop = newOptRect.topRight(); |
94 | start.rx() -= 3; |
95 | horizontalGradTop.rx() -= newOptRect.width() - 3; |
96 | } |
97 | QLinearGradient gradient(start, horizontalGradTop); |
98 | gradient.setColorAt(pos: 0, color: option.palette.base().color()); |
99 | gradient.setColorAt(pos: 1, color: Qt::transparent); |
100 | QSize rectSize; |
101 | if (leftToRight) { |
102 | rectSize = QSize(newOptRect.width() - 3, 1); |
103 | } else { |
104 | rectSize = QSize(-newOptRect.width() + 3, 1); |
105 | } |
106 | painter->fillRect(QRect(start, rectSize), gradient); |
107 | } |
108 | // END: inner horizontal line |
109 | } |
110 | |
111 | QColor outlineColor = option.palette.text().color(); |
112 | outlineColor.setAlphaF(0.35); |
113 | |
114 | // BEGIN: top left corner |
115 | { |
116 | painter->save(); |
117 | painter->setPen(outlineColor); |
118 | QRectF arc; |
119 | if (leftToRight) { |
120 | const QPointF topLeft(optRect.topLeft()); |
121 | arc = QRectF(topLeft, QSizeF(4, 4)); |
122 | arc.translate(dx: 0.5, dy: 0.5); |
123 | painter->drawArc(rect: arc, a: 1440, alen: 1440); |
124 | } else { |
125 | QPointF topRight(optRect.topRight()); |
126 | topRight.rx() -= 4; |
127 | arc = QRectF(topRight, QSizeF(4, 4)); |
128 | arc.translate(dx: -0.5, dy: 0.5); |
129 | painter->drawArc(rect: arc, a: 0, alen: 1440); |
130 | } |
131 | painter->restore(); |
132 | } |
133 | // END: top left corner |
134 | |
135 | // BEGIN: left vertical line |
136 | { |
137 | QPoint start; |
138 | QPoint verticalGradBottom; |
139 | if (leftToRight) { |
140 | start = optRect.topLeft(); |
141 | verticalGradBottom = optRect.topLeft(); |
142 | } else { |
143 | start = optRect.topRight(); |
144 | verticalGradBottom = optRect.topRight(); |
145 | } |
146 | start.ry() += 3; |
147 | verticalGradBottom.ry() += optRect.height() - 3; |
148 | QLinearGradient gradient(start, verticalGradBottom); |
149 | gradient.setColorAt(pos: 0, color: outlineColor); |
150 | gradient.setColorAt(pos: 1, color: option.palette.base().color()); |
151 | painter->fillRect(QRect(start, QSize(1, optRect.height() - 3)), gradient); |
152 | } |
153 | // END: left vertical line |
154 | |
155 | // BEGIN: horizontal line |
156 | { |
157 | QPoint start; |
158 | QPoint horizontalGradTop; |
159 | if (leftToRight) { |
160 | start = optRect.topLeft(); |
161 | horizontalGradTop = optRect.topLeft(); |
162 | start.rx() += 3; |
163 | horizontalGradTop.rx() += optRect.width() - 3; |
164 | } else { |
165 | start = optRect.topRight(); |
166 | horizontalGradTop = optRect.topRight(); |
167 | start.rx() -= 3; |
168 | horizontalGradTop.rx() -= optRect.width() - 3; |
169 | } |
170 | QLinearGradient gradient(start, horizontalGradTop); |
171 | gradient.setColorAt(pos: 0, color: outlineColor); |
172 | gradient.setColorAt(pos: 1, color: option.palette.base().color()); |
173 | QSize rectSize; |
174 | if (leftToRight) { |
175 | rectSize = QSize(optRect.width() - 3, 1); |
176 | } else { |
177 | rectSize = QSize(-optRect.width() + 3, 1); |
178 | } |
179 | painter->fillRect(QRect(start, rectSize), gradient); |
180 | } |
181 | // END: horizontal line |
182 | |
183 | // BEGIN: draw text |
184 | { |
185 | const QString category = index.model()->data(index, role: Qt::DisplayRole).toString(); // KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString(); |
186 | QRect textRect = QRect(option.rect.topLeft(), QSize(option.rect.width() - 2 - 3 - 3, height)); |
187 | textRect.setTop(textRect.top() + 2 + 3 /* corner */); |
188 | textRect.setLeft(textRect.left() + 2 + 3 /* corner */ + 3 /* a bit of margin */); |
189 | painter->save(); |
190 | painter->setFont(font); |
191 | QColor penColor(option.palette.text().color()); |
192 | penColor.setAlphaF(0.6); |
193 | painter->setPen(penColor); |
194 | painter->drawText(r: textRect, flags: Qt::AlignLeft | Qt::AlignTop, text: category); |
195 | painter->restore(); |
196 | } |
197 | // END: draw text |
198 | } |
199 | |
200 | int KateCategoryDrawer::categoryHeight(const QModelIndex &index, const QStyleOption &option) const |
201 | { |
202 | Q_UNUSED(index); |
203 | Q_UNUSED(option); |
204 | |
205 | QFont font(QApplication::font()); |
206 | font.setBold(true); |
207 | const QFontMetrics fontMetrics = QFontMetrics(font); |
208 | |
209 | return fontMetrics.height() + 2 + 12 /* vertical spacing */; |
210 | } |
211 | |
212 | int KateCategoryDrawer::leftMargin() const |
213 | { |
214 | return 7; |
215 | } |
216 | |
217 | int KateCategoryDrawer::rightMargin() const |
218 | { |
219 | return 7; |
220 | } |
221 | |