File indexing completed on 2024-04-21 03:57:42
0001 /* 0002 SPDX-FileCopyrightText: 2009 Rafael Fernández López <ereslibre@kde.org> 0003 SPDX-FileCopyrightText: 2013 Dominik Haumann <dhaumann@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "katecategorydrawer.h" 0009 0010 #include <QApplication> 0011 #include <QPainter> 0012 #include <QPainterPath> 0013 #include <QStyleOption> 0014 0015 KateCategoryDrawer::KateCategoryDrawer() 0016 : KCategoryDrawer(nullptr) 0017 { 0018 } 0019 0020 void KateCategoryDrawer::drawCategory(const QModelIndex &index, int sortRole, const QStyleOption &option, QPainter *painter) const 0021 { 0022 Q_UNUSED(sortRole) 0023 0024 painter->setRenderHint(QPainter::Antialiasing); 0025 0026 const QRect optRect = option.rect; 0027 QFont font(QApplication::font()); 0028 font.setBold(true); 0029 const int height = categoryHeight(index, option); 0030 const bool leftToRight = painter->layoutDirection() == Qt::LeftToRight; 0031 0032 // BEGIN: decoration gradient 0033 { 0034 QPainterPath path(optRect.bottomLeft()); 0035 0036 path.lineTo(QPoint(optRect.topLeft().x(), optRect.topLeft().y() - 3)); 0037 const QPointF topLeft(optRect.topLeft()); 0038 QRectF arc(topLeft, QSizeF(4, 4)); 0039 path.arcTo(arc, 180, -90); 0040 path.lineTo(optRect.topRight()); 0041 path.lineTo(optRect.bottomRight()); 0042 path.lineTo(optRect.bottomLeft()); 0043 0044 QColor window(option.palette.window().color()); 0045 const QColor base(option.palette.base().color()); 0046 0047 window.setAlphaF(0.4); 0048 0049 QLinearGradient decoGradient1; 0050 if (leftToRight) { 0051 decoGradient1.setStart(optRect.topLeft()); 0052 decoGradient1.setFinalStop(optRect.bottomLeft()); 0053 } else { 0054 decoGradient1.setStart(optRect.topRight()); 0055 decoGradient1.setFinalStop(optRect.bottomRight()); 0056 } 0057 decoGradient1.setColorAt(0, window); 0058 decoGradient1.setColorAt(1, Qt::transparent); 0059 0060 QLinearGradient decoGradient2; 0061 if (leftToRight) { 0062 decoGradient2.setStart(optRect.topLeft()); 0063 decoGradient2.setFinalStop(optRect.topRight()); 0064 } else { 0065 decoGradient2.setStart(optRect.topRight()); 0066 decoGradient2.setFinalStop(optRect.topLeft()); 0067 } 0068 decoGradient2.setColorAt(0, Qt::transparent); 0069 decoGradient2.setColorAt(1, base); 0070 0071 painter->fillPath(path, decoGradient1); 0072 painter->fillPath(path, decoGradient2); 0073 } 0074 // END: decoration gradient 0075 0076 { 0077 QRect newOptRect(optRect); 0078 0079 if (leftToRight) { 0080 newOptRect.translate(1, 1); 0081 } else { 0082 newOptRect.translate(-1, 1); 0083 } 0084 0085 // BEGIN: inner top left corner 0086 { 0087 painter->save(); 0088 painter->setPen(option.palette.base().color()); 0089 QRectF arc; 0090 if (leftToRight) { 0091 const QPointF topLeft(newOptRect.topLeft()); 0092 arc = QRectF(topLeft, QSizeF(4, 4)); 0093 arc.translate(0.5, 0.5); 0094 painter->drawArc(arc, 1440, 1440); 0095 } else { 0096 QPointF topRight(newOptRect.topRight()); 0097 topRight.rx() -= 4; 0098 arc = QRectF(topRight, QSizeF(4, 4)); 0099 arc.translate(-0.5, 0.5); 0100 painter->drawArc(arc, 0, 1440); 0101 } 0102 painter->restore(); 0103 } 0104 // END: inner top left corner 0105 0106 // BEGIN: inner left vertical line 0107 { 0108 QPoint start; 0109 QPoint verticalGradBottom; 0110 if (leftToRight) { 0111 start = newOptRect.topLeft(); 0112 verticalGradBottom = newOptRect.topLeft(); 0113 } else { 0114 start = newOptRect.topRight(); 0115 verticalGradBottom = newOptRect.topRight(); 0116 } 0117 start.ry() += 3; 0118 verticalGradBottom.ry() += newOptRect.height() - 3; 0119 QLinearGradient gradient(start, verticalGradBottom); 0120 gradient.setColorAt(0, option.palette.base().color()); 0121 gradient.setColorAt(1, Qt::transparent); 0122 painter->fillRect(QRect(start, QSize(1, newOptRect.height() - 3)), gradient); 0123 } 0124 // END: inner left vertical line 0125 0126 // BEGIN: inner horizontal line 0127 { 0128 QPoint start; 0129 QPoint horizontalGradTop; 0130 if (leftToRight) { 0131 start = newOptRect.topLeft(); 0132 horizontalGradTop = newOptRect.topLeft(); 0133 start.rx() += 3; 0134 horizontalGradTop.rx() += newOptRect.width() - 3; 0135 } else { 0136 start = newOptRect.topRight(); 0137 horizontalGradTop = newOptRect.topRight(); 0138 start.rx() -= 3; 0139 horizontalGradTop.rx() -= newOptRect.width() - 3; 0140 } 0141 QLinearGradient gradient(start, horizontalGradTop); 0142 gradient.setColorAt(0, option.palette.base().color()); 0143 gradient.setColorAt(1, Qt::transparent); 0144 QSize rectSize; 0145 if (leftToRight) { 0146 rectSize = QSize(newOptRect.width() - 3, 1); 0147 } else { 0148 rectSize = QSize(-newOptRect.width() + 3, 1); 0149 } 0150 painter->fillRect(QRect(start, rectSize), gradient); 0151 } 0152 // END: inner horizontal line 0153 } 0154 0155 QColor outlineColor = option.palette.text().color(); 0156 outlineColor.setAlphaF(0.35); 0157 0158 // BEGIN: top left corner 0159 { 0160 painter->save(); 0161 painter->setPen(outlineColor); 0162 QRectF arc; 0163 if (leftToRight) { 0164 const QPointF topLeft(optRect.topLeft()); 0165 arc = QRectF(topLeft, QSizeF(4, 4)); 0166 arc.translate(0.5, 0.5); 0167 painter->drawArc(arc, 1440, 1440); 0168 } else { 0169 QPointF topRight(optRect.topRight()); 0170 topRight.rx() -= 4; 0171 arc = QRectF(topRight, QSizeF(4, 4)); 0172 arc.translate(-0.5, 0.5); 0173 painter->drawArc(arc, 0, 1440); 0174 } 0175 painter->restore(); 0176 } 0177 // END: top left corner 0178 0179 // BEGIN: left vertical line 0180 { 0181 QPoint start; 0182 QPoint verticalGradBottom; 0183 if (leftToRight) { 0184 start = optRect.topLeft(); 0185 verticalGradBottom = optRect.topLeft(); 0186 } else { 0187 start = optRect.topRight(); 0188 verticalGradBottom = optRect.topRight(); 0189 } 0190 start.ry() += 3; 0191 verticalGradBottom.ry() += optRect.height() - 3; 0192 QLinearGradient gradient(start, verticalGradBottom); 0193 gradient.setColorAt(0, outlineColor); 0194 gradient.setColorAt(1, option.palette.base().color()); 0195 painter->fillRect(QRect(start, QSize(1, optRect.height() - 3)), gradient); 0196 } 0197 // END: left vertical line 0198 0199 // BEGIN: horizontal line 0200 { 0201 QPoint start; 0202 QPoint horizontalGradTop; 0203 if (leftToRight) { 0204 start = optRect.topLeft(); 0205 horizontalGradTop = optRect.topLeft(); 0206 start.rx() += 3; 0207 horizontalGradTop.rx() += optRect.width() - 3; 0208 } else { 0209 start = optRect.topRight(); 0210 horizontalGradTop = optRect.topRight(); 0211 start.rx() -= 3; 0212 horizontalGradTop.rx() -= optRect.width() - 3; 0213 } 0214 QLinearGradient gradient(start, horizontalGradTop); 0215 gradient.setColorAt(0, outlineColor); 0216 gradient.setColorAt(1, option.palette.base().color()); 0217 QSize rectSize; 0218 if (leftToRight) { 0219 rectSize = QSize(optRect.width() - 3, 1); 0220 } else { 0221 rectSize = QSize(-optRect.width() + 3, 1); 0222 } 0223 painter->fillRect(QRect(start, rectSize), gradient); 0224 } 0225 // END: horizontal line 0226 0227 // BEGIN: draw text 0228 { 0229 const QString category = index.model()->data(index, Qt::DisplayRole).toString(); // KCategorizedSortFilterProxyModel::CategoryDisplayRole).toString(); 0230 QRect textRect = QRect(option.rect.topLeft(), QSize(option.rect.width() - 2 - 3 - 3, height)); 0231 textRect.setTop(textRect.top() + 2 + 3 /* corner */); 0232 textRect.setLeft(textRect.left() + 2 + 3 /* corner */ + 3 /* a bit of margin */); 0233 painter->save(); 0234 painter->setFont(font); 0235 QColor penColor(option.palette.text().color()); 0236 penColor.setAlphaF(0.6); 0237 painter->setPen(penColor); 0238 painter->drawText(textRect, Qt::AlignLeft | Qt::AlignTop, category); 0239 painter->restore(); 0240 } 0241 // END: draw text 0242 } 0243 0244 int KateCategoryDrawer::categoryHeight(const QModelIndex &index, const QStyleOption &option) const 0245 { 0246 Q_UNUSED(index); 0247 Q_UNUSED(option); 0248 0249 QFont font(QApplication::font()); 0250 font.setBold(true); 0251 const QFontMetrics fontMetrics = QFontMetrics(font); 0252 0253 return fontMetrics.height() + 2 + 12 /* vertical spacing */; 0254 } 0255 0256 int KateCategoryDrawer::leftMargin() const 0257 { 0258 return 7; 0259 } 0260 0261 int KateCategoryDrawer::rightMargin() const 0262 { 0263 return 7; 0264 }