File indexing completed on 2024-05-12 05:38:57
0001 /* SPDX-FileCopyrightText: 2020 Noah Davis <noahadvs@gmail.com> 0002 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0003 */ 0004 0005 #include "paintedsymbolitem.h" 0006 #include "paintedsymbolitem_p.h" 0007 #include <QGuiApplication> 0008 #include <QPainter> 0009 0010 PaintedSymbolItem::PaintedSymbolItem(QQuickItem *parent) 0011 : QQuickPaintedItem(parent) 0012 , d_ptr(new PaintedSymbolItemPrivate(this)) 0013 { 0014 Q_D(PaintedSymbolItem); 0015 connect(qGuiApp, &QGuiApplication::fontChanged, this, [this, d]() { 0016 d->fontMetrics = QFontMetricsF(QGuiApplication::font()); 0017 update(); 0018 }); 0019 d->targetSymbolSize = d->fontMetrics.height() + std::fmod(d->fontMetrics.height(), 2.0); 0020 d->targetSymbolSize -= std::fmod(d->targetSymbolSize, 6.0); 0021 d->targetSymbolSize -= d->targetSymbolSize / 3.0; 0022 setImplicitSize(d->targetSymbolSize, d->fontMetrics.height()); 0023 setBaselineOffset(d->fontMetrics.ascent()); 0024 } 0025 0026 PaintedSymbolItem::~PaintedSymbolItem() noexcept 0027 { 0028 } 0029 0030 void PaintedSymbolItem::paint(QPainter *painter) 0031 { 0032 Q_D(PaintedSymbolItem); 0033 // Do I need to save() and restore() if I change the painter in the switch blocks? 0034 switch (d->symbolType) { 0035 case SymbolType::Checkmark: { 0036 setPenWidth(2); 0037 qreal penOffset = d->penWidth / 2; 0038 0039 // Prevent the sides from being cut off. Remember to add extra width and height externally. 0040 qreal width = this->width() - d->penWidth * 2; 0041 qreal height = this->height() - d->penWidth * 2; 0042 0043 // No point in trying to draw if it's too small 0044 if (std::min(width, height) <= 0) { 0045 return; 0046 } 0047 0048 painter->translate(d->penWidth, d->penWidth); 0049 0050 painter->setBrush(Qt::NoBrush); 0051 painter->setPen(d->pen); 0052 painter->setRenderHint(QPainter::Antialiasing); 0053 0054 QList<QPointF> points = { 0055 QPointF(0 + penOffset, height / 2.0 + penOffset), 0056 QPointF(width / 3.0, height / 1.2), // height * (5/6) 0057 QPointF(width - penOffset, height / 6.0 + penOffset), 0058 }; 0059 painter->drawPolyline(points); 0060 0061 } break; 0062 case SymbolType::LeftArrow: { 0063 setPenWidth(1); 0064 qreal penOffset = d->penWidth / 2; 0065 0066 // Prevent the sides from being cut off. Remember to add extra width and height externally. 0067 qreal width = this->width() - d->penWidth * 2; 0068 qreal height = this->height() - d->penWidth * 2; 0069 0070 // No point in trying to draw if it's too small 0071 if (std::min(width, height) <= 0) { 0072 return; 0073 } 0074 0075 painter->translate(d->penWidth, d->penWidth); 0076 0077 painter->setBrush(Qt::NoBrush); 0078 painter->setPen(d->pen); 0079 painter->setRenderHint(QPainter::Antialiasing); 0080 0081 QList<QPointF> points = { 0082 QPointF(width / 1.5 - penOffset, 0 + penOffset), 0083 QPointF(width / 4.0, height / 2), 0084 QPointF(width / 1.5 - penOffset, height - penOffset), 0085 }; 0086 painter->drawPolyline(points); 0087 0088 } break; 0089 case SymbolType::RightArrow: { 0090 setPenWidth(1); 0091 // qreal penOffset = d->penWidth / 2; 0092 0093 // Prevent the sides from being cut off. Remember to add extra width and height externally. 0094 qreal width = this->width() - d->penWidth * 2; 0095 qreal height = this->height() - d->penWidth * 2; 0096 0097 // No point in trying to draw if it's too small 0098 if (std::min(width, height) <= 0) { 0099 return; 0100 } 0101 0102 painter->translate(d->penWidth, d->penWidth); 0103 0104 painter->setBrush(Qt::NoBrush); 0105 painter->setPen(d->pen); 0106 painter->setRenderHint(QPainter::Antialiasing); 0107 0108 QList<QPointF> points = { 0109 QPointF(width / 3 /* + penOffset*/, 0 /* + penOffset*/), 0110 QPointF(width * 0.75, height / 2), 0111 QPointF(width / 3 /* + penOffset*/, height /* - penOffset*/), 0112 }; 0113 painter->drawPolyline(points); 0114 0115 } break; 0116 case SymbolType::UpArrow: { 0117 setPenWidth(1); 0118 qreal penOffset = d->penWidth / 2; 0119 0120 // Prevent the sides from being cut off. Remember to add extra width and height externally. 0121 qreal width = this->width() - d->penWidth * 2; 0122 qreal height = this->height() - d->penWidth * 2; 0123 0124 // No point in trying to draw if it's too small 0125 if (std::min(width, height) <= 0) { 0126 return; 0127 } 0128 0129 painter->translate(d->penWidth, d->penWidth + penOffset); 0130 0131 painter->setBrush(Qt::NoBrush); 0132 painter->setPen(d->pen); 0133 painter->setRenderHint(QPainter::Antialiasing); 0134 0135 QList<QPointF> points = { 0136 QPointF(0 - penOffset, height * 0.75), 0137 QPointF(width / 2.0, height / 4 - penOffset), 0138 QPointF(width + penOffset, height * 0.75), 0139 }; 0140 painter->drawPolyline(points); 0141 0142 } break; 0143 case SymbolType::DownArrow: { 0144 setPenWidth(1); 0145 qreal penOffset = d->penWidth / 2; 0146 0147 // Prevent the sides from being cut off. Remember to add extra width and height externally. 0148 qreal width = this->width() - d->penWidth * 2; 0149 qreal height = this->height() - d->penWidth * 2; 0150 0151 // No point in trying to draw if it's too small 0152 if (std::min(width, height) <= 0) { 0153 return; 0154 } 0155 0156 painter->translate(d->penWidth, d->penWidth + penOffset); 0157 0158 painter->setBrush(Qt::NoBrush); 0159 painter->setPen(d->pen); 0160 painter->setRenderHint(QPainter::Antialiasing); 0161 0162 QList<QPointF> points = { 0163 QPointF(0 - penOffset, height / 4), 0164 QPointF(width / 2.0, height * 0.75 + penOffset), 0165 QPointF(width + penOffset, height / 4), 0166 }; 0167 painter->drawPolyline(points); 0168 0169 } break; 0170 default: 0171 break; 0172 } 0173 } 0174 0175 // color 0176 QColor PaintedSymbolItem::color() const 0177 { 0178 Q_D(const PaintedSymbolItem); 0179 return d->color; 0180 } 0181 0182 void PaintedSymbolItem::setColor(const QColor &color) 0183 { 0184 Q_D(PaintedSymbolItem); 0185 if (color == d->color) { 0186 return; 0187 } 0188 0189 d->color = color; 0190 d->pen.setColor(d->color); 0191 update(); 0192 Q_EMIT colorChanged(); 0193 } 0194 0195 // penWidth 0196 qreal PaintedSymbolItem::penWidth() const 0197 { 0198 Q_D(const PaintedSymbolItem); 0199 return d->penWidth; 0200 } 0201 0202 void PaintedSymbolItem::setPenWidth(const qreal penWidth) 0203 { 0204 Q_D(PaintedSymbolItem); 0205 if (penWidth == d->penWidth || (d->penWidth == 1.001 && penWidth == 1)) { 0206 return; 0207 } 0208 0209 d->penWidth = penWidth == 1 ? 1.001 : penWidth; 0210 d->pen.setWidthF(d->penWidth); 0211 Q_EMIT penWidthChanged(); 0212 } 0213 0214 // symbolType 0215 PaintedSymbolItem::SymbolType PaintedSymbolItem::symbolType() const 0216 { 0217 Q_D(const PaintedSymbolItem); 0218 return d->symbolType; 0219 } 0220 0221 void PaintedSymbolItem::setSymbolType(const SymbolType symbolType) 0222 { 0223 Q_D(PaintedSymbolItem); 0224 if (symbolType == d->symbolType) { 0225 return; 0226 } 0227 0228 d->symbolType = symbolType; 0229 update(); 0230 Q_EMIT symbolTypeChanged(); 0231 } 0232 0233 #include "moc_paintedsymbolitem.cpp"