1 | // Copyright (C) 2016 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QQUICKTEXTEDIT_P_P_H |
5 | #define QQUICKTEXTEDIT_P_P_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists purely as an |
12 | // implementation detail. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include "qquicktextedit_p.h" |
19 | #include "qquickimplicitsizeitem_p_p.h" |
20 | #include "qquicktextutil_p.h" |
21 | |
22 | #include <QtQuick/private/qquicktextselection_p.h> |
23 | |
24 | #include <QtQml/qqml.h> |
25 | #include <QtCore/qlist.h> |
26 | #include <private/qlazilyallocated_p.h> |
27 | #include <private/qquicktextdocument_p.h> |
28 | |
29 | #if QT_CONFIG(accessibility) |
30 | #include <QtGui/qaccessible.h> |
31 | #endif |
32 | |
33 | #include <limits> |
34 | |
35 | QT_BEGIN_NAMESPACE |
36 | class QTextLayout; |
37 | class QQuickPixmap; |
38 | class QQuickTextControl; |
39 | class QSGInternalTextNode; |
40 | class QQuickTextNodeEngine; |
41 | |
42 | class Q_QUICK_EXPORT QQuickTextEditPrivate : public QQuickImplicitSizeItemPrivate |
43 | #if QT_CONFIG(accessibility) |
44 | , public QAccessible::ActivationObserver |
45 | #endif |
46 | { |
47 | public: |
48 | Q_DECLARE_PUBLIC(QQuickTextEdit) |
49 | |
50 | typedef QQuickTextEdit Public; |
51 | |
52 | struct Node { |
53 | explicit Node(int startPos = std::numeric_limits<int>::max(), |
54 | QSGInternalTextNode *node = nullptr) |
55 | : m_node(node), m_startPos(startPos) { } |
56 | QSGInternalTextNode *textNode() const { return m_node; } |
57 | void moveStartPos(int delta) { Q_ASSERT(m_startPos + delta > 0); m_startPos += delta; } |
58 | int startPos() const { return m_startPos; } |
59 | void setDirty() { m_dirty = true; } |
60 | bool dirty() const { return m_dirty; } |
61 | |
62 | private: |
63 | QSGInternalTextNode *m_node; |
64 | int m_startPos; |
65 | bool m_dirty = false; |
66 | |
67 | #ifndef QT_NO_DEBUG_STREAM |
68 | friend QDebug Q_QUICK_EXPORT operator<<(QDebug, const Node &); |
69 | #endif |
70 | }; |
71 | typedef QList<Node>::iterator TextNodeIterator; |
72 | |
73 | struct { |
74 | (); |
75 | |
76 | qreal = 0; |
77 | qreal = 0; |
78 | qreal = 0; |
79 | qreal = 0; |
80 | qreal = 0; |
81 | bool : 1; |
82 | bool : 1; |
83 | bool : 1; |
84 | bool : 1; |
85 | bool : 1; |
86 | }; |
87 | QLazilyAllocated<ExtraData> ; |
88 | |
89 | |
90 | QQuickTextEditPrivate() |
91 | : dirty(false), richText(false), cursorVisible(false), cursorPending(false) |
92 | , focusOnPress(true), persistentSelection(false), requireImplicitWidth(false) |
93 | , selectByMouse(true), canPaste(false), canPasteValid(false), hAlignImplicit(true) |
94 | , textCached(true), inLayout(false), selectByKeyboard(false), selectByKeyboardSet(false) |
95 | , hadSelection(false), markdownText(false), inResize(false), ownsDocument(false) |
96 | , containsUnscalableGlyphs(false) |
97 | { |
98 | #if QT_CONFIG(accessibility) |
99 | QAccessible::installActivationObserver(this); |
100 | #endif |
101 | } |
102 | |
103 | ~QQuickTextEditPrivate() |
104 | { |
105 | #if QT_CONFIG(accessibility) |
106 | QAccessible::removeActivationObserver(this); |
107 | #endif |
108 | } |
109 | |
110 | static QQuickTextEditPrivate *get(QQuickTextEdit *item) { |
111 | return static_cast<QQuickTextEditPrivate *>(QObjectPrivate::get(o: item)); } |
112 | |
113 | void init(); |
114 | |
115 | void resetInputMethod(); |
116 | void updateDefaultTextOption(); |
117 | void onDocumentStatusChanged(); |
118 | void relayoutDocument(); |
119 | bool determineHorizontalAlignment(); |
120 | bool setHAlign(QQuickTextEdit::HAlignment, bool forceAlign = false); |
121 | void mirrorChange() override; |
122 | bool transformChanged(QQuickItem *transformedItem) override; |
123 | qreal getImplicitWidth() const override; |
124 | Qt::LayoutDirection textDirection(const QString &text) const; |
125 | bool isLinkHoveredConnected(); |
126 | |
127 | #if QT_CONFIG(cursor) |
128 | void updateMouseCursorShape(); |
129 | #endif |
130 | |
131 | void setNativeCursorEnabled(bool) {} |
132 | void handleFocusEvent(QFocusEvent *event); |
133 | void addCurrentTextNodeToRoot(QQuickTextNodeEngine *, QSGTransformNode *, QSGInternalTextNode *, TextNodeIterator&, int startPos); |
134 | QSGInternalTextNode* createTextNode(); |
135 | |
136 | #if QT_CONFIG(im) |
137 | Qt::InputMethodHints effectiveInputMethodHints() const; |
138 | #endif |
139 | |
140 | #if QT_CONFIG(accessibility) |
141 | void accessibilityActiveChanged(bool active) override; |
142 | QAccessible::Role accessibleRole() const override; |
143 | #endif |
144 | |
145 | inline qreal padding() const { return extra.isAllocated() ? extra->padding : 0.0; } |
146 | void setTopPadding(qreal value, bool reset = false); |
147 | void setLeftPadding(qreal value, bool reset = false); |
148 | void setRightPadding(qreal value, bool reset = false); |
149 | void setBottomPadding(qreal value, bool reset = false); |
150 | |
151 | bool isImplicitResizeEnabled() const; |
152 | void setImplicitResizeEnabled(bool enabled); |
153 | |
154 | QColor color = QRgb(0xFF000000); |
155 | QColor selectionColor = QRgb(0xFF000080); |
156 | QColor selectedTextColor = QRgb(0xFFFFFFFF); |
157 | |
158 | QSizeF contentSize; |
159 | |
160 | qreal textMargin = 0; |
161 | qreal xoff = 0; |
162 | qreal yoff = 0; |
163 | |
164 | QString text; |
165 | QUrl baseUrl; |
166 | QFont sourceFont; |
167 | QFont font; |
168 | |
169 | QQmlComponent* cursorComponent = nullptr; |
170 | QQuickItem* cursorItem = nullptr; |
171 | QTextDocument *document = nullptr; |
172 | QQuickTextControl *control = nullptr; |
173 | QQuickTextDocument *quickDocument = nullptr; |
174 | mutable QQuickTextSelection *cursorSelection = nullptr; |
175 | QList<Node> textNodeMap; |
176 | QList<QQuickPixmap *> pixmapsInProgress; |
177 | |
178 | int lastSelectionStart = 0; |
179 | int lastSelectionEnd = 0; |
180 | int lineCount = 0; |
181 | int firstBlockInViewport = -1; // can be wrong after scrolling sometimes |
182 | int firstBlockPastViewport = -1; // only for the autotest |
183 | int renderedBlockCount = -1; // only for the autotest |
184 | QRectF renderedRegion; |
185 | |
186 | enum UpdateType { |
187 | UpdateNone, |
188 | UpdateOnlyPreprocess, |
189 | UpdatePaintNode, |
190 | UpdateAll |
191 | }; |
192 | |
193 | QQuickTextEdit::HAlignment hAlign = QQuickTextEdit::AlignLeft; |
194 | QQuickTextEdit::VAlignment vAlign = QQuickTextEdit::AlignTop; |
195 | QQuickTextEdit::TextFormat format = QQuickTextEdit::PlainText; |
196 | QQuickTextEdit::WrapMode wrapMode = QQuickTextEdit::NoWrap; |
197 | QQuickTextEdit::RenderType renderType = QQuickTextUtil::textRenderType<QQuickTextEdit>(); |
198 | Qt::LayoutDirection contentDirection = Qt::LayoutDirectionAuto; |
199 | QQuickTextEdit::SelectionMode mouseSelectionMode = QQuickTextEdit::SelectCharacters; |
200 | #if QT_CONFIG(im) |
201 | Qt::InputMethodHints inputMethodHints = Qt::ImhNone; |
202 | #endif |
203 | UpdateType updateType = UpdatePaintNode; |
204 | |
205 | bool dirty : 1; |
206 | bool richText : 1; |
207 | bool cursorVisible : 1; |
208 | bool cursorPending : 1; |
209 | bool focusOnPress : 1; |
210 | bool persistentSelection : 1; |
211 | bool requireImplicitWidth:1; |
212 | bool selectByMouse:1; |
213 | bool canPaste:1; |
214 | bool canPasteValid:1; |
215 | bool hAlignImplicit:1; |
216 | bool textCached:1; |
217 | bool inLayout:1; |
218 | bool selectByKeyboard:1; |
219 | bool selectByKeyboardSet:1; |
220 | bool hadSelection : 1; |
221 | bool markdownText : 1; |
222 | bool inResize : 1; |
223 | bool ownsDocument : 1; |
224 | bool containsUnscalableGlyphs : 1; |
225 | |
226 | static const int largeTextSizeThreshold; |
227 | }; |
228 | |
229 | #ifndef QT_NO_DEBUG_STREAM |
230 | QDebug Q_QUICK_EXPORT operator<<(QDebug debug, const QQuickTextEditPrivate::Node &); |
231 | #endif |
232 | |
233 | QT_END_NAMESPACE |
234 | |
235 | #endif // QQUICKTEXTEDIT_P_P_H |
236 | |