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 }