File indexing completed on 2024-05-19 03:49:34
0001 /* 0002 File : TextLabel.h 0003 Project : LabPlot 0004 Description : Text label supporting reach text and latex formatting 0005 -------------------------------------------------------------------- 0006 SPDX-FileCopyrightText: 2009 Tilman Benkert <thzs@gmx.net> 0007 SPDX-FileCopyrightText: 2012-2023 Alexander Semke <alexander.semke@web.de> 0008 SPDX-License-Identifier: GPL-2.0-or-later 0009 */ 0010 0011 #ifndef TEXTLABEL_H 0012 #define TEXTLABEL_H 0013 0014 #include "backend/lib/macros.h" 0015 #include "backend/worksheet/WorksheetElement.h" 0016 #include "tools/TeXRenderer.h" 0017 0018 #include <QTextEdit> 0019 0020 class QBrush; 0021 class QFont; 0022 class TextLabelPrivate; 0023 class CartesianPlot; 0024 class QPen; 0025 0026 class TextLabel : public WorksheetElement { 0027 Q_OBJECT 0028 0029 public: 0030 enum class Type { General, PlotTitle, AxisTitle, PlotLegendTitle, InfoElementLabel }; 0031 enum class Mode { Text, LaTeX, Markdown }; 0032 enum class BorderShape { 0033 NoBorder, 0034 Rect, 0035 Ellipse, 0036 RoundSideRect, 0037 RoundCornerRect, 0038 InwardsRoundCornerRect, 0039 DentedBorderRect, 0040 Cuboid, 0041 UpPointingRectangle, 0042 DownPointingRectangle, 0043 LeftPointingRectangle, 0044 RightPointingRectangle 0045 }; 0046 0047 // The text is always in HMTL format 0048 struct TextWrapper { 0049 TextWrapper() = default; 0050 TextWrapper(const QString& text, TextLabel::Mode mode, bool html) 0051 : mode(mode) { 0052 if (mode == TextLabel::Mode::Text) 0053 this->text = createHtml(text, html); 0054 else // LaTeX and markdown use plain string 0055 this->text = text; 0056 } 0057 TextWrapper(const QString& text) 0058 : mode(TextLabel::Mode::Text) { 0059 // assume text is not HTML yet 0060 this->text = createHtml(text, false); 0061 } 0062 TextWrapper(const QString& text, bool html, QString& placeholder) 0063 : allowPlaceholder(true) 0064 , textPlaceholder(placeholder) { 0065 this->text = createHtml(text, html); 0066 } 0067 TextWrapper(const QString& text, TextLabel::Mode mode, bool html, bool allowPlaceholder) 0068 : allowPlaceholder(allowPlaceholder) { 0069 TextWrapper(text, mode, html); 0070 } 0071 QString createHtml(QString text, bool isHtml) { 0072 if (isHtml || text.isEmpty()) 0073 return text; 0074 0075 QTextEdit te(text); 0076 // the html does not contain any colors! 0077 return te.toHtml(); 0078 } 0079 0080 bool isHtml() const { 0081 return text.startsWith(QStringLiteral("<!DOCTYPE HTML")); 0082 } 0083 0084 bool operator!=(const TextWrapper& other) const { 0085 return (text != other.text || mode != other.mode || allowPlaceholder != other.allowPlaceholder 0086 || ((allowPlaceholder || other.allowPlaceholder) && textPlaceholder != other.textPlaceholder)); 0087 } 0088 0089 bool operator==(TextWrapper& other) const { 0090 return (text == other.text && mode == other.mode && allowPlaceholder == other.allowPlaceholder 0091 && ((allowPlaceholder || other.allowPlaceholder) && textPlaceholder == other.textPlaceholder)); 0092 } 0093 0094 QString text; 0095 TextLabel::Mode mode{TextLabel::Mode::Text}; 0096 /*! Determines if the Textlabel can have a placeholder or not. 0097 * Depending on this variable in the LabelWidget between 0098 * the text and the placeholder text can be switched 0099 */ 0100 bool allowPlaceholder{false}; 0101 QString textPlaceholder{QLatin1String("")}; // text with placeholders 0102 }; 0103 0104 explicit TextLabel(const QString& name, Type = Type::General); 0105 TextLabel(const QString& name, CartesianPlot*, Type = Type::General); 0106 ~TextLabel() override; 0107 0108 Type type() const; 0109 QIcon icon() const override; 0110 0111 void save(QXmlStreamWriter*) const override; 0112 bool load(XmlStreamReader*, bool preview) override; 0113 void loadThemeConfig(const KConfig&) override; 0114 void saveThemeConfig(const KConfig&) override; 0115 0116 CLASS_D_ACCESSOR_DECL(TextWrapper, text, Text) 0117 BASIC_D_ACCESSOR_DECL(QColor, fontColor, FontColor) 0118 BASIC_D_ACCESSOR_DECL(QColor, backgroundColor, BackgroundColor) 0119 CLASS_D_ACCESSOR_DECL(TextWrapper, textPlaceholder, PlaceholderText) 0120 BASIC_D_ACCESSOR_DECL(QColor, teXFontColor, TeXFontColor) 0121 BASIC_D_ACCESSOR_DECL(QColor, teXBackgroundColor, TeXBackgroundColor) 0122 CLASS_D_ACCESSOR_DECL(QFont, teXFont, TeXFont) 0123 0124 BASIC_D_ACCESSOR_DECL(BorderShape, borderShape, BorderShape) 0125 CLASS_D_ACCESSOR_DECL(QPen, borderPen, BorderPen) 0126 BASIC_D_ACCESSOR_DECL(qreal, borderOpacity, BorderOpacity) 0127 0128 void setZoomFactor(double); 0129 QRectF size(); 0130 QPointF findNearestGluePoint(QPointF scenePoint); 0131 int gluePointCount(); 0132 struct GluePoint { 0133 #if (QT_VERSION < QT_VERSION_CHECK(5, 13, 0)) // we need a default constructor for QVector 0134 GluePoint() = default; 0135 #endif 0136 GluePoint(QPointF point, QString name) 0137 : point(point) 0138 , name(name) { 0139 } 0140 QPointF point; 0141 QString name; 0142 }; 0143 0144 GluePoint gluePointAt(int index); 0145 0146 void retransform() override; 0147 void handleResize(double horizontalRatio, double verticalRatio, bool pageResize) override; 0148 0149 typedef TextLabelPrivate Private; 0150 0151 private Q_SLOTS: 0152 void updateTeXImage(); 0153 0154 protected: 0155 TextLabel(const QString& name, TextLabelPrivate*, Type = Type::General); 0156 0157 private: 0158 Q_DECLARE_PRIVATE(TextLabel) 0159 void init(); 0160 0161 Type m_type; 0162 0163 Q_SIGNALS: 0164 void textWrapperChanged(const TextLabel::TextWrapper&); 0165 void teXFontSizeChanged(const int); 0166 void teXFontChanged(const QFont); 0167 void fontColorChanged(const QColor); 0168 void backgroundColorChanged(const QColor); 0169 0170 void borderShapeChanged(TextLabel::BorderShape); 0171 void borderPenChanged(QPen&); 0172 void borderOpacityChanged(float); 0173 0174 void teXImageUpdated(const TeXRenderer::Result&); 0175 }; 0176 0177 #endif