Diffstat (limited to 'noncore/apps/opie-write/qtextedit.cpp') (more/less context) (show whitespace changes)
-rw-r--r-- | noncore/apps/opie-write/qtextedit.cpp | 1375 |
1 files changed, 727 insertions, 648 deletions
diff --git a/noncore/apps/opie-write/qtextedit.cpp b/noncore/apps/opie-write/qtextedit.cpp index 9c5ea79..82401c6 100644 --- a/noncore/apps/opie-write/qtextedit.cpp +++ b/noncore/apps/opie-write/qtextedit.cpp | |||
@@ -45,174 +45,203 @@ | |||
45 | #include "qfont.h" | 45 | #include "qfont.h" |
46 | #include "qcolor.h" | 46 | #include "qcolor.h" |
47 | #include "qstyle.h" | 47 | #include "qstyle.h" |
48 | #include "qsize.h" | 48 | #include "qsize.h" |
49 | #include "qevent.h" | 49 | #include "qevent.h" |
50 | #include "qtimer.h" | 50 | #include "qtimer.h" |
51 | #include "qapplication.h" | 51 | #include "qapplication.h" |
52 | #include "qlistbox.h" | 52 | #include "qlistbox.h" |
53 | #include "qvbox.h" | 53 | #include "qvbox.h" |
54 | #include "qapplication.h" | 54 | #include "qapplication.h" |
55 | #include "qclipboard.h" | 55 | #include "qclipboard.h" |
56 | #include "qcolordialog.h" | 56 | #include "qcolordialog.h" |
57 | #include "qfontdialog.h" | 57 | #include "qfontdialog.h" |
58 | #include "qstylesheet.h" | 58 | #include "qstylesheet.h" |
59 | #include "qdragobject.h" | 59 | #include "qdragobject.h" |
60 | #include "qurl.h" | 60 | #include "qurl.h" |
61 | #include "qcursor.h" | 61 | #include "qcursor.h" |
62 | #include "qregexp.h" | 62 | #include "qregexp.h" |
63 | #include "qpopupmenu.h" | 63 | #include "qpopupmenu.h" |
64 | 64 | ||
65 | #define ACCEL_KEY(k) "\t" + QString("Ctrl+" #k) | 65 | #define ACCEL_KEY(k) "\t" + QString("Ctrl+" #k) |
66 | 66 | ||
67 | using namespace Qt3; | 67 | using namespace Qt3; |
68 | 68 | ||
69 | static bool qt_enable_richtext_copy = FALSE; | ||
70 | |||
69 | struct QUndoRedoInfoPrivate | 71 | struct QUndoRedoInfoPrivate |
70 | { | 72 | { |
71 | QTextString text; | 73 | QTextString text; |
72 | }; | 74 | }; |
73 | 75 | ||
74 | namespace Qt3 { | 76 | namespace Qt3 { |
75 | 77 | ||
76 | class QTextEditPrivate | 78 | class QTextEditPrivate |
77 | { | 79 | { |
78 | public: | 80 | public: |
79 | QTextEditPrivate() | 81 | QTextEditPrivate() |
80 | :preeditStart(-1),preeditLength(-1),ensureCursorVisibleInShowEvent(FALSE) {} | 82 | :preeditStart(-1),preeditLength(-1),ensureCursorVisibleInShowEvent(FALSE) |
83 | { | ||
84 | for ( int i=0; i<7; i++ ) | ||
85 | id[i] = 0; | ||
86 | } | ||
81 | int id[ 7 ]; | 87 | int id[ 7 ]; |
82 | int preeditStart; | 88 | int preeditStart; |
83 | int preeditLength; | 89 | int preeditLength; |
84 | bool ensureCursorVisibleInShowEvent; | 90 | bool ensureCursorVisibleInShowEvent; |
91 | QString scrollToAnchor; // used to deferr scrollToAnchor() until the show event when we are resized | ||
85 | }; | 92 | }; |
86 | 93 | ||
87 | } | 94 | } |
88 | 95 | ||
89 | static bool block_set_alignment = FALSE; | 96 | static bool block_set_alignment = FALSE; |
90 | 97 | ||
91 | /*! | 98 | /*! |
92 | \class QTextEdit qtextedit.h | 99 | \class QTextEdit qtextedit.h |
93 | \brief The QTextEdit widget provides a sophisticated single-page rich text editor. | 100 | \brief The QTextEdit widget provides a powerful single-page rich text editor. |
94 | 101 | ||
95 | \ingroup basic | 102 | \ingroup basic |
96 | \ingroup text | 103 | \ingroup text |
97 | \mainclass | 104 | \mainclass |
98 | 105 | ||
99 | QTextEdit is an advanced WYSIWYG editor supporting rich text | 106 | \tableofcontents |
100 | formatting. It is optimized to handle large documents and to | 107 | |
101 | respond quickly to user input. | 108 | \section1 Introduction and Concepts |
109 | |||
110 | QTextEdit is an advanced WYSIWYG viewer/editor supporting rich | ||
111 | text formatting using HTML-style tags. It is optimized to handle | ||
112 | large documents and to respond quickly to user input. | ||
113 | |||
114 | QTextEdit has three modes of operation: | ||
115 | \table | ||
116 | \header \i Mode \i Command \i Notes | ||
117 | \row \i Plain Text Editor \i setTextFormat(PlainText) | ||
118 | \i Set text with setText(); text() returns plain text. Text | ||
119 | attributes (e.g. colors) can be set, but plain text is always | ||
120 | returned.<sup>1.</sup> | ||
121 | \row \i Rich Text Editor \i setTextFormat(RichText) | ||
122 | \i Set text with setText(); text() returns rich text. Rich | ||
123 | text editing is fairly limited. You can't set margins or | ||
124 | insert images for example (although you can read and | ||
125 | correctly display files that have margins set and that | ||
126 | include images). This mode is mostly useful for editing small | ||
127 | amounts of rich text. <sup>2.</sup> | ||
128 | \row \i Text Viewer<sup>3.</sup> \i setReadOnly(TRUE) | ||
129 | \i Set text with setText() or append() (which has no undo | ||
130 | history so is faster and uses less memory); text() returns | ||
131 | plain or rich text depending on the textFormat(). This mode | ||
132 | can correctly display a large subset of HTML tags. | ||
133 | \endtable | ||
134 | |||
135 | <sup>1.</sup><small>We do \e not recommend using QTextEdit to | ||
136 | create syntax highlighting editors because the current API is | ||
137 | insufficient for this purpose. We hope to release a more complete | ||
138 | API that will support syntax highlighting in a later | ||
139 | release.</small> | ||
140 | |||
141 | <sup>2.</sup><small>A more complete API that supports setting | ||
142 | margins, images, etc., is planned for a later Qt release.</small> | ||
143 | |||
144 | <sup>3.</sup><small>Qt 3.1 will provide a Log Viewer mode which is | ||
145 | optimised for the fast and memory efficient display of large | ||
146 | amounts of read only text.</small> | ||
147 | |||
148 | We recommend that you always call setTextFormat() to set the mode | ||
149 | you want to use. If you use \c AutoText then setText() and | ||
150 | append() will try to determine whether the text they are given is | ||
151 | plain text or rich text. If you use \c RichText then setText() and | ||
152 | append() will assume that the text they are given is rich text. | ||
153 | insert() simply inserts the text it is given. | ||
102 | 154 | ||
103 | QTextEdit works on paragraphs and characters. A paragraph is a | 155 | QTextEdit works on paragraphs and characters. A paragraph is a |
104 | formatted string which is word-wrapped to fit into the width of | 156 | formatted string which is word-wrapped to fit into the width of |
105 | the widget. A document consists of zero or more paragraphs, | 157 | the widget. By default when reading plain text, two newlines |
106 | indexed from 0. Characters are indexed on a per-paragraph basis, | 158 | signify a paragraph. A document consists of zero or more |
107 | also indexed from 0. The words in the paragraph are aligned in | 159 | paragraphs, indexed from 0. Characters are indexed on a |
108 | accordance with the paragraph's alignment(). Paragraphs are | 160 | per-paragraph basis, also indexed from 0. The words in the |
109 | separated by hard line breaks. Each character within a paragraph | 161 | paragraph are aligned in accordance with the paragraph's |
110 | has its own attributes, for example, font and color. | 162 | alignment(). Paragraphs are separated by hard line breaks. Each |
163 | character within a paragraph has its own attributes, for example, | ||
164 | font and color. | ||
165 | |||
166 | The text edit documentation uses the following concepts: | ||
167 | \list | ||
168 | \i \e{current format} -- | ||
169 | this is the format at the current cursor position, \e and it | ||
170 | is the format of the selected text if any. | ||
171 | \i \e{current paragraph} -- the paragraph which contains the | ||
172 | cursor. | ||
173 | \endlist | ||
111 | 174 | ||
112 | QTextEdit can display images (using QMimeSourceFactory), lists and | 175 | QTextEdit can display images (using QMimeSourceFactory), lists and |
113 | tables. If the text is too large to view within the text edit's | 176 | tables. If the text is too large to view within the text edit's |
114 | viewport, scrollbars will appear. The text edit can load both | 177 | viewport, scrollbars will appear. The text edit can load both |
115 | plain text and HTML files (a subset of HTML 3.2 and 4). The | 178 | plain text and HTML files (a subset of HTML 3.2 and 4). The |
116 | rendering style and the set of valid tags are defined by a | 179 | rendering style and the set of valid tags are defined by a |
117 | styleSheet(). Change the style sheet with \l{setStyleSheet()}; see | 180 | styleSheet(). Custom tags can be created and placed in a custom |
181 | style sheet. Change the style sheet with \l{setStyleSheet()}; see | ||
118 | QStyleSheet for details. The images identified by image tags are | 182 | QStyleSheet for details. The images identified by image tags are |
119 | displayed if they can be interpreted using the text edit's | 183 | displayed if they can be interpreted using the text edit's |
120 | \l{QMimeSourceFactory}; see setMimeSourceFactory(). | 184 | \l{QMimeSourceFactory}; see setMimeSourceFactory(). |
121 | 185 | ||
122 | If you want a text browser with more navigation use QTextBrowser. | 186 | If you want a text browser with more navigation use QTextBrowser. |
123 | If you just need to display a small piece of rich text use QLabel | 187 | If you just need to display a small piece of rich text use QLabel |
124 | or QSimpleRichText. | 188 | or QSimpleRichText. |
125 | 189 | ||
126 | If you create a new QTextEdit, and want to allow the user to edit | 190 | If you create a new QTextEdit, and want to allow the user to edit |
127 | rich text, call setTextFormat(Qt::RichText) to ensure that the | 191 | rich text, call setTextFormat(Qt::RichText) to ensure that the |
128 | text is treated as rich text. (Rich text uses HTML tags to set | 192 | text is treated as rich text. (Rich text uses HTML tags to set |
129 | text formatting attributes. See QStyleSheet for information on the | 193 | text formatting attributes. See QStyleSheet for information on the |
130 | HTML tags that are supported.). If you don't call setTextFormat() | 194 | HTML tags that are supported.). If you don't call setTextFormat() |
131 | explicitly the text edit will guess from the text itself whether | 195 | explicitly the text edit will guess from the text itself whether |
132 | it is rich text or plain text. This means that if the text looks | 196 | it is rich text or plain text. This means that if the text looks |
133 | like HTML or XML it will probably be interpreted as rich text, so | 197 | like HTML or XML it will probably be interpreted as rich text, so |
134 | you should call setTextFormat(Qt::PlainText) to preserve such | 198 | you should call setTextFormat(Qt::PlainText) to preserve such |
135 | text. | 199 | text. |
136 | 200 | ||
137 | The text edit documentation uses the following concepts: | 201 | Note that we do not intend to add a full-featured web browser |
138 | \list | 202 | widget to Qt (because that would easily double Qt's size and only |
139 | \i <i>current format</i> -- | 203 | a few applications would benefit from it). The rich |
140 | this is the format at the current cursor position, \e and it | 204 | text support in Qt is designed to provide a fast, portable and |
141 | is the format of the selected text if any. | 205 | efficient way to add reasonable online help facilities to |
142 | \i <i>current paragraph</i> -- the paragraph which contains the | 206 | applications, and to provide a basis for rich text editors. |
143 | cursor. | 207 | \section1 Using QTextEdit as a Display Widget |
144 | \endlist | 208 | |
209 | QTextEdit can display a large HTML subset, including tables and | ||
210 | images. | ||
145 | 211 | ||
146 | The text is set or replaced using setText() which deletes any | 212 | The text is set or replaced using setText() which deletes any |
147 | existing text and replaces it with the text passed in the | 213 | existing text and replaces it with the text passed in the |
148 | setText() call. Text can be inserted with insert(), paste() and | 214 | setText() call. If you call setText() with legacy HTML (with |
149 | pasteSubType(). Text can also be cut(). The entire text is deleted | 215 | setTextFormat(RichText) in force), and then call text(), the text |
150 | with clear() and the selected text is deleted with | 216 | that is returned may have different markup, but will render the |
151 | removeSelectedText(). Selected (marked) text can also be deleted | 217 | same. Text can be inserted with insert(), paste(), pasteSubType() |
152 | with del() (which will delete the character to the right of the | 218 | and append(). Text that is appended does not go into the undo |
153 | cursor if no text is selected). | 219 | history; this makes append() faster and consumes less memory. Text |
154 | 220 | can also be cut(). The entire text is deleted with clear() and the | |
155 | The current format's attributes are set with setItalic(), | 221 | selected text is deleted with removeSelectedText(). Selected |
156 | setBold(), setUnderline(), setFamily() (font family), | 222 | (marked) text can also be deleted with del() (which will delete |
157 | setPointSize(), setColor() and setCurrentFont(). The current | 223 | the character to the right of the cursor if no text is selected). |
158 | paragraph's style is set with setParagType() and its alignment is | ||
159 | set with setAlignment(). | ||
160 | |||
161 | Use setSelection() to select text. The setSelectionAttributes() | ||
162 | function is used to indicate how selected text should be | ||
163 | displayed. Use hasSelectedText() to find out if any text is | ||
164 | selected. The currently selected text's position is available | ||
165 | using getSelection() and the selected text itself is returned by | ||
166 | selectedText(). The selection can be copied to the clipboard with | ||
167 | copy(), or cut to the clipboard with cut(). It can be deleted with | ||
168 | removeSelectedText(). The entire text can be selected (or | ||
169 | unselected) using selectAll(). QTextEdit supports multiple | ||
170 | selections. Most of the selection functions operate on the default | ||
171 | selection, selection 0. If the user presses a non-selecting key, | ||
172 | e.g. a cursor key without also holding down Shift, all selections | ||
173 | are cleared. | ||
174 | |||
175 | Set and get the position of the cursor with setCursorPosition() | ||
176 | and getCursorPosition() respectively. When the cursor is moved, | ||
177 | the signals currentFontChanged(), currentColorChanged() and | ||
178 | currentAlignmentChanged() are emitted to reflect the font, color | ||
179 | and alignment at the new cursor position. | ||
180 | |||
181 | If the text changes, the textChanged() signal is emitted, and if | ||
182 | the user inserts a new line by pressing Return or Enter, | ||
183 | returnPressed() is emitted. The isModified() function will return | ||
184 | TRUE if the text has been modified. | ||
185 | |||
186 | QTextEdit provides command-based undo and redo. To set the depth | ||
187 | of the command history use setUndoDepth() which defaults to 100 | ||
188 | steps. To undo or redo the last operation call undo() or redo(). | ||
189 | The signals undoAvailable() and redoAvailable() indicate whether | ||
190 | the undo and redo operations can be executed. | ||
191 | |||
192 | The indent() function is used to reindent a paragraph. It is | ||
193 | useful for code editors, for example in <em>Qt Designer</em>'s | ||
194 | code editor \e{Ctrl+I} invokes the indent() function. | ||
195 | 224 | ||
196 | Loading and saving text is achieved using setText() and text(), | 225 | Loading and saving text is achieved using setText() and text(), |
197 | for example: | 226 | for example: |
198 | \code | 227 | \code |
199 | QFile file( fileName ); // Read the text from a file | 228 | QFile file( fileName ); // Read the text from a file |
200 | if ( file.open( IO_ReadOnly ) ) { | 229 | if ( file.open( IO_ReadOnly ) ) { |
201 | QTextStream ts( &file ); | 230 | QTextStream ts( &file ); |
202 | textEdit->setText( ts.read() ); | 231 | textEdit->setText( ts.read() ); |
203 | } | 232 | } |
204 | \endcode | 233 | \endcode |
205 | \code | 234 | \code |
206 | QFile file( fileName ); // Write the text to a file | 235 | QFile file( fileName ); // Write the text to a file |
207 | if ( file.open( IO_WriteOnly ) ) { | 236 | if ( file.open( IO_WriteOnly ) ) { |
208 | QTextStream ts( &file ); | 237 | QTextStream ts( &file ); |
209 | ts << textEdit->text(); | 238 | ts << textEdit->text(); |
210 | textEdit->setModified( FALSE ); | 239 | textEdit->setModified( FALSE ); |
211 | } | 240 | } |
212 | \endcode | 241 | \endcode |
213 | 242 | ||
214 | By default the text edit wraps words at whitespace to fit within | 243 | By default the text edit wraps words at whitespace to fit within |
215 | the text edit widget. The setWordWrap() function is used to | 244 | the text edit widget. The setWordWrap() function is used to |
216 | specify the kind of word wrap you want, or \c NoWrap if you don't | 245 | specify the kind of word wrap you want, or \c NoWrap if you don't |
217 | want any wrapping. Call setWordWrap() to set a fixed pixel width | 246 | want any wrapping. Call setWordWrap() to set a fixed pixel width |
218 | \c FixedPixelWidth, or character column (e.g. 80 column) \c | 247 | \c FixedPixelWidth, or character column (e.g. 80 column) \c |
@@ -222,48 +251,127 @@ static bool block_set_alignment = FALSE; | |||
222 | anywhere with setWrapPolicy(). | 251 | anywhere with setWrapPolicy(). |
223 | 252 | ||
224 | The background color is set differently than other widgets, using | 253 | The background color is set differently than other widgets, using |
225 | setPaper(). You specify a brush style which could be a plain color | 254 | setPaper(). You specify a brush style which could be a plain color |
226 | or a complex pixmap. | 255 | or a complex pixmap. |
227 | 256 | ||
228 | Hypertext links are automatically underlined; this can be changed | 257 | Hypertext links are automatically underlined; this can be changed |
229 | with setLinkUnderline(). The tab stop width is set with | 258 | with setLinkUnderline(). The tab stop width is set with |
230 | setTabStopWidth(). | 259 | setTabStopWidth(). |
231 | 260 | ||
232 | The zoomIn() and zoomOut() functions can be used to resize the | 261 | The zoomIn() and zoomOut() functions can be used to resize the |
233 | text by increasing (decreasing for zoomOut()) the point size used. | 262 | text by increasing (decreasing for zoomOut()) the point size used. |
234 | Images are not affected by the zoom functions. | 263 | Images are not affected by the zoom functions. |
235 | 264 | ||
236 | The lines() function returns the number of lines in the text and | 265 | The lines() function returns the number of lines in the text and |
237 | paragraphs() returns the number of paragraphs. The number of lines | 266 | paragraphs() returns the number of paragraphs. The number of lines |
238 | within a particular paragraph is returned by linesOfParagraph(). | 267 | within a particular paragraph is returned by linesOfParagraph(). |
239 | The length of the entire text in characters is returned by | 268 | The length of the entire text in characters is returned by |
240 | length(). | 269 | length(). |
241 | 270 | ||
242 | You can scroll to an anchor in the text, e.g. \c{<a | 271 | You can scroll to an anchor in the text, e.g. \c{<a |
243 | name="anchor">} with scrollToAnchor(). The find() function can be | 272 | name="anchor">} with scrollToAnchor(). The find() function can be |
244 | used to find and select a given string within the text. | 273 | used to find and select a given string within the text. |
245 | 274 | ||
275 | A read-only QTextEdit provides the same functionality as the | ||
276 | (obsolete) QTextView. (QTextView is still supplied for | ||
277 | compatibility with old code.) | ||
278 | |||
279 | \section2 Read-only key bindings | ||
280 | |||
281 | When QTextEdit is used read-only the key-bindings are limited to | ||
282 | navigation, and text may only be selected with the mouse: | ||
283 | \table | ||
284 | \header \i Keypresses \i Action | ||
285 | \row \i \e{UpArrow} \i Move one line up | ||
286 | \row \i \e{DownArrow} \i Move one line down | ||
287 | \row \i \e{LeftArrow} \i Move one character left | ||
288 | \row \i \e{RightArrow} \i Move one character right | ||
289 | \row \i \e{PageUp} \i Move one (viewport) page up | ||
290 | \row \i \e{PageDown} \i Move one (viewport) page down | ||
291 | \row \i \e{Home} \i Move to the beginning of the text | ||
292 | \row \i \e{End} \i Move to the end of the text | ||
293 | \row \i \e{Shift+Wheel} \i Scroll the page horizontally (the Wheel is the mouse wheel) | ||
294 | \row \i \e{Ctrl+Wheel} \i Zoom the text | ||
295 | \endtable | ||
296 | |||
297 | The text edit may be able to provide some meta-information. For | ||
298 | example, the documentTitle() function will return the text from | ||
299 | within HTML \c{<title>} tags. | ||
300 | |||
301 | The text displayed in a text edit has a \e context. The context is | ||
302 | a path which the text edit's QMimeSourceFactory uses to resolve | ||
303 | the locations of files and images. It is passed to the | ||
304 | mimeSourceFactory() when quering data. (See QTextEdit() and | ||
305 | \l{context()}.) | ||
306 | |||
307 | \section1 Using QTextEdit as an Editor | ||
308 | |||
309 | All the information about using QTextEdit as a display widget also | ||
310 | applies here. | ||
311 | |||
312 | The current format's attributes are set with setItalic(), | ||
313 | setBold(), setUnderline(), setFamily() (font family), | ||
314 | setPointSize(), setColor() and setCurrentFont(). The current | ||
315 | paragraph's alignment is set with setAlignment(). | ||
316 | |||
317 | Use setSelection() to select text. The setSelectionAttributes() | ||
318 | function is used to indicate how selected text should be | ||
319 | displayed. Use hasSelectedText() to find out if any text is | ||
320 | selected. The currently selected text's position is available | ||
321 | using getSelection() and the selected text itself is returned by | ||
322 | selectedText(). The selection can be copied to the clipboard with | ||
323 | copy(), or cut to the clipboard with cut(). It can be deleted with | ||
324 | removeSelectedText(). The entire text can be selected (or | ||
325 | unselected) using selectAll(). QTextEdit supports multiple | ||
326 | selections. Most of the selection functions operate on the default | ||
327 | selection, selection 0. If the user presses a non-selecting key, | ||
328 | e.g. a cursor key without also holding down Shift, all selections | ||
329 | are cleared. | ||
330 | |||
331 | Set and get the position of the cursor with setCursorPosition() | ||
332 | and getCursorPosition() respectively. When the cursor is moved, | ||
333 | the signals currentFontChanged(), currentColorChanged() and | ||
334 | currentAlignmentChanged() are emitted to reflect the font, color | ||
335 | and alignment at the new cursor position. | ||
336 | |||
337 | If the text changes, the textChanged() signal is emitted, and if | ||
338 | the user inserts a new line by pressing Return or Enter, | ||
339 | returnPressed() is emitted. The isModified() function will return | ||
340 | TRUE if the text has been modified. | ||
341 | |||
342 | QTextEdit provides command-based undo and redo. To set the depth | ||
343 | of the command history use setUndoDepth() which defaults to 100 | ||
344 | steps. To undo or redo the last operation call undo() or redo(). | ||
345 | The signals undoAvailable() and redoAvailable() indicate whether | ||
346 | the undo and redo operations can be executed. | ||
347 | |||
348 | The indent() function is used to reindent a paragraph. It is | ||
349 | useful for code editors, for example in <em>Qt Designer</em>'s | ||
350 | code editor \e{Ctrl+I} invokes the indent() function. | ||
351 | |||
352 | \section2 Editing key bindings | ||
353 | |||
246 | The list of key-bindings which are implemented for editing: | 354 | The list of key-bindings which are implemented for editing: |
247 | \table | 355 | \table |
248 | \header \i Keypresses \i Action | 356 | \header \i Keypresses \i Action |
249 | \row \i \e{Backspace} \i Delete the character to the left of the cursor | 357 | \row \i \e{Backspace} \i Delete the character to the left of the cursor |
250 | \row \i \e{Delete} \i Delete the character to the right of the cursor | 358 | \row \i \e{Delete} \i Delete the character to the right of the cursor |
251 | \row \i \e{Ctrl+A} \i Move the cursor to the beginning of the line | 359 | \row \i \e{Ctrl+A} \i Move the cursor to the beginning of the line |
252 | \row \i \e{Ctrl+B} \i Move the cursor one character left | 360 | \row \i \e{Ctrl+B} \i Move the cursor one character left |
253 | \row \i \e{Ctrl+C} \i Copy the marked text to the clipboard (also | 361 | \row \i \e{Ctrl+C} \i Copy the marked text to the clipboard (also |
254 | \e{Ctrl+Insert} under Windows) | 362 | \e{Ctrl+Insert} under Windows) |
255 | \row \i \e{Ctrl+D} \i Delete the character to the right of the cursor | 363 | \row \i \e{Ctrl+D} \i Delete the character to the right of the cursor |
256 | \row \i \e{Ctrl+E} \i Move the cursor to the end of the line | 364 | \row \i \e{Ctrl+E} \i Move the cursor to the end of the line |
257 | \row \i \e{Ctrl+F} \i Move the cursor one character right | 365 | \row \i \e{Ctrl+F} \i Move the cursor one character right |
258 | \row \i \e{Ctrl+H} \i Delete the character to the left of the cursor | 366 | \row \i \e{Ctrl+H} \i Delete the character to the left of the cursor |
259 | \row \i \e{Ctrl+K} \i Delete to end of line | 367 | \row \i \e{Ctrl+K} \i Delete to end of line |
260 | \row \i \e{Ctrl+N} \i Move the cursor one line down | 368 | \row \i \e{Ctrl+N} \i Move the cursor one line down |
261 | \row \i \e{Ctrl+P} \i Move the cursor one line up | 369 | \row \i \e{Ctrl+P} \i Move the cursor one line up |
262 | \row \i \e{Ctrl+V} \i Paste the clipboard text into line edit | 370 | \row \i \e{Ctrl+V} \i Paste the clipboard text into line edit |
263 | (also \e{Shift+Insert} under Windows) | 371 | (also \e{Shift+Insert} under Windows) |
264 | \row \i \e{Ctrl+X} \i Cut the marked text, copy to clipboard | 372 | \row \i \e{Ctrl+X} \i Cut the marked text, copy to clipboard |
265 | (also \e{Shift+Delete} under Windows) | 373 | (also \e{Shift+Delete} under Windows) |
266 | \row \i \e{Ctrl+Z} \i Undo the last operation | 374 | \row \i \e{Ctrl+Z} \i Undo the last operation |
267 | \row \i \e{Ctrl+Y} \i Redo the last operation | 375 | \row \i \e{Ctrl+Y} \i Redo the last operation |
268 | \row \i \e{LeftArrow} \i Move the cursor one character left | 376 | \row \i \e{LeftArrow} \i Move the cursor one character left |
269 | \row \i \e{Ctrl+LeftArrow} \i Move the cursor one word left | 377 | \row \i \e{Ctrl+LeftArrow} \i Move the cursor one word left |
@@ -274,85 +382,48 @@ static bool block_set_alignment = FALSE; | |||
274 | \row \i \e{DownArrow} \i Move the cursor one line down | 382 | \row \i \e{DownArrow} \i Move the cursor one line down |
275 | \row \i \e{Ctrl+Down Arrow} \i Move the cursor one word down | 383 | \row \i \e{Ctrl+Down Arrow} \i Move the cursor one word down |
276 | \row \i \e{PageUp} \i Move the cursor one page up | 384 | \row \i \e{PageUp} \i Move the cursor one page up |
277 | \row \i \e{PageDown} \i Move the cursor one page down | 385 | \row \i \e{PageDown} \i Move the cursor one page down |
278 | \row \i \e{Home} \i Move the cursor to the beginning of the line | 386 | \row \i \e{Home} \i Move the cursor to the beginning of the line |
279 | \row \i \e{Ctrl+Home} \i Move the cursor to the beginning of the text | 387 | \row \i \e{Ctrl+Home} \i Move the cursor to the beginning of the text |
280 | \row \i \e{End} \i Move the cursor to the end of the line | 388 | \row \i \e{End} \i Move the cursor to the end of the line |
281 | \row \i \e{Ctrl+End} \i Move the cursor to the end of the text | 389 | \row \i \e{Ctrl+End} \i Move the cursor to the end of the text |
282 | \row \i \e{Shift+Wheel} \i Scroll the page horizontally | 390 | \row \i \e{Shift+Wheel} \i Scroll the page horizontally |
283 | (the Wheel is the mouse wheel) | 391 | (the Wheel is the mouse wheel) |
284 | \row \i \e{Ctrl+Wheel} \i Zoom the text | 392 | \row \i \e{Ctrl+Wheel} \i Zoom the text |
285 | \endtable | 393 | \endtable |
286 | 394 | ||
287 | To select (mark) text hold down the Shift key whilst pressing one | 395 | To select (mark) text hold down the Shift key whilst pressing one |
288 | of the movement keystrokes, for example, <i>Shift+Right Arrow</i> | 396 | of the movement keystrokes, for example, <i>Shift+Right Arrow</i> |
289 | will select the character to the right, and <i>Shift+Ctrl+Right | 397 | will select the character to the right, and <i>Shift+Ctrl+Right |
290 | Arrow</i> will select the word to the right, etc. | 398 | Arrow</i> will select the word to the right, etc. |
291 | 399 | ||
292 | By default the text edit widget operates in insert mode so all | 400 | By default the text edit widget operates in insert mode so all |
293 | text that the user enters is inserted into the text edit and any | 401 | text that the user enters is inserted into the text edit and any |
294 | text to the right of the cursor is moved out of the way. The mode | 402 | text to the right of the cursor is moved out of the way. The mode |
295 | can be changed to overwrite, where new text overwrites any text to | 403 | can be changed to overwrite, where new text overwrites any text to |
296 | the right of the cursor, using setOverwriteMode(). | 404 | the right of the cursor, using setOverwriteMode(). |
297 | 405 | ||
298 | QTextEdit can also be used as read-only text viewer. Call | ||
299 | setReadOnly( TRUE ) to disable editing. A read-only QTextEdit | ||
300 | provides the same functionality as the (obsolete) QTextView. | ||
301 | (QTextView is still supplied for compatibility with old code.) | ||
302 | |||
303 | When QTextEdit is used read-only the key-bindings are limited to | ||
304 | navigation, and text may only be selected with the mouse: | ||
305 | \table | ||
306 | \header \i Keypresses \i Action | ||
307 | \row \i \e{UpArrow} \i Move one line up | ||
308 | \row \i \e{DownArrow} \i Move one line down | ||
309 | \row \i \e{LeftArrow} \i Move one character left | ||
310 | \row \i \e{RightArrow} \i Move one character right | ||
311 | \row \i \e{PageUp} \i Move one (viewport) page up | ||
312 | \row \i \e{PageDown} \i Move one (viewport) page down | ||
313 | \row \i \e{Home} \i Move to the beginning of the text | ||
314 | \row \i \e{End} \i Move to the end of the text | ||
315 | \row \i \e{Shift+Wheel} \i Scroll the page horizontally (the Wheel is the mouse wheel) | ||
316 | \row \i \e{Ctrl+Wheel} \i Zoom the text | ||
317 | \endtable | ||
318 | |||
319 | The text edit may be able to provide some meta-information. For | ||
320 | example, the documentTitle() function will return the text from | ||
321 | within HTML \c{<title>} tags. | ||
322 | |||
323 | The text displayed in a text edit has a \e context. The context is | ||
324 | a path which the text edit's QMimeSourceFactory uses to resolve | ||
325 | the locations of files and images. It is passed to the | ||
326 | mimeSourceFactory() when quering data. (See QTextEdit() and | ||
327 | \l{context()}.) | ||
328 | |||
329 | Note that we do not intend to add a full-featured web browser | ||
330 | widget to Qt (because that would easily double Qt's size and only | ||
331 | a few applications would benefit from it). The rich | ||
332 | text support in Qt is designed to provide a fast, portable and | ||
333 | efficient way to add reasonable online help facilities to | ||
334 | applications, and to provide a basis for rich text editors. | ||
335 | */ | 406 | */ |
336 | 407 | ||
337 | /*! \enum QTextEdit::KeyboardAction | 408 | /*! \enum QTextEdit::KeyboardAction |
338 | 409 | ||
339 | This enum is used by doKeyboardAction() to specify which action | 410 | This enum is used by doKeyboardAction() to specify which action |
340 | should be executed: | 411 | should be executed: |
341 | 412 | ||
342 | \value ActionBackspace Delete the character to the left of the | 413 | \value ActionBackspace Delete the character to the left of the |
343 | cursor. | 414 | cursor. |
344 | 415 | ||
345 | \value ActionDelete Delete the character to the right of the cursor. | 416 | \value ActionDelete Delete the character to the right of the cursor. |
346 | 417 | ||
347 | \value ActionReturn Split the paragraph at the cursor position. | 418 | \value ActionReturn Split the paragraph at the cursor position. |
348 | 419 | ||
349 | \value ActionKill If the cursor is not at the end of the paragraph, | 420 | \value ActionKill If the cursor is not at the end of the paragraph, |
350 | delete the text from the cursor position until the end of the | 421 | delete the text from the cursor position until the end of the |
351 | paragraph. If the cursor is at the end of the paragraph, delete the | 422 | paragraph. If the cursor is at the end of the paragraph, delete the |
352 | hard line break at the end of the paragraph - this will cause this | 423 | hard line break at the end of the paragraph - this will cause this |
353 | paragraph to be joined with the following paragraph. | 424 | paragraph to be joined with the following paragraph. |
354 | */ | 425 | */ |
355 | 426 | ||
356 | /*! \enum QTextEdit::VerticalAlignment | 427 | /*! \enum QTextEdit::VerticalAlignment |
357 | 428 | ||
358 | This enum is used to set the vertical alignment of the text. | 429 | This enum is used to set the vertical alignment of the text. |
@@ -619,67 +690,69 @@ QTextEdit::~QTextEdit() | |||
619 | delete d; | 690 | delete d; |
620 | } | 691 | } |
621 | 692 | ||
622 | void QTextEdit::init() | 693 | void QTextEdit::init() |
623 | { | 694 | { |
624 | setFrameStyle( Sunken ); | 695 | setFrameStyle( Sunken ); |
625 | undoEnabled = TRUE; | 696 | undoEnabled = TRUE; |
626 | readonly = TRUE; | 697 | readonly = TRUE; |
627 | setReadOnly( FALSE ); | 698 | setReadOnly( FALSE ); |
628 | d = new QTextEditPrivate; | 699 | d = new QTextEditPrivate; |
629 | connect( doc, SIGNAL( minimumWidthChanged( int ) ), | 700 | connect( doc, SIGNAL( minimumWidthChanged( int ) ), |
630 | this, SLOT( documentWidthChanged( int ) ) ); | 701 | this, SLOT( documentWidthChanged( int ) ) ); |
631 | 702 | ||
632 | mousePressed = FALSE; | 703 | mousePressed = FALSE; |
633 | inDoubleClick = FALSE; | 704 | inDoubleClick = FALSE; |
634 | modified = FALSE; | 705 | modified = FALSE; |
635 | onLink = QString::null; | 706 | onLink = QString::null; |
636 | overWrite = FALSE; | 707 | overWrite = FALSE; |
637 | wrapMode = WidgetWidth; | 708 | wrapMode = WidgetWidth; |
638 | wrapWidth = -1; | 709 | wrapWidth = -1; |
639 | wPolicy = AtWhiteSpace; | 710 | wPolicy = AtWhiteSpace; |
640 | inDnD = FALSE; | 711 | inDnD = FALSE; |
641 | 712 | ||
642 | doc->setFormatter( new QTextFormatterBreakWords ); | 713 | doc->setFormatter( new QTextFormatterBreakWords ); |
714 | doc->formatCollection()->defaultFormat()->setFont( QScrollView::font() ); | ||
715 | doc->formatCollection()->defaultFormat()->setColor( colorGroup().color( QColorGroup::Text ) ); | ||
643 | currentFormat = doc->formatCollection()->defaultFormat(); | 716 | currentFormat = doc->formatCollection()->defaultFormat(); |
644 | currentAlignment = Qt3::AlignAuto; | 717 | currentAlignment = Qt3::AlignAuto; |
645 | 718 | ||
646 | viewport()->setBackgroundMode( PaletteBase ); | 719 | viewport()->setBackgroundMode( PaletteBase ); |
647 | viewport()->setAcceptDrops( TRUE ); | 720 | viewport()->setAcceptDrops( TRUE ); |
648 | resizeContents( 0, doc->lastParag() ? | 721 | resizeContents( 0, doc->lastParagraph() ? |
649 | ( doc->lastParag()->paragId() + 1 ) * doc->formatCollection()->defaultFormat()->height() : 0 ); | 722 | ( doc->lastParagraph()->paragId() + 1 ) * doc->formatCollection()->defaultFormat()->height() : 0 ); |
650 | 723 | ||
651 | setKeyCompression( TRUE ); | 724 | setKeyCompression( TRUE ); |
652 | viewport()->setMouseTracking( TRUE ); | 725 | viewport()->setMouseTracking( TRUE ); |
653 | #ifndef QT_NO_CURSOR | 726 | #ifndef QT_NO_CURSOR |
654 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); | 727 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); |
655 | #endif | 728 | #endif |
656 | cursor = new QTextCursor( doc ); | 729 | cursor = new QTextCursor( doc ); |
657 | 730 | ||
658 | formatTimer = new QTimer( this ); | 731 | formatTimer = new QTimer( this ); |
659 | connect( formatTimer, SIGNAL( timeout() ), | 732 | connect( formatTimer, SIGNAL( timeout() ), |
660 | this, SLOT( formatMore() ) ); | 733 | this, SLOT( formatMore() ) ); |
661 | lastFormatted = doc->firstParag(); | 734 | lastFormatted = doc->firstParagraph(); |
662 | 735 | ||
663 | scrollTimer = new QTimer( this ); | 736 | scrollTimer = new QTimer( this ); |
664 | connect( scrollTimer, SIGNAL( timeout() ), | 737 | connect( scrollTimer, SIGNAL( timeout() ), |
665 | this, SLOT( autoScrollTimerDone() ) ); | 738 | this, SLOT( autoScrollTimerDone() ) ); |
666 | 739 | ||
667 | interval = 0; | 740 | interval = 0; |
668 | changeIntervalTimer = new QTimer( this ); | 741 | changeIntervalTimer = new QTimer( this ); |
669 | connect( changeIntervalTimer, SIGNAL( timeout() ), | 742 | connect( changeIntervalTimer, SIGNAL( timeout() ), |
670 | this, SLOT( doChangeInterval() ) ); | 743 | this, SLOT( doChangeInterval() ) ); |
671 | 744 | ||
672 | cursorVisible = TRUE; | 745 | cursorVisible = TRUE; |
673 | blinkTimer = new QTimer( this ); | 746 | blinkTimer = new QTimer( this ); |
674 | connect( blinkTimer, SIGNAL( timeout() ), | 747 | connect( blinkTimer, SIGNAL( timeout() ), |
675 | this, SLOT( blinkCursor() ) ); | 748 | this, SLOT( blinkCursor() ) ); |
676 | 749 | ||
677 | #ifndef QT_NO_DRAGANDDROP | 750 | #ifndef QT_NO_DRAGANDDROP |
678 | dragStartTimer = new QTimer( this ); | 751 | dragStartTimer = new QTimer( this ); |
679 | connect( dragStartTimer, SIGNAL( timeout() ), | 752 | connect( dragStartTimer, SIGNAL( timeout() ), |
680 | this, SLOT( startDrag() ) ); | 753 | this, SLOT( startDrag() ) ); |
681 | #endif | 754 | #endif |
682 | 755 | ||
683 | 756 | ||
684 | formatMore(); | 757 | formatMore(); |
685 | 758 | ||
@@ -692,52 +765,52 @@ void QTextEdit::init() | |||
692 | } | 765 | } |
693 | 766 | ||
694 | void QTextEdit::paintDocument( bool drawAll, QPainter *p, int cx, int cy, int cw, int ch ) | 767 | void QTextEdit::paintDocument( bool drawAll, QPainter *p, int cx, int cy, int cw, int ch ) |
695 | { | 768 | { |
696 | bool drawCur = hasFocus() || viewport()->hasFocus(); | 769 | bool drawCur = hasFocus() || viewport()->hasFocus(); |
697 | if ( hasSelectedText() || isReadOnly() || !cursorVisible ) | 770 | if ( hasSelectedText() || isReadOnly() || !cursorVisible ) |
698 | drawCur = FALSE; | 771 | drawCur = FALSE; |
699 | QColorGroup g = colorGroup(); | 772 | QColorGroup g = colorGroup(); |
700 | if ( doc->paper() ) | 773 | if ( doc->paper() ) |
701 | g.setBrush( QColorGroup::Base, *doc->paper() ); | 774 | g.setBrush( QColorGroup::Base, *doc->paper() ); |
702 | 775 | ||
703 | if ( contentsY() < doc->y() ) { | 776 | if ( contentsY() < doc->y() ) { |
704 | p->fillRect( contentsX(), contentsY(), visibleWidth(), doc->y(), | 777 | p->fillRect( contentsX(), contentsY(), visibleWidth(), doc->y(), |
705 | g.brush( QColorGroup::Base ) ); | 778 | g.brush( QColorGroup::Base ) ); |
706 | } | 779 | } |
707 | if ( drawAll && doc->width() - contentsX() < cx + cw ) { | 780 | if ( drawAll && doc->width() - contentsX() < cx + cw ) { |
708 | p->fillRect( doc->width() - contentsX(), cy, cx + cw - doc->width() + contentsX(), ch, | 781 | p->fillRect( doc->width() - contentsX(), cy, cx + cw - doc->width() + contentsX(), ch, |
709 | g.brush( QColorGroup::Base ) ); | 782 | g.brush( QColorGroup::Base ) ); |
710 | } | 783 | } |
711 | 784 | ||
712 | p->setBrushOrigin( -contentsX(), -contentsY() ); | 785 | p->setBrushOrigin( -contentsX(), -contentsY() ); |
713 | 786 | ||
714 | lastFormatted = doc->draw( p, cx, cy, cw, ch, g, !drawAll, drawCur, cursor ); | 787 | lastFormatted = doc->draw( p, cx, cy, cw, ch, g, !drawAll, drawCur, cursor ); |
715 | 788 | ||
716 | if ( lastFormatted == doc->lastParag() ) | 789 | if ( lastFormatted == doc->lastParagraph() ) |
717 | resizeContents( contentsWidth(), doc->height() ); | 790 | resizeContents( contentsWidth(), doc->height() ); |
718 | 791 | ||
719 | if ( contentsHeight() < visibleHeight() && ( !doc->lastParag() || doc->lastParag()->isValid() ) && drawAll ) | 792 | if ( contentsHeight() < visibleHeight() && ( !doc->lastParagraph() || doc->lastParagraph()->isValid() ) && drawAll ) |
720 | p->fillRect( 0, contentsHeight(), visibleWidth(), | 793 | p->fillRect( 0, contentsHeight(), visibleWidth(), |
721 | visibleHeight() - contentsHeight(), g.brush( QColorGroup::Base ) ); | 794 | visibleHeight() - contentsHeight(), g.brush( QColorGroup::Base ) ); |
722 | } | 795 | } |
723 | 796 | ||
724 | /*! \reimp */ | 797 | /*! \reimp */ |
725 | 798 | ||
726 | void QTextEdit::drawContents( QPainter *p, int cx, int cy, int cw, int ch ) | 799 | void QTextEdit::drawContents( QPainter *p, int cx, int cy, int cw, int ch ) |
727 | { | 800 | { |
728 | paintDocument( TRUE, p, cx, cy, cw, ch ); | 801 | paintDocument( TRUE, p, cx, cy, cw, ch ); |
729 | int v; | 802 | int v; |
730 | p->setPen( foregroundColor() ); | 803 | p->setPen( foregroundColor() ); |
731 | if ( document()->isPageBreakEnabled() && ( v = document()->flow()->pageSize() ) > 0 ) { | 804 | if ( document()->isPageBreakEnabled() && ( v = document()->flow()->pageSize() ) > 0 ) { |
732 | int l = int(cy / v) * v; | 805 | int l = int(cy / v) * v; |
733 | while ( l < cy + ch ) { | 806 | while ( l < cy + ch ) { |
734 | p->drawLine( cx, l, cx + cw - 1, l ); | 807 | p->drawLine( cx, l, cx + cw - 1, l ); |
735 | l += v; | 808 | l += v; |
736 | } | 809 | } |
737 | } | 810 | } |
738 | 811 | ||
739 | } | 812 | } |
740 | 813 | ||
741 | /*! \reimp */ | 814 | /*! \reimp */ |
742 | 815 | ||
743 | void QTextEdit::drawContents( QPainter * ) | 816 | void QTextEdit::drawContents( QPainter * ) |
@@ -792,784 +865,738 @@ bool QTextEdit::event( QEvent *e ) | |||
792 | case Key_Down: | 865 | case Key_Down: |
793 | case Key_Home: | 866 | case Key_Home: |
794 | case Key_End: | 867 | case Key_End: |
795 | case Key_Tab: | 868 | case Key_Tab: |
796 | #if defined (Q_WS_WIN) | 869 | #if defined (Q_WS_WIN) |
797 | case Key_Insert: | 870 | case Key_Insert: |
798 | case Key_Delete: | 871 | case Key_Delete: |
799 | #endif | 872 | #endif |
800 | ke->accept(); | 873 | ke->accept(); |
801 | default: | 874 | default: |
802 | break; | 875 | break; |
803 | } | 876 | } |
804 | } else { | 877 | } else { |
805 | switch ( ke->key() ) { | 878 | switch ( ke->key() ) { |
806 | #if defined (Q_WS_WIN) | 879 | #if defined (Q_WS_WIN) |
807 | case Key_Insert: | 880 | case Key_Insert: |
808 | ke->accept(); | 881 | ke->accept(); |
809 | #endif | 882 | #endif |
810 | default: | 883 | default: |
811 | break; | 884 | break; |
812 | } | 885 | } |
813 | } | 886 | } |
814 | } | 887 | } |
815 | 888 | ||
816 | if ( e->type() == QEvent::Show && d->ensureCursorVisibleInShowEvent ) { | 889 | if ( e->type() == QEvent::Show ) { |
890 | if ( d->ensureCursorVisibleInShowEvent ) { | ||
817 | sync(); | 891 | sync(); |
818 | ensureCursorVisible(); | 892 | ensureCursorVisible(); |
819 | d->ensureCursorVisibleInShowEvent = FALSE; | 893 | d->ensureCursorVisibleInShowEvent = FALSE; |
820 | } | 894 | } |
895 | if ( !d->scrollToAnchor.isEmpty() ) { | ||
896 | scrollToAnchor( d->scrollToAnchor ); | ||
897 | d->scrollToAnchor = QString::null; | ||
898 | } | ||
899 | } | ||
821 | return QWidget::event( e ); | 900 | return QWidget::event( e ); |
822 | } | 901 | } |
823 | 902 | ||
824 | /*! | 903 | /*! |
825 | Processes the key event, \a e. | 904 | Processes the key event, \a e. |
826 | By default key events are used to provide keyboard navigation and | 905 | By default key events are used to provide keyboard navigation and |
827 | text editing. | 906 | text editing. |
828 | */ | 907 | */ |
829 | 908 | ||
830 | void QTextEdit::keyPressEvent( QKeyEvent *e ) | 909 | void QTextEdit::keyPressEvent( QKeyEvent *e ) |
831 | { | 910 | { |
832 | changeIntervalTimer->stop(); | 911 | changeIntervalTimer->stop(); |
833 | interval = 10; | 912 | interval = 10; |
834 | bool unknown = FALSE; | 913 | bool unknown = FALSE; |
835 | if ( isReadOnly() ) { | 914 | if ( isReadOnly() ) { |
836 | if ( !handleReadOnlyKeyEvent( e ) ) | 915 | if ( !handleReadOnlyKeyEvent( e ) ) |
837 | QScrollView::keyPressEvent( e ); | 916 | QScrollView::keyPressEvent( e ); |
838 | changeIntervalTimer->start( 100, TRUE ); | 917 | changeIntervalTimer->start( 100, TRUE ); |
839 | return; | 918 | return; |
840 | } | 919 | } |
841 | 920 | ||
842 | 921 | ||
843 | bool selChanged = FALSE; | 922 | bool selChanged = FALSE; |
844 | for ( int i = 1; i < doc->numSelections(); ++i ) // start with 1 as we don't want to remove the Standard-Selection | 923 | for ( int i = 1; i < doc->numSelections(); ++i ) // start with 1 as we don't want to remove the Standard-Selection |
845 | selChanged = doc->removeSelection( i ) || selChanged; | 924 | selChanged = doc->removeSelection( i ) || selChanged; |
846 | 925 | ||
847 | if ( selChanged ) { | 926 | if ( selChanged ) { |
848 | cursor->parag()->document()->nextDoubleBuffered = TRUE; | 927 | cursor->paragraph()->document()->nextDoubleBuffered = TRUE; |
849 | repaintChanged(); | 928 | repaintChanged(); |
850 | } | 929 | } |
851 | 930 | ||
852 | bool clearUndoRedoInfo = TRUE; | 931 | bool clearUndoRedoInfo = TRUE; |
853 | 932 | ||
854 | 933 | ||
855 | switch ( e->key() ) { | 934 | switch ( e->key() ) { |
856 | case Key_Left: | 935 | case Key_Left: |
857 | case Key_Right: { | 936 | case Key_Right: { |
858 | // a bit hacky, but can't change this without introducing new enum values for move and keeping the | 937 | // a bit hacky, but can't change this without introducing new enum values for move and keeping the |
859 | // correct semantics and movement for BiDi and non BiDi text. | 938 | // correct semantics and movement for BiDi and non BiDi text. |
860 | CursorAction a; | 939 | CursorAction a; |
861 | if ( cursor->parag()->string()->isRightToLeft() == (e->key() == Key_Right) ) | 940 | if ( cursor->paragraph()->string()->isRightToLeft() == (e->key() == Key_Right) ) |
862 | a = e->state() & ControlButton ? MoveWordBackward : MoveBackward; | 941 | a = e->state() & ControlButton ? MoveWordBackward : MoveBackward; |
863 | else | 942 | else |
864 | a = e->state() & ControlButton ? MoveWordForward : MoveForward; | 943 | a = e->state() & ControlButton ? MoveWordForward : MoveForward; |
865 | moveCursor( a, e->state() & ShiftButton ); | 944 | moveCursor( a, e->state() & ShiftButton ); |
866 | break; | 945 | break; |
867 | } | 946 | } |
868 | case Key_Up: | 947 | case Key_Up: |
869 | moveCursor( e->state() & ControlButton ? MovePgUp : MoveUp, e->state() & ShiftButton ); | 948 | moveCursor( e->state() & ControlButton ? MovePgUp : MoveUp, e->state() & ShiftButton ); |
870 | break; | 949 | break; |
871 | case Key_Down: | 950 | case Key_Down: |
872 | moveCursor( e->state() & ControlButton ? MovePgDown : MoveDown, e->state() & ShiftButton ); | 951 | moveCursor( e->state() & ControlButton ? MovePgDown : MoveDown, e->state() & ShiftButton ); |
873 | break; | 952 | break; |
874 | case Key_Home: | 953 | case Key_Home: |
875 | moveCursor( e->state() & ControlButton ? MoveHome : MoveLineStart, e->state() & ShiftButton ); | 954 | moveCursor( e->state() & ControlButton ? MoveHome : MoveLineStart, e->state() & ShiftButton ); |
876 | break; | 955 | break; |
877 | case Key_End: | 956 | case Key_End: |
878 | moveCursor( e->state() & ControlButton ? MoveEnd : MoveLineEnd, e->state() & ShiftButton ); | 957 | moveCursor( e->state() & ControlButton ? MoveEnd : MoveLineEnd, e->state() & ShiftButton ); |
879 | break; | 958 | break; |
880 | case Key_Prior: | 959 | case Key_Prior: |
881 | moveCursor( MovePgUp, e->state() & ShiftButton ); | 960 | moveCursor( MovePgUp, e->state() & ShiftButton ); |
882 | break; | 961 | break; |
883 | case Key_Next: | 962 | case Key_Next: |
884 | moveCursor( MovePgDown, e->state() & ShiftButton ); | 963 | moveCursor( MovePgDown, e->state() & ShiftButton ); |
885 | break; | 964 | break; |
886 | case Key_Return: case Key_Enter: | 965 | case Key_Return: case Key_Enter: |
887 | if ( doc->hasSelection( QTextDocument::Standard, FALSE ) ) | 966 | if ( doc->hasSelection( QTextDocument::Standard, FALSE ) ) |
888 | removeSelectedText(); | 967 | removeSelectedText(); |
968 | if ( textFormat() == Qt::RichText && ( e->state() & ControlButton ) ) { | ||
969 | // Ctrl-Enter inserts a line break in rich text mode | ||
970 | insert( QString( QChar( 0x2028) ), TRUE, FALSE, TRUE ); | ||
971 | } else { | ||
889 | #ifndef QT_NO_CURSOR | 972 | #ifndef QT_NO_CURSOR |
890 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); | 973 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); |
891 | #endif | 974 | #endif |
892 | clearUndoRedoInfo = FALSE; | 975 | clearUndoRedoInfo = FALSE; |
893 | doKeyboardAction( ActionReturn ); | 976 | doKeyboardAction( ActionReturn ); |
894 | emit returnPressed(); | 977 | emit returnPressed(); |
978 | } | ||
895 | break; | 979 | break; |
896 | case Key_Delete: | 980 | case Key_Delete: |
897 | #if defined (Q_WS_WIN) | 981 | #if defined (Q_WS_WIN) |
898 | if ( e->state() & ShiftButton ) { | 982 | if ( e->state() & ShiftButton ) { |
899 | cut(); | 983 | cut(); |
900 | break; | 984 | break; |
901 | } else | 985 | } else |
902 | #endif | 986 | #endif |
903 | if ( doc->hasSelection( QTextDocument::Standard, TRUE ) ) { | 987 | if ( doc->hasSelection( QTextDocument::Standard, TRUE ) ) { |
904 | removeSelectedText(); | 988 | removeSelectedText(); |
905 | break; | 989 | break; |
906 | } | 990 | } |
907 | doKeyboardAction( ActionDelete ); | 991 | doKeyboardAction( ActionDelete ); |
908 | clearUndoRedoInfo = FALSE; | 992 | clearUndoRedoInfo = FALSE; |
909 | 993 | ||
910 | break; | 994 | break; |
911 | case Key_Insert: | 995 | case Key_Insert: |
912 | if ( e->state() & ShiftButton ) | 996 | if ( e->state() & ShiftButton ) |
913 | paste(); | 997 | paste(); |
998 | #if defined (Q_WS_WIN) | ||
999 | else if ( e->state() & ControlButton ) | ||
1000 | copy(); | ||
1001 | #endif | ||
914 | break; | 1002 | break; |
915 | case Key_Backspace: | 1003 | case Key_Backspace: |
916 | if ( doc->hasSelection( QTextDocument::Standard, TRUE ) ) { | 1004 | if ( doc->hasSelection( QTextDocument::Standard, TRUE ) ) { |
917 | removeSelectedText(); | 1005 | removeSelectedText(); |
918 | break; | 1006 | break; |
919 | } | 1007 | } |
920 | 1008 | ||
921 | if ( !cursor->parag()->prev() && | ||
922 | cursor->atParagStart() ) | ||
923 | break; | ||
924 | |||
925 | doKeyboardAction( ActionBackspace ); | 1009 | doKeyboardAction( ActionBackspace ); |
926 | clearUndoRedoInfo = FALSE; | 1010 | clearUndoRedoInfo = FALSE; |
927 | 1011 | ||
928 | break; | 1012 | break; |
929 | case Key_F16: // Copy key on Sun keyboards | 1013 | case Key_F16: // Copy key on Sun keyboards |
930 | copy(); | 1014 | copy(); |
931 | break; | 1015 | break; |
932 | case Key_F18: // Paste key on Sun keyboards | 1016 | case Key_F18: // Paste key on Sun keyboards |
933 | paste(); | 1017 | paste(); |
934 | break; | 1018 | break; |
935 | case Key_F20: // Cut key on Sun keyboards | 1019 | case Key_F20: // Cut key on Sun keyboards |
936 | cut(); | 1020 | cut(); |
937 | break; | 1021 | break; |
938 | default: { | 1022 | default: { |
939 | if ( e->text().length() && | 1023 | if ( e->text().length() && |
940 | ( !( e->state() & ControlButton ) && | 1024 | ( !( e->state() & ControlButton ) && |
941 | !( e->state() & AltButton ) || | 1025 | !( e->state() & AltButton ) || |
942 | ( ( e->state() & ControlButton | AltButton ) == (ControlButton|AltButton) ) ) && | 1026 | ( ( e->state() & ControlButton | AltButton ) == (ControlButton|AltButton) ) ) && |
943 | ( !e->ascii() || e->ascii() >= 32 || e->text() == "\t" ) ) { | 1027 | ( !e->ascii() || e->ascii() >= 32 || e->text() == "\t" ) ) { |
944 | clearUndoRedoInfo = FALSE; | 1028 | clearUndoRedoInfo = FALSE; |
945 | if ( e->key() == Key_Tab ) { | 1029 | if ( e->key() == Key_Tab ) { |
946 | if ( textFormat() == Qt::RichText && | 1030 | if ( textFormat() == Qt::RichText && cursor->paragraph()->isListItem() ) { |
947 | cursor->index() == 0 && cursor->parag()->style() && | 1031 | clearUndoRedo(); |
948 | cursor->parag()->style()->displayMode() == | 1032 | undoRedoInfo.type = UndoRedoInfo::Style; |
949 | QStyleSheetItem::DisplayListItem ) { | 1033 | undoRedoInfo.id = cursor->paragraph()->paragId(); |
950 | cursor->parag()->incDepth(); | 1034 | undoRedoInfo.eid = undoRedoInfo.id; |
1035 | undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); | ||
1036 | cursor->paragraph()->setListDepth( cursor->paragraph()->listDepth() +1 ); | ||
1037 | clearUndoRedo(); | ||
951 | drawCursor( FALSE ); | 1038 | drawCursor( FALSE ); |
952 | repaintChanged(); | 1039 | repaintChanged(); |
953 | drawCursor( TRUE ); | 1040 | drawCursor( TRUE ); |
954 | break; | 1041 | break; |
955 | } | 1042 | } |
956 | } | 1043 | } |
957 | if ( textFormat() == Qt::RichText && ( !cursor->parag()->style() || | 1044 | |
958 | cursor->parag()->style()->displayMode() == QStyleSheetItem::DisplayBlock ) && | 1045 | if ( textFormat() == Qt::RichText && !cursor->paragraph()->isListItem() ) { |
959 | cursor->index() == 0 && ( e->text()[0] == '-' || e->text()[0] == '*' ) ) { | 1046 | if ( cursor->index() == 0 && ( e->text()[0] == '-' || e->text()[0] == '*' ) ) { |
1047 | clearUndoRedo(); | ||
1048 | undoRedoInfo.type = UndoRedoInfo::Style; | ||
1049 | undoRedoInfo.id = cursor->paragraph()->paragId(); | ||
1050 | undoRedoInfo.eid = undoRedoInfo.id; | ||
1051 | undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); | ||
960 | setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDisc ); | 1052 | setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDisc ); |
961 | cursor->parag()->incDepth(); | 1053 | clearUndoRedo(); |
962 | drawCursor( FALSE ); | 1054 | drawCursor( FALSE ); |
963 | repaintChanged(); | 1055 | repaintChanged(); |
964 | drawCursor( TRUE ); | 1056 | drawCursor( TRUE ); |
965 | } else { | 1057 | break; |
1058 | } | ||
1059 | } | ||
966 | if ( overWrite && !cursor->atParagEnd() ) | 1060 | if ( overWrite && !cursor->atParagEnd() ) |
967 | cursor->remove(); | 1061 | cursor->remove(); |
968 | QString t = e->text(); | 1062 | QString t = e->text(); |
969 | QTextParag *p = cursor->parag(); | 1063 | QTextParagraph *p = cursor->paragraph(); |
970 | if ( p && p->string() && p->string()->isRightToLeft() ) { | 1064 | if ( p && p->string() && p->string()->isRightToLeft() ) { |
971 | QChar *c = (QChar *)t.unicode(); | 1065 | QChar *c = (QChar *)t.unicode(); |
972 | int l = t.length(); | 1066 | int l = t.length(); |
973 | while( l-- ) { | 1067 | while( l-- ) { |
974 | if ( c->mirrored() ) | 1068 | if ( c->mirrored() ) |
975 | *c = c->mirroredChar(); | 1069 | *c = c->mirroredChar(); |
976 | c++; | 1070 | c++; |
977 | } | 1071 | } |
978 | } | 1072 | } |
979 | insert( t, TRUE, FALSE, TRUE ); | 1073 | insert( t, TRUE, FALSE, TRUE ); |
980 | } | ||
981 | break; | 1074 | break; |
982 | } else if ( e->state() & ControlButton ) { | 1075 | } else if ( e->state() & ControlButton ) { |
983 | switch ( e->key() ) { | 1076 | switch ( e->key() ) { |
984 | case Key_C: case Key_F16: // Copy key on Sun keyboards | 1077 | case Key_C: case Key_F16: // Copy key on Sun keyboards |
985 | copy(); | 1078 | copy(); |
986 | break; | 1079 | break; |
987 | case Key_V: | 1080 | case Key_V: |
988 | paste(); | 1081 | paste(); |
989 | break; | 1082 | break; |
990 | case Key_X: | 1083 | case Key_X: |
991 | cut(); | 1084 | cut(); |
992 | break; | 1085 | break; |
993 | case Key_I: case Key_T: case Key_Tab: | 1086 | case Key_I: case Key_T: case Key_Tab: |
994 | indent(); | 1087 | indent(); |
995 | break; | 1088 | break; |
996 | case Key_A: | 1089 | case Key_A: |
997 | #if defined(Q_WS_X11) | 1090 | #if defined(Q_WS_X11) |
998 | moveCursor( MoveLineStart, e->state() & ShiftButton ); | 1091 | moveCursor( MoveLineStart, e->state() & ShiftButton ); |
999 | #else | 1092 | #else |
1000 | selectAll( TRUE ); | 1093 | selectAll( TRUE ); |
1001 | #endif | 1094 | #endif |
1002 | break; | 1095 | break; |
1003 | case Key_B: | 1096 | case Key_B: |
1004 | moveCursor( MoveBackward, e->state() & ShiftButton ); | 1097 | moveCursor( MoveBackward, e->state() & ShiftButton ); |
1005 | break; | 1098 | break; |
1006 | case Key_F: | 1099 | case Key_F: |
1007 | moveCursor( MoveForward, e->state() & ShiftButton ); | 1100 | moveCursor( MoveForward, e->state() & ShiftButton ); |
1008 | break; | 1101 | break; |
1009 | case Key_D: | 1102 | case Key_D: |
1010 | if ( doc->hasSelection( QTextDocument::Standard ) ) { | 1103 | if ( doc->hasSelection( QTextDocument::Standard ) ) { |
1011 | removeSelectedText(); | 1104 | removeSelectedText(); |
1012 | break; | 1105 | break; |
1013 | } | 1106 | } |
1014 | doKeyboardAction( ActionDelete ); | 1107 | doKeyboardAction( ActionDelete ); |
1015 | clearUndoRedoInfo = FALSE; | 1108 | clearUndoRedoInfo = FALSE; |
1016 | break; | 1109 | break; |
1017 | case Key_H: | 1110 | case Key_H: |
1018 | if ( doc->hasSelection( QTextDocument::Standard ) ) { | 1111 | if ( doc->hasSelection( QTextDocument::Standard ) ) { |
1019 | removeSelectedText(); | 1112 | removeSelectedText(); |
1020 | break; | 1113 | break; |
1021 | } | 1114 | } |
1022 | if ( !cursor->parag()->prev() && | 1115 | if ( !cursor->paragraph()->prev() && |
1023 | cursor->atParagStart() ) | 1116 | cursor->atParagStart() ) |
1024 | break; | 1117 | break; |
1025 | 1118 | ||
1026 | doKeyboardAction( ActionBackspace ); | 1119 | doKeyboardAction( ActionBackspace ); |
1027 | clearUndoRedoInfo = FALSE; | 1120 | clearUndoRedoInfo = FALSE; |
1028 | break; | 1121 | break; |
1029 | case Key_E: | 1122 | case Key_E: |
1030 | moveCursor( MoveLineEnd, e->state() & ShiftButton ); | 1123 | moveCursor( MoveLineEnd, e->state() & ShiftButton ); |
1031 | break; | 1124 | break; |
1032 | case Key_N: | 1125 | case Key_N: |
1033 | moveCursor( MoveDown, e->state() & ShiftButton ); | 1126 | moveCursor( MoveDown, e->state() & ShiftButton ); |
1034 | break; | 1127 | break; |
1035 | case Key_P: | 1128 | case Key_P: |
1036 | moveCursor( MoveUp, e->state() & ShiftButton ); | 1129 | moveCursor( MoveUp, e->state() & ShiftButton ); |
1037 | break; | 1130 | break; |
1038 | case Key_Z: | 1131 | case Key_Z: |
1132 | if(e->state() & ShiftButton) | ||
1133 | redo(); | ||
1134 | else | ||
1039 | undo(); | 1135 | undo(); |
1040 | break; | 1136 | break; |
1041 | case Key_Y: | 1137 | case Key_Y: |
1042 | redo(); | 1138 | redo(); |
1043 | break; | 1139 | break; |
1044 | case Key_K: | 1140 | case Key_K: |
1045 | doKeyboardAction( ActionKill ); | 1141 | doKeyboardAction( ActionKill ); |
1046 | break; | 1142 | break; |
1047 | #if defined(Q_WS_WIN) | 1143 | #if defined(Q_WS_WIN) |
1048 | case Key_Insert: | 1144 | case Key_Insert: |
1049 | copy(); | 1145 | copy(); |
1050 | break; | 1146 | break; |
1051 | case Key_Delete: | 1147 | case Key_Delete: |
1052 | del(); | 1148 | del(); |
1053 | break; | 1149 | break; |
1054 | #endif | 1150 | #endif |
1055 | default: | 1151 | default: |
1056 | unknown = FALSE; | 1152 | unknown = FALSE; |
1057 | break; | 1153 | break; |
1058 | } | 1154 | } |
1059 | } else { | 1155 | } else { |
1060 | unknown = TRUE; | 1156 | unknown = TRUE; |
1061 | } | 1157 | } |
1062 | } | 1158 | } |
1063 | } | 1159 | } |
1064 | 1160 | ||
1065 | emit cursorPositionChanged( cursor ); | 1161 | emit cursorPositionChanged( cursor ); |
1066 | emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); | 1162 | emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); |
1067 | if ( clearUndoRedoInfo ) | 1163 | if ( clearUndoRedoInfo ) |
1068 | clearUndoRedo(); | 1164 | clearUndoRedo(); |
1069 | changeIntervalTimer->start( 100, TRUE ); | 1165 | changeIntervalTimer->start( 100, TRUE ); |
1070 | if ( unknown ) | 1166 | if ( unknown ) |
1071 | e->ignore(); | 1167 | e->ignore(); |
1072 | } | 1168 | } |
1073 | 1169 | ||
1074 | /*! | 1170 | /*! |
1075 | Executes keyboard action \a action. This is normally called by | 1171 | Executes keyboard action \a action. This is normally called by |
1076 | a key event handler. | 1172 | a key event handler. |
1077 | */ | 1173 | */ |
1078 | 1174 | ||
1079 | void QTextEdit::doKeyboardAction( KeyboardAction action ) | 1175 | void QTextEdit::doKeyboardAction( KeyboardAction action ) |
1080 | { | 1176 | { |
1081 | if ( isReadOnly() ) | 1177 | if ( isReadOnly() ) |
1082 | return; | 1178 | return; |
1083 | 1179 | ||
1084 | if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough | 1180 | if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough |
1085 | return; | 1181 | return; |
1086 | 1182 | ||
1087 | lastFormatted = cursor->parag(); | 1183 | lastFormatted = cursor->paragraph(); |
1088 | drawCursor( FALSE ); | 1184 | drawCursor( FALSE ); |
1089 | bool doUpdateCurrentFormat = TRUE; | 1185 | bool doUpdateCurrentFormat = TRUE; |
1090 | 1186 | ||
1091 | switch ( action ) { | 1187 | switch ( action ) { |
1092 | case ActionDelete: { | 1188 | case ActionDelete: |
1189 | if ( !cursor->atParagEnd() ) { | ||
1093 | checkUndoRedoInfo( UndoRedoInfo::Delete ); | 1190 | checkUndoRedoInfo( UndoRedoInfo::Delete ); |
1094 | if ( !undoRedoInfo.valid() ) { | 1191 | if ( !undoRedoInfo.valid() ) { |
1095 | undoRedoInfo.id = cursor->parag()->paragId(); | 1192 | undoRedoInfo.id = cursor->paragraph()->paragId(); |
1096 | undoRedoInfo.index = cursor->index(); | 1193 | undoRedoInfo.index = cursor->index(); |
1097 | undoRedoInfo.d->text = QString::null; | 1194 | undoRedoInfo.d->text = QString::null; |
1098 | } | 1195 | } |
1099 | undoRedoInfo.d->text += cursor->parag()->at( cursor->index() )->c; | 1196 | undoRedoInfo.d->text.insert( undoRedoInfo.d->text.length(), cursor->paragraph()->at( cursor->index() ), TRUE ); |
1100 | if ( cursor->parag()->at( cursor->index() )->format() ) { | 1197 | cursor->remove(); |
1101 | cursor->parag()->at( cursor->index() )->format()->addRef(); | 1198 | } else { |
1102 | undoRedoInfo.d->text.at( undoRedoInfo.d->text.length() - 1 ).setFormat( cursor->parag()->at( cursor->index() )->format() ); | 1199 | clearUndoRedo(); |
1103 | } | 1200 | doc->setSelectionStart( QTextDocument::Temp, *cursor ); |
1104 | QTextParag *old = cursor->parag(); | 1201 | cursor->gotoNextLetter(); |
1105 | if ( cursor->remove() ) { | 1202 | doc->setSelectionEnd( QTextDocument::Temp, *cursor ); |
1106 | if ( old != cursor->parag() && lastFormatted == old ) | 1203 | removeSelectedText( QTextDocument::Temp ); |
1107 | lastFormatted = cursor->parag() ? cursor->parag()->prev() : 0; | ||
1108 | undoRedoInfo.d->text += "\n"; | ||
1109 | } | 1204 | } |
1110 | } break; | 1205 | break; |
1111 | case ActionBackspace: | 1206 | case ActionBackspace: |
1112 | if ( textFormat() == Qt::RichText && | 1207 | if ( textFormat() == Qt::RichText && cursor->paragraph()->isListItem() && cursor->index() == 0 ) { |
1113 | cursor->parag()->style() && | 1208 | clearUndoRedo(); |
1114 | cursor->parag()->style()->displayMode() == QStyleSheetItem::DisplayListItem && | 1209 | undoRedoInfo.type = UndoRedoInfo::Style; |
1115 | cursor->index() == 0 ) { | 1210 | undoRedoInfo.id = cursor->paragraph()->paragId(); |
1116 | cursor->parag()->decDepth(); | 1211 | undoRedoInfo.eid = undoRedoInfo.id; |
1117 | lastFormatted = cursor->parag(); | 1212 | undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); |
1213 | int ldepth = cursor->paragraph()->listDepth(); | ||
1214 | ldepth = QMAX( ldepth-1, 0 ); | ||
1215 | cursor->paragraph()->setListDepth( ldepth ); | ||
1216 | if ( ldepth == 0 ) | ||
1217 | cursor->paragraph()->setListItem( FALSE ); | ||
1218 | clearUndoRedo(); | ||
1219 | lastFormatted = cursor->paragraph(); | ||
1118 | repaintChanged(); | 1220 | repaintChanged(); |
1119 | drawCursor( TRUE ); | 1221 | drawCursor( TRUE ); |
1120 | return; | 1222 | return; |
1121 | } | 1223 | } |
1224 | if ( !cursor->atParagStart() ) { | ||
1122 | checkUndoRedoInfo( UndoRedoInfo::Delete ); | 1225 | checkUndoRedoInfo( UndoRedoInfo::Delete ); |
1123 | if ( !undoRedoInfo.valid() ) { | 1226 | if ( !undoRedoInfo.valid() ) { |
1124 | undoRedoInfo.id = cursor->parag()->paragId(); | 1227 | undoRedoInfo.id = cursor->paragraph()->paragId(); |
1125 | undoRedoInfo.index = cursor->index(); | 1228 | undoRedoInfo.index = cursor->index(); |
1126 | undoRedoInfo.d->text = QString::null; | 1229 | undoRedoInfo.d->text = QString::null; |
1127 | } | 1230 | } |
1128 | cursor->gotoPreviousLetter(); | 1231 | cursor->gotoPreviousLetter(); |
1129 | undoRedoInfo.d->text.prepend( QString( cursor->parag()->at( cursor->index() )->c ) ); | 1232 | undoRedoInfo.d->text.insert( 0, cursor->paragraph()->at( cursor->index() ), TRUE ); |
1130 | if ( cursor->parag()->at( cursor->index() )->format() ) { | ||
1131 | cursor->parag()->at( cursor->index() )->format()->addRef(); | ||
1132 | undoRedoInfo.d->text.at( 0 ).setFormat( cursor->parag()->at( cursor->index() )->format() ); | ||
1133 | } | ||
1134 | undoRedoInfo.index = cursor->index(); | ||
1135 | if ( cursor->remove() ) { | ||
1136 | undoRedoInfo.d->text.remove( 0, 1 ); | ||
1137 | undoRedoInfo.d->text.prepend( "\n" ); | ||
1138 | undoRedoInfo.index = cursor->index(); | 1233 | undoRedoInfo.index = cursor->index(); |
1139 | undoRedoInfo.id = cursor->parag()->paragId(); | 1234 | cursor->remove(); |
1235 | lastFormatted = cursor->paragraph(); | ||
1236 | } else if ( cursor->paragraph()->prev() ){ | ||
1237 | clearUndoRedo(); | ||
1238 | doc->setSelectionStart( QTextDocument::Temp, *cursor ); | ||
1239 | cursor->gotoPreviousLetter(); | ||
1240 | doc->setSelectionEnd( QTextDocument::Temp, *cursor ); | ||
1241 | removeSelectedText( QTextDocument::Temp ); | ||
1140 | } | 1242 | } |
1141 | lastFormatted = cursor->parag(); | ||
1142 | break; | 1243 | break; |
1143 | case ActionReturn: { | 1244 | case ActionReturn: |
1144 | checkUndoRedoInfo( UndoRedoInfo::Return ); | 1245 | checkUndoRedoInfo( UndoRedoInfo::Return ); |
1145 | if ( !undoRedoInfo.valid() ) { | 1246 | if ( !undoRedoInfo.valid() ) { |
1146 | undoRedoInfo.id = cursor->parag()->paragId(); | 1247 | undoRedoInfo.id = cursor->paragraph()->paragId(); |
1147 | undoRedoInfo.index = cursor->index(); | 1248 | undoRedoInfo.index = cursor->index(); |
1148 | undoRedoInfo.d->text = QString::null; | 1249 | undoRedoInfo.d->text = QString::null; |
1149 | } | 1250 | } |
1150 | undoRedoInfo.d->text += "\n"; | 1251 | undoRedoInfo.d->text += "\n"; |
1151 | cursor->splitAndInsertEmptyParag(); | 1252 | cursor->splitAndInsertEmptyParagraph(); |
1152 | if ( cursor->parag()->prev() ) { | 1253 | if ( cursor->paragraph()->prev() ) { |
1153 | lastFormatted = cursor->parag()->prev(); | 1254 | lastFormatted = cursor->paragraph()->prev(); |
1154 | lastFormatted->invalidate( 0 ); | 1255 | lastFormatted->invalidate( 0 ); |
1155 | } | 1256 | } |
1156 | doUpdateCurrentFormat = FALSE; | 1257 | doUpdateCurrentFormat = FALSE; |
1157 | } break; | 1258 | break; |
1158 | case ActionKill: | 1259 | case ActionKill: |
1159 | checkUndoRedoInfo( UndoRedoInfo::Delete ); | 1260 | clearUndoRedo(); |
1160 | if ( !undoRedoInfo.valid() ) { | 1261 | doc->setSelectionStart( QTextDocument::Temp, *cursor ); |
1161 | undoRedoInfo.id = cursor->parag()->paragId(); | 1262 | if ( cursor->atParagEnd() ) |
1162 | undoRedoInfo.index = cursor->index(); | 1263 | cursor->gotoNextLetter(); |
1163 | undoRedoInfo.d->text = QString::null; | 1264 | else |
1164 | } | 1265 | cursor->setIndex( cursor->paragraph()->length() - 1 ); |
1165 | if ( cursor->atParagEnd() ) { | 1266 | doc->setSelectionEnd( QTextDocument::Temp, *cursor ); |
1166 | undoRedoInfo.d->text += cursor->parag()->at( cursor->index() )->c; | 1267 | removeSelectedText( QTextDocument::Temp ); |
1167 | if ( cursor->parag()->at( cursor->index() )->format() ) { | ||
1168 | cursor->parag()->at( cursor->index() )->format()->addRef(); | ||
1169 | undoRedoInfo.d->text.at( undoRedoInfo.d->text.length() - 1 ).setFormat( cursor->parag()->at( cursor->index() )->format() ); | ||
1170 | } | ||
1171 | QTextParag *old = cursor->parag(); | ||
1172 | if ( cursor->remove() ) { | ||
1173 | if ( old != cursor->parag() && lastFormatted == old ) | ||
1174 | lastFormatted = cursor->parag() ? cursor->parag()->prev() : 0; | ||
1175 | undoRedoInfo.d->text += "\n"; | ||
1176 | } | ||
1177 | } else { | ||
1178 | int oldLen = undoRedoInfo.d->text.length(); | ||
1179 | undoRedoInfo.d->text += cursor->parag()->string()->toString().mid( cursor->index() ); | ||
1180 | for ( int i = cursor->index(); i < cursor->parag()->length(); ++i ) { | ||
1181 | if ( cursor->parag()->at( i )->format() ) { | ||
1182 | cursor->parag()->at( i )->format()->addRef(); | ||
1183 | undoRedoInfo.d->text.at( oldLen + i - cursor->index() ).setFormat( cursor->parag()->at( i )->format() ); | ||
1184 | } | ||
1185 | } | ||
1186 | undoRedoInfo.d->text.remove( undoRedoInfo.d->text.length() - 1, 1 ); | ||
1187 | cursor->killLine(); | ||
1188 | } | ||
1189 | break; | 1268 | break; |
1190 | } | 1269 | } |
1191 | 1270 | ||
1192 | formatMore(); | 1271 | formatMore(); |
1193 | repaintChanged(); | 1272 | repaintChanged(); |
1194 | ensureCursorVisible(); | 1273 | ensureCursorVisible(); |
1195 | drawCursor( TRUE ); | 1274 | drawCursor( TRUE ); |
1196 | 1275 | updateMicroFocusHint(); | |
1197 | if ( hasFocus() || viewport()->hasFocus() ) { | ||
1198 | int h = cursor->parag()->lineHeightOfChar( cursor->index() ); | ||
1199 | if ( !readonly ) { | ||
1200 | QFont f = cursor->parag()->at( cursor->index() )->format()->font(); | ||
1201 | setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), | ||
1202 | cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); | ||
1203 | } | ||
1204 | } | ||
1205 | |||
1206 | if ( doUpdateCurrentFormat ) | 1276 | if ( doUpdateCurrentFormat ) |
1207 | updateCurrentFormat(); | 1277 | updateCurrentFormat(); |
1208 | setModified(); | 1278 | setModified(); |
1209 | emit textChanged(); | 1279 | emit textChanged(); |
1210 | } | 1280 | } |
1211 | 1281 | ||
1212 | void QTextEdit::readFormats( QTextCursor &c1, QTextCursor &c2, int oldLen, QTextString &text, bool fillStyles ) | 1282 | void QTextEdit::readFormats( QTextCursor &c1, QTextCursor &c2, QTextString &text, bool fillStyles ) |
1213 | { | 1283 | { |
1284 | QDataStream styleStream( undoRedoInfo.styleInformation, IO_WriteOnly ); | ||
1214 | c2.restoreState(); | 1285 | c2.restoreState(); |
1215 | c1.restoreState(); | 1286 | c1.restoreState(); |
1216 | if ( c1.parag() == c2.parag() ) { | 1287 | int lastIndex = text.length(); |
1217 | for ( int i = c1.index(); i < c2.index(); ++i ) { | 1288 | if ( c1.paragraph() == c2.paragraph() ) { |
1218 | if ( c1.parag()->at( i )->format() ) { | 1289 | for ( int i = c1.index(); i < c2.index(); ++i ) |
1219 | c1.parag()->at( i )->format()->addRef(); | 1290 | text.insert( lastIndex + i - c1.index(), c1.paragraph()->at( i ), TRUE ); |
1220 | text.at( oldLen + i - c1.index() ).setFormat( c1.parag()->at( i )->format() ); | ||
1221 | } | ||
1222 | } | ||
1223 | if ( fillStyles ) { | 1291 | if ( fillStyles ) { |
1224 | undoRedoInfo.oldAligns[ 0 ] = c1.parag()->alignment(); | 1292 | styleStream << (int) 1; |
1225 | undoRedoInfo.oldStyles << c1.parag()->styleSheetItems(); | 1293 | c1.paragraph()->writeStyleInformation( styleStream ); |
1226 | undoRedoInfo.oldListStyles << c1.parag()->listStyle(); | ||
1227 | } | 1294 | } |
1228 | } else { | 1295 | } else { |
1229 | int lastIndex = oldLen; | ||
1230 | int i; | 1296 | int i; |
1231 | for ( i = c1.index(); i < c1.parag()->length(); ++i ) { | 1297 | for ( i = c1.index(); i < c1.paragraph()->length()-1; ++i ) |
1232 | if ( c1.parag()->at( i )->format() ) { | 1298 | text.insert( lastIndex++, c1.paragraph()->at( i ), TRUE ); |
1233 | c1.parag()->at( i )->format()->addRef(); | 1299 | int num = 2; // start and end, being different |
1234 | text.at( lastIndex ).setFormat( c1.parag()->at( i )->format() ); | 1300 | text += "\n"; lastIndex++; |
1235 | lastIndex++; | 1301 | QTextParagraph *p = c1.paragraph()->next(); |
1236 | } | 1302 | while ( p && p != c2.paragraph() ) { |
1237 | } | 1303 | for ( i = 0; i < p->length()-1; ++i ) |
1238 | QTextParag *p = c1.parag()->next(); | 1304 | text.insert( lastIndex++ , p->at( i ), TRUE ); |
1239 | while ( p && p != c2.parag() ) { | 1305 | text += "\n"; num++; lastIndex++; |
1240 | for ( int i = 0; i < p->length(); ++i ) { | ||
1241 | if ( p->at( i )->format() ) { | ||
1242 | p->at( i )->format()->addRef(); | ||
1243 | text.at( i + lastIndex ).setFormat( p->at( i )->format() ); | ||
1244 | } | ||
1245 | } | ||
1246 | lastIndex += p->length(); | ||
1247 | p = p->next(); | 1306 | p = p->next(); |
1248 | } | 1307 | } |
1249 | for ( i = 0; i < c2.index(); ++i ) { | 1308 | for ( i = 0; i < c2.index(); ++i ) |
1250 | if ( c2.parag()->at( i )->format() ) { | 1309 | text.insert( i + lastIndex, c2.paragraph()->at( i ), TRUE ); |
1251 | c2.parag()->at( i )->format()->addRef(); | ||
1252 | text.at( i + lastIndex ).setFormat( c2.parag()->at( i )->format() ); | ||
1253 | } | ||
1254 | } | ||
1255 | if ( fillStyles ) { | 1310 | if ( fillStyles ) { |
1256 | QTextParag *p = c1.parag(); | 1311 | styleStream << num; |
1257 | i = 0; | 1312 | for ( QTextParagraph *p = c1.paragraph(); --num >= 0; p = p->next() ) |
1258 | while ( p ) { | 1313 | p->writeStyleInformation( styleStream ); |
1259 | if ( i < (int)undoRedoInfo.oldAligns.size() ) | ||
1260 | undoRedoInfo.oldAligns[ i ] = p->alignment(); | ||
1261 | undoRedoInfo.oldStyles << p->styleSheetItems(); | ||
1262 | undoRedoInfo.oldListStyles << p->listStyle(); | ||
1263 | if ( p == c2.parag() ) | ||
1264 | break; | ||
1265 | p = p->next(); | ||
1266 | ++i; | ||
1267 | } | ||
1268 | } | 1314 | } |
1269 | } | 1315 | } |
1270 | } | 1316 | } |
1271 | 1317 | ||
1272 | /*! Removes the selection \a selNum (by default 0). This does not | 1318 | /*! Removes the selection \a selNum (by default 0). This does not |
1273 | remove the selected text. | 1319 | remove the selected text. |
1274 | 1320 | ||
1275 | \sa removeSelectedText() | 1321 | \sa removeSelectedText() |
1276 | */ | 1322 | */ |
1277 | 1323 | ||
1278 | void QTextEdit::removeSelection( int selNum ) | 1324 | void QTextEdit::removeSelection( int selNum ) |
1279 | { | 1325 | { |
1280 | doc->removeSelection( selNum ); | 1326 | doc->removeSelection( selNum ); |
1281 | repaintChanged(); | 1327 | repaintChanged(); |
1282 | } | 1328 | } |
1283 | 1329 | ||
1284 | /*! Deletes the selected text (i.e. the default selection's text) of | 1330 | /*! Deletes the selected text (i.e. the default selection's text) of |
1285 | the selection \a selNum (by default, 0). If there is no selected text | 1331 | the selection \a selNum (by default, 0). If there is no selected text |
1286 | nothing happens. | 1332 | nothing happens. |
1287 | 1333 | ||
1288 | \sa selectedText removeSelection() | 1334 | \sa selectedText removeSelection() |
1289 | */ | 1335 | */ |
1290 | 1336 | ||
1291 | void QTextEdit::removeSelectedText( int selNum ) | 1337 | void QTextEdit::removeSelectedText( int selNum ) |
1292 | { | 1338 | { |
1293 | if ( isReadOnly() ) | 1339 | if ( isReadOnly() ) |
1294 | return; | 1340 | return; |
1295 | 1341 | ||
1296 | QTextCursor c1 = doc->selectionStartCursor( selNum ); | 1342 | QTextCursor c1 = doc->selectionStartCursor( selNum ); |
1343 | c1.restoreState(); | ||
1297 | QTextCursor c2 = doc->selectionEndCursor( selNum ); | 1344 | QTextCursor c2 = doc->selectionEndCursor( selNum ); |
1345 | c2.restoreState(); | ||
1298 | 1346 | ||
1299 | // ### no support for editing tables yet | 1347 | // ### no support for editing tables yet, plus security for broken selections |
1300 | if ( c1.nestedDepth() || c2.nestedDepth() ) | 1348 | if ( c1.nestedDepth() || c2.nestedDepth() ) |
1301 | return; | 1349 | return; |
1302 | 1350 | ||
1303 | for ( int i = 0; i < (int)doc->numSelections(); ++i ) { | 1351 | for ( int i = 0; i < (int)doc->numSelections(); ++i ) { |
1304 | if ( i == selNum ) | 1352 | if ( i == selNum ) |
1305 | continue; | 1353 | continue; |
1306 | doc->removeSelection( i ); | 1354 | doc->removeSelection( i ); |
1307 | } | 1355 | } |
1308 | 1356 | ||
1309 | drawCursor( FALSE ); | 1357 | drawCursor( FALSE ); |
1310 | checkUndoRedoInfo( UndoRedoInfo::RemoveSelected ); | 1358 | checkUndoRedoInfo( UndoRedoInfo::RemoveSelected ); |
1311 | if ( !undoRedoInfo.valid() ) { | 1359 | if ( !undoRedoInfo.valid() ) { |
1312 | doc->selectionStart( selNum, undoRedoInfo.id, undoRedoInfo.index ); | 1360 | doc->selectionStart( selNum, undoRedoInfo.id, undoRedoInfo.index ); |
1313 | undoRedoInfo.d->text = QString::null; | 1361 | undoRedoInfo.d->text = QString::null; |
1314 | } | 1362 | } |
1315 | int oldLen = undoRedoInfo.d->text.length(); | 1363 | readFormats( c1, c2, undoRedoInfo.d->text, TRUE ); |
1316 | undoRedoInfo.d->text = doc->selectedText( selNum, FALSE ); | 1364 | |
1317 | undoRedoInfo.oldAligns.resize( undoRedoInfo.oldAligns.size() + QMAX( 0, c2.parag()->paragId() - c1.parag()->paragId() + 1 ) ); | 1365 | |
1318 | readFormats( c1, c2, oldLen, undoRedoInfo.d->text, TRUE ); | ||
1319 | doc->removeSelectedText( selNum, cursor ); | 1366 | doc->removeSelectedText( selNum, cursor ); |
1320 | if ( cursor->isValid() ) { | 1367 | if ( cursor->isValid() ) { |
1321 | ensureCursorVisible(); | 1368 | ensureCursorVisible(); |
1322 | lastFormatted = cursor->parag(); | 1369 | lastFormatted = cursor->paragraph(); |
1323 | formatMore(); | 1370 | formatMore(); |
1324 | repaintChanged(); | 1371 | repaintChanged(); |
1325 | ensureCursorVisible(); | 1372 | ensureCursorVisible(); |
1326 | drawCursor( TRUE ); | 1373 | drawCursor( TRUE ); |
1327 | clearUndoRedo(); | 1374 | clearUndoRedo(); |
1328 | #if defined(Q_WS_WIN) | 1375 | #if defined(Q_WS_WIN) |
1329 | // there seems to be a problem with repainting or erasing the area | 1376 | // there seems to be a problem with repainting or erasing the area |
1330 | // of the scrollview which is not the contents on windows | 1377 | // of the scrollview which is not the contents on windows |
1331 | if ( contentsHeight() < visibleHeight() ) | 1378 | if ( contentsHeight() < visibleHeight() ) |
1332 | viewport()->repaint( 0, contentsHeight(), visibleWidth(), visibleHeight() - contentsHeight(), TRUE ); | 1379 | viewport()->repaint( 0, contentsHeight(), visibleWidth(), visibleHeight() - contentsHeight(), TRUE ); |
1333 | #endif | 1380 | #endif |
1334 | #ifndef QT_NO_CURSOR | 1381 | #ifndef QT_NO_CURSOR |
1335 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); | 1382 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); |
1336 | #endif | 1383 | #endif |
1337 | if ( hasFocus() || viewport()->hasFocus() ) { | 1384 | updateMicroFocusHint(); |
1338 | int h = cursor->parag()->lineHeightOfChar( cursor->index() ); | ||
1339 | if ( !readonly ) { | ||
1340 | QFont f = cursor->parag()->at( cursor->index() )->format()->font(); | ||
1341 | setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), | ||
1342 | cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); | ||
1343 | } | ||
1344 | } | ||
1345 | } else { | 1385 | } else { |
1346 | cursor->setDocument( doc ); | 1386 | delete cursor; |
1347 | cursor->setParag( doc->firstParag() ); | 1387 | cursor = new QTextCursor( doc ); |
1348 | cursor->setIndex( 0 ); | ||
1349 | drawCursor( TRUE ); | 1388 | drawCursor( TRUE ); |
1350 | viewport()->repaint( TRUE ); | 1389 | viewport()->repaint( TRUE ); |
1351 | } | 1390 | } |
1352 | setModified(); | 1391 | setModified(); |
1353 | emit textChanged(); | 1392 | emit textChanged(); |
1354 | emit selectionChanged(); | 1393 | emit selectionChanged(); |
1355 | } | 1394 | } |
1356 | 1395 | ||
1357 | /*! Moves the text cursor according to \a action. This is normally | 1396 | /*! Moves the text cursor according to \a action. This is normally |
1358 | used by some key event handler. \a select specifies whether the text | 1397 | used by some key event handler. \a select specifies whether the text |
1359 | between the current cursor position and the new position should be | 1398 | between the current cursor position and the new position should be |
1360 | selected. | 1399 | selected. |
1361 | */ | 1400 | */ |
1362 | 1401 | ||
1363 | void QTextEdit::moveCursor( CursorAction action, bool select ) | 1402 | void QTextEdit::moveCursor( CursorAction action, bool select ) |
1364 | { | 1403 | { |
1365 | drawCursor( FALSE ); | 1404 | drawCursor( FALSE ); |
1366 | if ( select ) { | 1405 | if ( select ) { |
1367 | if ( !doc->hasSelection( QTextDocument::Standard ) ) | 1406 | if ( !doc->hasSelection( QTextDocument::Standard ) ) |
1368 | doc->setSelectionStart( QTextDocument::Standard, cursor ); | 1407 | doc->setSelectionStart( QTextDocument::Standard, *cursor ); |
1369 | moveCursor( action ); | 1408 | moveCursor( action ); |
1370 | if ( doc->setSelectionEnd( QTextDocument::Standard, cursor ) ) { | 1409 | if ( doc->setSelectionEnd( QTextDocument::Standard, *cursor ) ) { |
1371 | cursor->parag()->document()->nextDoubleBuffered = TRUE; | 1410 | cursor->paragraph()->document()->nextDoubleBuffered = TRUE; |
1372 | repaintChanged(); | 1411 | repaintChanged(); |
1373 | } else { | 1412 | } else { |
1374 | drawCursor( TRUE ); | 1413 | drawCursor( TRUE ); |
1375 | } | 1414 | } |
1376 | ensureCursorVisible(); | 1415 | ensureCursorVisible(); |
1377 | emit selectionChanged(); | 1416 | emit selectionChanged(); |
1378 | emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) ); | 1417 | emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) ); |
1379 | } else { | 1418 | } else { |
1380 | bool redraw = doc->removeSelection( QTextDocument::Standard ); | 1419 | bool redraw = doc->removeSelection( QTextDocument::Standard ); |
1381 | moveCursor( action ); | 1420 | moveCursor( action ); |
1382 | if ( !redraw ) { | 1421 | if ( !redraw ) { |
1383 | ensureCursorVisible(); | 1422 | ensureCursorVisible(); |
1384 | drawCursor( TRUE ); | 1423 | drawCursor( TRUE ); |
1385 | } else { | 1424 | } else { |
1386 | cursor->parag()->document()->nextDoubleBuffered = TRUE; | 1425 | cursor->paragraph()->document()->nextDoubleBuffered = TRUE; |
1387 | repaintChanged(); | 1426 | repaintChanged(); |
1388 | ensureCursorVisible(); | 1427 | ensureCursorVisible(); |
1389 | drawCursor( TRUE ); | 1428 | drawCursor( TRUE ); |
1390 | #ifndef QT_NO_CURSOR | 1429 | #ifndef QT_NO_CURSOR |
1391 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); | 1430 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); |
1392 | #endif | 1431 | #endif |
1393 | } | 1432 | } |
1394 | if ( redraw ) { | 1433 | if ( redraw ) { |
1395 | emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) ); | 1434 | emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) ); |
1396 | emit selectionChanged(); | 1435 | emit selectionChanged(); |
1397 | } | 1436 | } |
1398 | } | 1437 | } |
1399 | 1438 | ||
1400 | drawCursor( TRUE ); | 1439 | drawCursor( TRUE ); |
1401 | updateCurrentFormat(); | 1440 | updateCurrentFormat(); |
1402 | if ( hasFocus() || viewport()->hasFocus() ) { | 1441 | updateMicroFocusHint(); |
1403 | int h = cursor->parag()->lineHeightOfChar( cursor->index() ); | ||
1404 | if ( !readonly ) { | ||
1405 | QFont f = cursor->parag()->at( cursor->index() )->format()->font(); | ||
1406 | setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), | ||
1407 | cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); | ||
1408 | } | ||
1409 | } | ||
1410 | } | 1442 | } |
1411 | 1443 | ||
1412 | /*! \overload | 1444 | /*! \overload |
1413 | */ | 1445 | */ |
1414 | 1446 | ||
1415 | void QTextEdit::moveCursor( CursorAction action ) | 1447 | void QTextEdit::moveCursor( CursorAction action ) |
1416 | { | 1448 | { |
1417 | switch ( action ) { | 1449 | switch ( action ) { |
1418 | case MoveBackward: | 1450 | case MoveBackward: |
1419 | cursor->gotoPreviousLetter(); | 1451 | cursor->gotoPreviousLetter(); |
1420 | break; | 1452 | break; |
1421 | case MoveWordBackward: | 1453 | case MoveWordBackward: |
1422 | cursor->gotoPreviousWord(); | 1454 | cursor->gotoPreviousWord(); |
1423 | break; | 1455 | break; |
1424 | case MoveForward: | 1456 | case MoveForward: |
1425 | cursor->gotoNextLetter(); | 1457 | cursor->gotoNextLetter(); |
1426 | break; | 1458 | break; |
1427 | case MoveWordForward: | 1459 | case MoveWordForward: |
1428 | cursor->gotoNextWord(); | 1460 | cursor->gotoNextWord(); |
1429 | break; | 1461 | break; |
1430 | case MoveUp: | 1462 | case MoveUp: |
1431 | cursor->gotoUp(); | 1463 | cursor->gotoUp(); |
1432 | break; | 1464 | break; |
1433 | case MovePgUp: | 1465 | case MovePgUp: |
1434 | cursor->gotoPageUp( visibleHeight() ); | 1466 | cursor->gotoPageUp( visibleHeight() ); |
1435 | break; | 1467 | break; |
1436 | case MoveDown: | 1468 | case MoveDown: |
1437 | cursor->gotoDown(); | 1469 | cursor->gotoDown(); |
1438 | break; | 1470 | break; |
1439 | case MovePgDown: | 1471 | case MovePgDown: |
1440 | cursor->gotoPageDown( visibleHeight() ); | 1472 | cursor->gotoPageDown( visibleHeight() ); |
1441 | break; | 1473 | break; |
1442 | case MoveLineStart: | 1474 | case MoveLineStart: |
1443 | cursor->gotoLineStart(); | 1475 | cursor->gotoLineStart(); |
1444 | break; | 1476 | break; |
1445 | case MoveHome: | 1477 | case MoveHome: |
1446 | cursor->gotoHome(); | 1478 | cursor->gotoHome(); |
1447 | break; | 1479 | break; |
1448 | case MoveLineEnd: | 1480 | case MoveLineEnd: |
1449 | cursor->gotoLineEnd(); | 1481 | cursor->gotoLineEnd(); |
1450 | break; | 1482 | break; |
1451 | case MoveEnd: | 1483 | case MoveEnd: |
1452 | ensureFormatted( doc->lastParag() ); | 1484 | ensureFormatted( doc->lastParagraph() ); |
1453 | cursor->gotoEnd(); | 1485 | cursor->gotoEnd(); |
1454 | break; | 1486 | break; |
1455 | } | 1487 | } |
1456 | 1488 | updateMicroFocusHint(); | |
1457 | if ( hasFocus() || viewport()->hasFocus() ) { | ||
1458 | int h = cursor->parag()->lineHeightOfChar( cursor->index() ); | ||
1459 | if ( !readonly ) { | ||
1460 | QFont f = cursor->parag()->at( cursor->index() )->format()->font(); | ||
1461 | setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), | ||
1462 | cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); | ||
1463 | } | ||
1464 | } | ||
1465 | updateCurrentFormat(); | 1489 | updateCurrentFormat(); |
1466 | } | 1490 | } |
1467 | 1491 | ||
1468 | /*! \reimp */ | 1492 | /*! \reimp */ |
1469 | 1493 | ||
1470 | void QTextEdit::resizeEvent( QResizeEvent *e ) | 1494 | void QTextEdit::resizeEvent( QResizeEvent *e ) |
1471 | { | 1495 | { |
1472 | QScrollView::resizeEvent( e ); | 1496 | QScrollView::resizeEvent( e ); |
1497 | if ( doc->visibleWidth() == 0 ) | ||
1498 | doResize(); | ||
1473 | } | 1499 | } |
1474 | 1500 | ||
1475 | /*! \reimp */ | 1501 | /*! \reimp */ |
1476 | 1502 | ||
1477 | void QTextEdit::viewportResizeEvent( QResizeEvent *e ) | 1503 | void QTextEdit::viewportResizeEvent( QResizeEvent *e ) |
1478 | { | 1504 | { |
1479 | QScrollView::viewportResizeEvent( e ); | 1505 | QScrollView::viewportResizeEvent( e ); |
1480 | if ( e->oldSize().width() != e->size().width() ) | 1506 | if ( e->oldSize().width() != e->size().width() ) { |
1507 | bool stayAtBottom = e->oldSize().height() != e->size().height() && | ||
1508 | contentsY() > 0 && contentsY() >= doc->height() - e->oldSize().height(); | ||
1481 | doResize(); | 1509 | doResize(); |
1510 | if ( stayAtBottom ) | ||
1511 | scrollToBottom(); | ||
1512 | } | ||
1482 | } | 1513 | } |
1483 | |||
1484 | static bool blockEnsureCursorVisible = FALSE; | ||
1485 | 1514 | ||
1486 | /*! | 1515 | /*! |
1487 | Ensures that the cursor is visible by scrolling the text edit if | 1516 | Ensures that the cursor is visible by scrolling the text edit if |
1488 | necessary. | 1517 | necessary. |
1489 | 1518 | ||
1490 | \sa setCursorPosition() | 1519 | \sa setCursorPosition() |
1491 | */ | 1520 | */ |
1492 | 1521 | ||
1493 | void QTextEdit::ensureCursorVisible() | 1522 | void QTextEdit::ensureCursorVisible() |
1494 | { | 1523 | { |
1495 | if ( blockEnsureCursorVisible ) | ||
1496 | return; | ||
1497 | if ( !isVisible() ) { | 1524 | if ( !isVisible() ) { |
1498 | d->ensureCursorVisibleInShowEvent = TRUE; | 1525 | d->ensureCursorVisibleInShowEvent = TRUE; |
1499 | return; | 1526 | return; |
1500 | } | 1527 | } |
1501 | lastFormatted = cursor->parag(); | 1528 | lastFormatted = cursor->paragraph(); |
1502 | formatMore(); | 1529 | formatMore(); |
1503 | QTextStringChar *chr = cursor->parag()->at( cursor->index() ); | 1530 | QTextStringChar *chr = cursor->paragraph()->at( cursor->index() ); |
1504 | int h = cursor->parag()->lineHeightOfChar( cursor->index() ); | 1531 | int h = cursor->paragraph()->lineHeightOfChar( cursor->index() ); |
1505 | int x = cursor->parag()->rect().x() + chr->x + cursor->offsetX(); | 1532 | int x = cursor->paragraph()->rect().x() + chr->x + cursor->offsetX(); |
1506 | int y = 0; int dummy; | 1533 | int y = 0; int dummy; |
1507 | cursor->parag()->lineHeightOfChar( cursor->index(), &dummy, &y ); | 1534 | cursor->paragraph()->lineHeightOfChar( cursor->index(), &dummy, &y ); |
1508 | y += cursor->parag()->rect().y() + cursor->offsetY(); | 1535 | y += cursor->paragraph()->rect().y() + cursor->offsetY(); |
1509 | int w = 1; | 1536 | int w = 1; |
1510 | ensureVisible( x, y + h / 2, w, h / 2 + 2 ); | 1537 | ensureVisible( x, y + h / 2, w, h / 2 + 2 ); |
1511 | } | 1538 | } |
1512 | 1539 | ||
1513 | /*! | 1540 | /*! |
1514 | \internal | 1541 | \internal |
1515 | */ | 1542 | */ |
1516 | void QTextEdit::drawCursor( bool visible ) | 1543 | void QTextEdit::drawCursor( bool visible ) |
1517 | { | 1544 | { |
1518 | if ( !isUpdatesEnabled() || | 1545 | if ( !isUpdatesEnabled() || |
1519 | !viewport()->isUpdatesEnabled() || | 1546 | !viewport()->isUpdatesEnabled() || |
1520 | !cursor->parag() || | 1547 | !cursor->paragraph() || |
1521 | !cursor->parag()->isValid() || | 1548 | !cursor->paragraph()->isValid() || |
1522 | !selectedText().isEmpty() || | 1549 | !selectedText().isEmpty() || |
1523 | ( visible && !hasFocus() && !viewport()->hasFocus() && !inDnD ) || | 1550 | ( visible && !hasFocus() && !viewport()->hasFocus() && !inDnD ) || |
1524 | isReadOnly() ) | 1551 | isReadOnly() ) |
1525 | return; | 1552 | return; |
1526 | 1553 | ||
1527 | QPainter p( viewport() ); | 1554 | QPainter p( viewport() ); |
1528 | QRect r( cursor->topParag()->rect() ); | 1555 | QRect r( cursor->topParagraph()->rect() ); |
1529 | cursor->parag()->setChanged( TRUE ); | 1556 | cursor->paragraph()->setChanged( TRUE ); |
1530 | p.translate( -contentsX() + cursor->totalOffsetX(), -contentsY() + cursor->totalOffsetY() ); | 1557 | p.translate( -contentsX() + cursor->totalOffsetX(), -contentsY() + cursor->totalOffsetY() ); |
1531 | QPixmap *pix = 0; | 1558 | QPixmap *pix = 0; |
1532 | QColorGroup cg( colorGroup() ); | 1559 | QColorGroup cg( colorGroup() ); |
1533 | if ( cursor->parag()->background() ) | 1560 | if ( cursor->paragraph()->background() ) |
1534 | cg.setBrush( QColorGroup::Base, *cursor->parag()->background() ); | 1561 | cg.setBrush( QColorGroup::Base, *cursor->paragraph()->background() ); |
1535 | else if ( doc->paper() ) | 1562 | else if ( doc->paper() ) |
1536 | cg.setBrush( QColorGroup::Base, *doc->paper() ); | 1563 | cg.setBrush( QColorGroup::Base, *doc->paper() ); |
1537 | p.setBrushOrigin( -contentsX(), -contentsY() ); | 1564 | p.setBrushOrigin( -contentsX(), -contentsY() ); |
1538 | cursor->parag()->document()->nextDoubleBuffered = TRUE; | 1565 | cursor->paragraph()->document()->nextDoubleBuffered = TRUE; |
1539 | if ( !cursor->nestedDepth() ) { | 1566 | if ( !cursor->nestedDepth() ) { |
1540 | int h = cursor->parag()->lineHeightOfChar( cursor->index() ); | 1567 | int h = cursor->paragraph()->lineHeightOfChar( cursor->index() ); |
1541 | int dist = 5; | 1568 | int dist = 5; |
1542 | if ( ( cursor->parag()->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify ) | 1569 | if ( ( cursor->paragraph()->alignment() & Qt3::AlignJustify ) == Qt3::AlignJustify ) |
1543 | dist = 50; | 1570 | dist = 50; |
1544 | int x = r.x() - cursor->totalOffsetX() + cursor->x() - dist; | 1571 | int x = r.x() - cursor->totalOffsetX() + cursor->x() - dist; |
1545 | x = QMAX( x, 0 ); | 1572 | x = QMAX( x, 0 ); |
1546 | p.setClipRect( QRect( x - contentsX(), | 1573 | p.setClipRect( QRect( x - contentsX(), |
1547 | r.y() - cursor->totalOffsetY() + cursor->y() - contentsY(), 2 * dist, h ) ); | 1574 | r.y() - cursor->totalOffsetY() + cursor->y() - contentsY(), 2 * dist, h ) ); |
1548 | doc->drawParag( &p, cursor->parag(), x, | 1575 | doc->drawParagraph( &p, cursor->paragraph(), x, |
1549 | r.y() - cursor->totalOffsetY() + cursor->y(), 2 * dist, h, pix, cg, visible, cursor ); | 1576 | r.y() - cursor->totalOffsetY() + cursor->y(), 2 * dist, h, pix, cg, visible, cursor ); |
1550 | } else { | 1577 | } else { |
1551 | doc->drawParag( &p, cursor->parag(), r.x() - cursor->totalOffsetX(), | 1578 | doc->drawParagraph( &p, cursor->paragraph(), r.x() - cursor->totalOffsetX(), |
1552 | r.y() - cursor->totalOffsetY(), r.width(), r.height(), | 1579 | r.y() - cursor->totalOffsetY(), r.width(), r.height(), |
1553 | pix, cg, visible, cursor ); | 1580 | pix, cg, visible, cursor ); |
1554 | } | 1581 | } |
1555 | cursorVisible = visible; | 1582 | cursorVisible = visible; |
1556 | } | 1583 | } |
1557 | 1584 | ||
1558 | enum { | 1585 | enum { |
1559 | IdUndo = 0, | 1586 | IdUndo = 0, |
1560 | IdRedo = 1, | 1587 | IdRedo = 1, |
1561 | IdCut = 2, | 1588 | IdCut = 2, |
1562 | IdCopy = 3, | 1589 | IdCopy = 3, |
1563 | IdPaste = 4, | 1590 | IdPaste = 4, |
1564 | IdClear = 5, | 1591 | IdClear = 5, |
1565 | IdSelectAll = 6 | 1592 | IdSelectAll = 6 |
1566 | }; | 1593 | }; |
1567 | 1594 | ||
1568 | /*! \reimp */ | 1595 | /*! \reimp */ |
1569 | #ifndef QT_NO_WHEELEVENT | 1596 | #ifndef QT_NO_WHEELEVENT |
1570 | void QTextEdit::contentsWheelEvent( QWheelEvent *e ) | 1597 | void QTextEdit::contentsWheelEvent( QWheelEvent *e ) |
1571 | { | 1598 | { |
1572 | if ( isReadOnly() ) { | 1599 | if ( isReadOnly() ) { |
1573 | if ( e->state() & ControlButton ) { | 1600 | if ( e->state() & ControlButton ) { |
1574 | if ( e->delta() > 0 ) | 1601 | if ( e->delta() > 0 ) |
1575 | zoomOut(); | 1602 | zoomOut(); |
@@ -1581,78 +1608,78 @@ void QTextEdit::contentsWheelEvent( QWheelEvent *e ) | |||
1581 | QScrollView::contentsWheelEvent( e ); | 1608 | QScrollView::contentsWheelEvent( e ); |
1582 | } | 1609 | } |
1583 | #endif | 1610 | #endif |
1584 | 1611 | ||
1585 | /*! \reimp */ | 1612 | /*! \reimp */ |
1586 | 1613 | ||
1587 | void QTextEdit::contentsMousePressEvent( QMouseEvent *e ) | 1614 | void QTextEdit::contentsMousePressEvent( QMouseEvent *e ) |
1588 | { | 1615 | { |
1589 | clearUndoRedo(); | 1616 | clearUndoRedo(); |
1590 | QTextCursor oldCursor = *cursor; | 1617 | QTextCursor oldCursor = *cursor; |
1591 | QTextCursor c = *cursor; | 1618 | QTextCursor c = *cursor; |
1592 | mousePos = e->pos(); | 1619 | mousePos = e->pos(); |
1593 | mightStartDrag = FALSE; | 1620 | mightStartDrag = FALSE; |
1594 | pressedLink = QString::null; | 1621 | pressedLink = QString::null; |
1595 | 1622 | ||
1596 | if ( e->button() == LeftButton ) { | 1623 | if ( e->button() == LeftButton ) { |
1597 | mousePressed = TRUE; | 1624 | mousePressed = TRUE; |
1598 | drawCursor( FALSE ); | 1625 | drawCursor( FALSE ); |
1599 | placeCursor( e->pos() ); | 1626 | placeCursor( e->pos() ); |
1600 | ensureCursorVisible(); | 1627 | ensureCursorVisible(); |
1601 | 1628 | ||
1602 | if ( isReadOnly() && linksEnabled() ) { | 1629 | if ( isReadOnly() && linksEnabled() ) { |
1603 | QTextCursor c = *cursor; | 1630 | QTextCursor c = *cursor; |
1604 | placeCursor( e->pos(), &c, TRUE ); | 1631 | placeCursor( e->pos(), &c, TRUE ); |
1605 | if ( c.parag() && c.parag()->at( c.index() ) && | 1632 | if ( c.paragraph() && c.paragraph()->at( c.index() ) && |
1606 | c.parag()->at( c.index() )->isAnchor() ) { | 1633 | c.paragraph()->at( c.index() )->isAnchor() ) { |
1607 | pressedLink = c.parag()->at( c.index() )->anchorHref(); | 1634 | pressedLink = c.paragraph()->at( c.index() )->anchorHref(); |
1608 | } | 1635 | } |
1609 | } | 1636 | } |
1610 | 1637 | ||
1611 | #ifndef QT_NO_DRAGANDDROP | 1638 | #ifndef QT_NO_DRAGANDDROP |
1612 | if ( doc->inSelection( QTextDocument::Standard, e->pos() ) ) { | 1639 | if ( doc->inSelection( QTextDocument::Standard, e->pos() ) ) { |
1613 | mightStartDrag = TRUE; | 1640 | mightStartDrag = TRUE; |
1614 | drawCursor( TRUE ); | 1641 | drawCursor( TRUE ); |
1615 | dragStartTimer->start( QApplication::startDragTime(), TRUE ); | 1642 | dragStartTimer->start( QApplication::startDragTime(), TRUE ); |
1616 | dragStartPos = e->pos(); | 1643 | dragStartPos = e->pos(); |
1617 | return; | 1644 | return; |
1618 | } | 1645 | } |
1619 | #endif | 1646 | #endif |
1620 | 1647 | ||
1621 | bool redraw = FALSE; | 1648 | bool redraw = FALSE; |
1622 | if ( doc->hasSelection( QTextDocument::Standard ) ) { | 1649 | if ( doc->hasSelection( QTextDocument::Standard ) ) { |
1623 | if ( !( e->state() & ShiftButton ) ) { | 1650 | if ( !( e->state() & ShiftButton ) ) { |
1624 | redraw = doc->removeSelection( QTextDocument::Standard ); | 1651 | redraw = doc->removeSelection( QTextDocument::Standard ); |
1625 | doc->setSelectionStart( QTextDocument::Standard, cursor ); | 1652 | doc->setSelectionStart( QTextDocument::Standard, *cursor ); |
1626 | } else { | 1653 | } else { |
1627 | redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; | 1654 | redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw; |
1628 | } | 1655 | } |
1629 | } else { | 1656 | } else { |
1630 | if ( isReadOnly() || !( e->state() & ShiftButton ) ) { | 1657 | if ( isReadOnly() || !( e->state() & ShiftButton ) ) { |
1631 | doc->setSelectionStart( QTextDocument::Standard, cursor ); | 1658 | doc->setSelectionStart( QTextDocument::Standard, *cursor ); |
1632 | } else { | 1659 | } else { |
1633 | doc->setSelectionStart( QTextDocument::Standard, &c ); | 1660 | doc->setSelectionStart( QTextDocument::Standard, c ); |
1634 | redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; | 1661 | redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw; |
1635 | } | 1662 | } |
1636 | } | 1663 | } |
1637 | 1664 | ||
1638 | for ( int i = 1; i < doc->numSelections(); ++i ) // start with 1 as we don't want to remove the Standard-Selection | 1665 | for ( int i = 1; i < doc->numSelections(); ++i ) // start with 1 as we don't want to remove the Standard-Selection |
1639 | redraw = doc->removeSelection( i ) || redraw; | 1666 | redraw = doc->removeSelection( i ) || redraw; |
1640 | 1667 | ||
1641 | if ( !redraw ) { | 1668 | if ( !redraw ) { |
1642 | drawCursor( TRUE ); | 1669 | drawCursor( TRUE ); |
1643 | } else { | 1670 | } else { |
1644 | repaintChanged(); | 1671 | repaintChanged(); |
1645 | #ifndef QT_NO_CURSOR | 1672 | #ifndef QT_NO_CURSOR |
1646 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); | 1673 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); |
1647 | #endif | 1674 | #endif |
1648 | } | 1675 | } |
1649 | } else if ( e->button() == MidButton ) { | 1676 | } else if ( e->button() == MidButton ) { |
1650 | bool redraw = doc->removeSelection( QTextDocument::Standard ); | 1677 | bool redraw = doc->removeSelection( QTextDocument::Standard ); |
1651 | if ( !redraw ) { | 1678 | if ( !redraw ) { |
1652 | drawCursor( TRUE ); | 1679 | drawCursor( TRUE ); |
1653 | } else { | 1680 | } else { |
1654 | repaintChanged(); | 1681 | repaintChanged(); |
1655 | #ifndef QT_NO_CURSOR | 1682 | #ifndef QT_NO_CURSOR |
1656 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); | 1683 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); |
1657 | #endif | 1684 | #endif |
1658 | } | 1685 | } |
@@ -1693,85 +1720,85 @@ void QTextEdit::contentsMouseMoveEvent( QMouseEvent *e ) | |||
1693 | } | 1720 | } |
1694 | #endif | 1721 | #endif |
1695 | updateCursor( e->pos() ); | 1722 | updateCursor( e->pos() ); |
1696 | } | 1723 | } |
1697 | 1724 | ||
1698 | /*! \reimp */ | 1725 | /*! \reimp */ |
1699 | 1726 | ||
1700 | void QTextEdit::contentsMouseReleaseEvent( QMouseEvent * e ) | 1727 | void QTextEdit::contentsMouseReleaseEvent( QMouseEvent * e ) |
1701 | { | 1728 | { |
1702 | QTextCursor oldCursor = *cursor; | 1729 | QTextCursor oldCursor = *cursor; |
1703 | if ( scrollTimer->isActive() ) | 1730 | if ( scrollTimer->isActive() ) |
1704 | scrollTimer->stop(); | 1731 | scrollTimer->stop(); |
1705 | #ifndef QT_NO_DRAGANDDROP | 1732 | #ifndef QT_NO_DRAGANDDROP |
1706 | if ( dragStartTimer->isActive() ) | 1733 | if ( dragStartTimer->isActive() ) |
1707 | dragStartTimer->stop(); | 1734 | dragStartTimer->stop(); |
1708 | if ( mightStartDrag ) { | 1735 | if ( mightStartDrag ) { |
1709 | selectAll( FALSE ); | 1736 | selectAll( FALSE ); |
1710 | mousePressed = FALSE; | 1737 | mousePressed = FALSE; |
1711 | } | 1738 | } |
1712 | #endif | 1739 | #endif |
1713 | if ( mousePressed ) { | 1740 | if ( mousePressed ) { |
1714 | mousePressed = FALSE; | 1741 | mousePressed = FALSE; |
1715 | } | 1742 | } |
1716 | emit cursorPositionChanged( cursor ); | 1743 | emit cursorPositionChanged( cursor ); |
1717 | emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); | 1744 | emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); |
1718 | if ( oldCursor != *cursor ) | 1745 | if ( oldCursor != *cursor ) |
1719 | updateCurrentFormat(); | 1746 | updateCurrentFormat(); |
1720 | inDoubleClick = FALSE; | 1747 | inDoubleClick = FALSE; |
1721 | 1748 | ||
1722 | #ifndef QT_NO_NETWORKPROTOCOL | 1749 | #ifndef QT_NO_NETWORKPROTOCOL |
1723 | if ( !onLink.isEmpty() && onLink == pressedLink && linksEnabled() ) { | 1750 | if ( !onLink.isEmpty() && onLink == pressedLink && linksEnabled() ) { |
1724 | QUrl u( doc->context(), onLink, TRUE ); | 1751 | QUrl u( doc->context(), onLink, TRUE ); |
1725 | emitLinkClicked( u.toString( FALSE, FALSE ) ); | 1752 | emitLinkClicked( u.toString( FALSE, FALSE ) ); |
1726 | 1753 | ||
1727 | // emitting linkClicked() may result in that the cursor winds | 1754 | // emitting linkClicked() may result in that the cursor winds |
1728 | // up hovering over a different valid link - check this and | 1755 | // up hovering over a different valid link - check this and |
1729 | // set the appropriate cursor shape | 1756 | // set the appropriate cursor shape |
1730 | updateCursor( e->pos() ); | 1757 | updateCursor( e->pos() ); |
1731 | } | 1758 | } |
1732 | #endif | 1759 | #endif |
1733 | drawCursor( TRUE ); | 1760 | drawCursor( TRUE ); |
1734 | if ( !doc->hasSelection( QTextDocument::Standard, TRUE ) ) | 1761 | if ( !doc->hasSelection( QTextDocument::Standard, TRUE ) ) |
1735 | doc->removeSelection( QTextDocument::Standard ); | 1762 | doc->removeSelection( QTextDocument::Standard ); |
1736 | 1763 | ||
1737 | emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) ); | 1764 | emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) ); |
1738 | emit selectionChanged(); | 1765 | emit selectionChanged(); |
1739 | } | 1766 | } |
1740 | 1767 | ||
1741 | /*! \reimp */ | 1768 | /*! \reimp */ |
1742 | 1769 | ||
1743 | void QTextEdit::contentsMouseDoubleClickEvent( QMouseEvent * ) | 1770 | void QTextEdit::contentsMouseDoubleClickEvent( QMouseEvent * ) |
1744 | { | 1771 | { |
1745 | QTextCursor c1 = *cursor; | 1772 | QTextCursor c1 = *cursor; |
1746 | QTextCursor c2 = *cursor; | 1773 | QTextCursor c2 = *cursor; |
1747 | if ( cursor->index() > 0 && !cursor->parag()->at( cursor->index()-1 )->c.isSpace() ) | 1774 | if ( cursor->index() > 0 && !cursor->paragraph()->at( cursor->index()-1 )->c.isSpace() ) |
1748 | c1.gotoPreviousWord(); | 1775 | c1.gotoPreviousWord(); |
1749 | if ( !cursor->parag()->at( cursor->index() )->c.isSpace() && !cursor->atParagEnd() ) | 1776 | if ( !cursor->paragraph()->at( cursor->index() )->c.isSpace() && !cursor->atParagEnd() ) |
1750 | c2.gotoNextWord(); | 1777 | c2.gotoNextWord(); |
1751 | 1778 | ||
1752 | doc->setSelectionStart( QTextDocument::Standard, &c1 ); | 1779 | doc->setSelectionStart( QTextDocument::Standard, c1 ); |
1753 | doc->setSelectionEnd( QTextDocument::Standard, &c2 ); | 1780 | doc->setSelectionEnd( QTextDocument::Standard, c2 ); |
1754 | 1781 | ||
1755 | *cursor = c2; | 1782 | *cursor = c2; |
1756 | 1783 | ||
1757 | repaintChanged(); | 1784 | repaintChanged(); |
1758 | 1785 | ||
1759 | inDoubleClick = TRUE; | 1786 | inDoubleClick = TRUE; |
1760 | mousePressed = TRUE; | 1787 | mousePressed = TRUE; |
1761 | } | 1788 | } |
1762 | 1789 | ||
1763 | #ifndef QT_NO_DRAGANDDROP | 1790 | #ifndef QT_NO_DRAGANDDROP |
1764 | 1791 | ||
1765 | /*! \reimp */ | 1792 | /*! \reimp */ |
1766 | 1793 | ||
1767 | void QTextEdit::contentsDragEnterEvent( QDragEnterEvent *e ) | 1794 | void QTextEdit::contentsDragEnterEvent( QDragEnterEvent *e ) |
1768 | { | 1795 | { |
1769 | if ( isReadOnly() || !QTextDrag::canDecode( e ) ) { | 1796 | if ( isReadOnly() || !QTextDrag::canDecode( e ) ) { |
1770 | e->ignore(); | 1797 | e->ignore(); |
1771 | return; | 1798 | return; |
1772 | } | 1799 | } |
1773 | e->acceptAction(); | 1800 | e->acceptAction(); |
1774 | inDnD = TRUE; | 1801 | inDnD = TRUE; |
1775 | } | 1802 | } |
1776 | 1803 | ||
1777 | /*! \reimp */ | 1804 | /*! \reimp */ |
@@ -1785,602 +1812,613 @@ void QTextEdit::contentsDragMoveEvent( QDragMoveEvent *e ) | |||
1785 | drawCursor( FALSE ); | 1812 | drawCursor( FALSE ); |
1786 | placeCursor( e->pos(), cursor ); | 1813 | placeCursor( e->pos(), cursor ); |
1787 | drawCursor( TRUE ); | 1814 | drawCursor( TRUE ); |
1788 | e->acceptAction(); | 1815 | e->acceptAction(); |
1789 | } | 1816 | } |
1790 | 1817 | ||
1791 | /*! \reimp */ | 1818 | /*! \reimp */ |
1792 | 1819 | ||
1793 | void QTextEdit::contentsDragLeaveEvent( QDragLeaveEvent * ) | 1820 | void QTextEdit::contentsDragLeaveEvent( QDragLeaveEvent * ) |
1794 | { | 1821 | { |
1795 | inDnD = FALSE; | 1822 | inDnD = FALSE; |
1796 | } | 1823 | } |
1797 | 1824 | ||
1798 | /*! \reimp */ | 1825 | /*! \reimp */ |
1799 | 1826 | ||
1800 | void QTextEdit::contentsDropEvent( QDropEvent *e ) | 1827 | void QTextEdit::contentsDropEvent( QDropEvent *e ) |
1801 | { | 1828 | { |
1802 | if ( isReadOnly() ) | 1829 | if ( isReadOnly() ) |
1803 | return; | 1830 | return; |
1804 | inDnD = FALSE; | 1831 | inDnD = FALSE; |
1805 | e->acceptAction(); | 1832 | e->acceptAction(); |
1806 | QString text; | 1833 | QString text; |
1807 | bool intern = FALSE; | 1834 | bool intern = FALSE; |
1808 | if ( QTextDrag::decode( e, text ) ) { | 1835 | if ( QTextDrag::decode( e, text ) ) { |
1809 | if ( ( e->source() == this || | 1836 | bool hasSel = doc->hasSelection( QTextDocument::Standard ); |
1810 | e->source() == viewport() ) && | 1837 | bool internalDrag = e->source() == this || e->source() == viewport(); |
1811 | e->action() == QDropEvent::Move ) { | 1838 | int dropId, dropIndex; |
1839 | QTextCursor insertCursor = *cursor; | ||
1840 | dropId = cursor->paragraph()->paragId(); | ||
1841 | dropIndex = cursor->index(); | ||
1842 | if ( hasSel && internalDrag ) { | ||
1843 | QTextCursor c1, c2; | ||
1844 | int selStartId, selStartIndex; | ||
1845 | int selEndId, selEndIndex; | ||
1846 | c1 = doc->selectionStartCursor( QTextDocument::Standard ); | ||
1847 | c1.restoreState(); | ||
1848 | c2 = doc->selectionEndCursor( QTextDocument::Standard ); | ||
1849 | c2.restoreState(); | ||
1850 | selStartId = c1.paragraph()->paragId(); | ||
1851 | selStartIndex = c1.index(); | ||
1852 | selEndId = c2.paragraph()->paragId(); | ||
1853 | selEndIndex = c2.index(); | ||
1854 | if ( ( ( dropId > selStartId ) || | ||
1855 | ( dropId == selStartId && dropIndex > selStartIndex ) ) && | ||
1856 | ( ( dropId < selEndId ) || | ||
1857 | ( dropId == selEndId && dropIndex <= selEndIndex ) ) ) | ||
1858 | insertCursor = c1; | ||
1859 | if ( dropId == selEndId && dropIndex > selEndIndex ) { | ||
1860 | insertCursor = c1; | ||
1861 | if ( selStartId == selEndId ) { | ||
1862 | insertCursor.setIndex( dropIndex - | ||
1863 | ( selEndIndex - selStartIndex ) ); | ||
1864 | } else { | ||
1865 | insertCursor.setIndex( dropIndex - selEndIndex + | ||
1866 | selStartIndex ); | ||
1867 | } | ||
1868 | } | ||
1869 | } | ||
1870 | |||
1871 | if ( internalDrag && e->action() == QDropEvent::Move ) { | ||
1812 | removeSelectedText(); | 1872 | removeSelectedText(); |
1813 | intern = TRUE; | 1873 | intern = TRUE; |
1814 | } else { | 1874 | } else { |
1815 | doc->removeSelection( QTextDocument::Standard ); | 1875 | doc->removeSelection( QTextDocument::Standard ); |
1816 | #ifndef QT_NO_CURSOR | 1876 | #ifndef QT_NO_CURSOR |
1817 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); | 1877 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); |
1818 | #endif | 1878 | #endif |
1819 | } | 1879 | } |
1820 | drawCursor( FALSE ); | 1880 | drawCursor( FALSE ); |
1821 | placeCursor( e->pos(), cursor ); | 1881 | cursor->setParagraph( insertCursor.paragraph() ); |
1882 | cursor->setIndex( insertCursor.index() ); | ||
1822 | drawCursor( TRUE ); | 1883 | drawCursor( TRUE ); |
1823 | if ( !cursor->nestedDepth() ) { | 1884 | if ( !cursor->nestedDepth() ) { |
1824 | insert( text, FALSE, TRUE, FALSE ); | 1885 | insert( text, FALSE, TRUE, FALSE ); |
1825 | } else { | 1886 | } else { |
1826 | if ( intern ) | 1887 | if ( intern ) |
1827 | undo(); | 1888 | undo(); |
1828 | e->ignore(); | 1889 | e->ignore(); |
1829 | } | 1890 | } |
1830 | } | 1891 | } |
1831 | } | 1892 | } |
1832 | 1893 | ||
1833 | #endif | 1894 | #endif |
1834 | 1895 | ||
1835 | void QTextEdit::autoScrollTimerDone() | 1896 | void QTextEdit::autoScrollTimerDone() |
1836 | { | 1897 | { |
1837 | if ( mousePressed ) | 1898 | if ( mousePressed ) |
1838 | handleMouseMove( viewportToContents( viewport()->mapFromGlobal( QCursor::pos() ) ) ); | 1899 | handleMouseMove( viewportToContents( viewport()->mapFromGlobal( QCursor::pos() ) ) ); |
1839 | } | 1900 | } |
1840 | 1901 | ||
1841 | void QTextEdit::handleMouseMove( const QPoint& pos ) | 1902 | void QTextEdit::handleMouseMove( const QPoint& pos ) |
1842 | { | 1903 | { |
1843 | if ( !mousePressed ) | 1904 | if ( !mousePressed ) |
1844 | return; | 1905 | return; |
1845 | 1906 | ||
1846 | if ( !scrollTimer->isActive() && pos.y() < contentsY() || pos.y() > contentsY() + visibleHeight() ) | 1907 | if ( !scrollTimer->isActive() && pos.y() < contentsY() || pos.y() > contentsY() + visibleHeight() ) |
1847 | scrollTimer->start( 100, FALSE ); | 1908 | scrollTimer->start( 100, FALSE ); |
1848 | else if ( scrollTimer->isActive() && pos.y() >= contentsY() && pos.y() <= contentsY() + visibleHeight() ) | 1909 | else if ( scrollTimer->isActive() && pos.y() >= contentsY() && pos.y() <= contentsY() + visibleHeight() ) |
1849 | scrollTimer->stop(); | 1910 | scrollTimer->stop(); |
1850 | 1911 | ||
1851 | drawCursor( FALSE ); | 1912 | drawCursor( FALSE ); |
1852 | QTextCursor oldCursor = *cursor; | 1913 | QTextCursor oldCursor = *cursor; |
1853 | 1914 | ||
1854 | placeCursor( pos ); | 1915 | placeCursor( pos ); |
1855 | 1916 | ||
1856 | if ( inDoubleClick ) { | 1917 | if ( inDoubleClick ) { |
1857 | QTextCursor cl = *cursor; | 1918 | QTextCursor cl = *cursor; |
1858 | cl.gotoPreviousWord(); | 1919 | cl.gotoPreviousWord(); |
1859 | QTextCursor cr = *cursor; | 1920 | QTextCursor cr = *cursor; |
1860 | cr.gotoNextWord(); | 1921 | cr.gotoNextWord(); |
1861 | 1922 | ||
1862 | int diff = QABS( oldCursor.parag()->at( oldCursor.index() )->x - mousePos.x() ); | 1923 | int diff = QABS( oldCursor.paragraph()->at( oldCursor.index() )->x - mousePos.x() ); |
1863 | int ldiff = QABS( cl.parag()->at( cl.index() )->x - mousePos.x() ); | 1924 | int ldiff = QABS( cl.paragraph()->at( cl.index() )->x - mousePos.x() ); |
1864 | int rdiff = QABS( cr.parag()->at( cr.index() )->x - mousePos.x() ); | 1925 | int rdiff = QABS( cr.paragraph()->at( cr.index() )->x - mousePos.x() ); |
1865 | 1926 | ||
1866 | 1927 | ||
1867 | if ( cursor->parag()->lineStartOfChar( cursor->index() ) != | 1928 | if ( cursor->paragraph()->lineStartOfChar( cursor->index() ) != |
1868 | oldCursor.parag()->lineStartOfChar( oldCursor.index() ) ) | 1929 | oldCursor.paragraph()->lineStartOfChar( oldCursor.index() ) ) |
1869 | diff = 0xFFFFFF; | 1930 | diff = 0xFFFFFF; |
1870 | 1931 | ||
1871 | if ( rdiff < diff && rdiff < ldiff ) | 1932 | if ( rdiff < diff && rdiff < ldiff ) |
1872 | *cursor = cr; | 1933 | *cursor = cr; |
1873 | else if ( ldiff < diff && ldiff < rdiff ) | 1934 | else if ( ldiff < diff && ldiff < rdiff ) |
1874 | *cursor = cl; | 1935 | *cursor = cl; |
1875 | else | 1936 | else |
1876 | *cursor = oldCursor; | 1937 | *cursor = oldCursor; |
1877 | 1938 | ||
1878 | } | 1939 | } |
1879 | ensureCursorVisible(); | 1940 | ensureCursorVisible(); |
1880 | 1941 | ||
1881 | bool redraw = FALSE; | 1942 | bool redraw = FALSE; |
1882 | if ( doc->hasSelection( QTextDocument::Standard ) ) { | 1943 | if ( doc->hasSelection( QTextDocument::Standard ) ) { |
1883 | redraw = doc->setSelectionEnd( QTextDocument::Standard, cursor ) || redraw; | 1944 | redraw = doc->setSelectionEnd( QTextDocument::Standard, *cursor ) || redraw; |
1884 | } | 1945 | } |
1885 | 1946 | ||
1886 | if ( !redraw ) { | 1947 | if ( !redraw ) { |
1887 | drawCursor( TRUE ); | 1948 | drawCursor( TRUE ); |
1888 | } else { | 1949 | } else { |
1889 | repaintChanged(); | 1950 | repaintChanged(); |
1890 | drawCursor( TRUE ); | 1951 | drawCursor( TRUE ); |
1891 | } | 1952 | } |
1892 | 1953 | ||
1893 | if ( currentFormat && currentFormat->key() != cursor->parag()->at( cursor->index() )->format()->key() ) { | 1954 | if ( currentFormat && currentFormat->key() != cursor->paragraph()->at( cursor->index() )->format()->key() ) { |
1894 | currentFormat->removeRef(); | 1955 | currentFormat->removeRef(); |
1895 | currentFormat = doc->formatCollection()->format( cursor->parag()->at( cursor->index() )->format() ); | 1956 | currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( cursor->index() )->format() ); |
1896 | if ( currentFormat->isMisspelled() ) { | 1957 | if ( currentFormat->isMisspelled() ) { |
1897 | currentFormat->removeRef(); | 1958 | currentFormat->removeRef(); |
1898 | currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); | 1959 | currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); |
1899 | } | 1960 | } |
1900 | emit currentFontChanged( currentFormat->font() ); | 1961 | emit currentFontChanged( currentFormat->font() ); |
1901 | emit currentColorChanged( currentFormat->color() ); | 1962 | emit currentColorChanged( currentFormat->color() ); |
1902 | emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); | 1963 | emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); |
1903 | } | 1964 | } |
1904 | 1965 | ||
1905 | if ( currentAlignment != cursor->parag()->alignment() ) { | 1966 | if ( currentAlignment != cursor->paragraph()->alignment() ) { |
1906 | currentAlignment = cursor->parag()->alignment(); | 1967 | currentAlignment = cursor->paragraph()->alignment(); |
1907 | block_set_alignment = TRUE; | 1968 | block_set_alignment = TRUE; |
1908 | emit currentAlignmentChanged( currentAlignment ); | 1969 | emit currentAlignmentChanged( currentAlignment ); |
1909 | block_set_alignment = FALSE; | 1970 | block_set_alignment = FALSE; |
1910 | } | 1971 | } |
1911 | } | 1972 | } |
1912 | 1973 | ||
1913 | /*! | 1974 | /*! |
1914 | \fn void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c ) | 1975 | \fn void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c ) |
1915 | Places the cursor \a c at the character which is closest to position | 1976 | Places the cursor \a c at the character which is closest to position |
1916 | \a pos (in contents coordinates). If \a c is 0, the default text | 1977 | \a pos (in contents coordinates). If \a c is 0, the default text |
1917 | cursor is used. | 1978 | cursor is used. |
1918 | 1979 | ||
1919 | \sa setCursorPosition() | 1980 | \sa setCursorPosition() |
1920 | */ | 1981 | */ |
1921 | 1982 | ||
1922 | void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c, bool link ) | 1983 | void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c, bool link ) |
1923 | { | 1984 | { |
1924 | if ( !c ) | 1985 | if ( !c ) |
1925 | c = cursor; | 1986 | c = cursor; |
1926 | 1987 | ||
1927 | c->restoreState(); | 1988 | c->restoreState(); |
1928 | QTextParag *s = doc->firstParag(); | 1989 | QTextParagraph *s = doc->firstParagraph(); |
1929 | c->place( pos, s, link ); | 1990 | c->place( pos, s, link ); |
1991 | updateMicroFocusHint(); | ||
1992 | } | ||
1993 | |||
1994 | |||
1995 | void QTextEdit::updateMicroFocusHint() | ||
1996 | { | ||
1997 | QTextCursor c( *cursor ); | ||
1998 | if ( d->preeditStart != -1 ) | ||
1999 | c.setIndex( d->preeditStart ); | ||
2000 | |||
1930 | if ( hasFocus() || viewport()->hasFocus() ) { | 2001 | if ( hasFocus() || viewport()->hasFocus() ) { |
1931 | int h = cursor->parag()->lineHeightOfChar( cursor->index() ); | 2002 | int h = c.paragraph()->lineHeightOfChar( cursor->index() ); |
1932 | if ( !readonly ) { | 2003 | if ( !readonly ) { |
1933 | QFont f = cursor->parag()->at( cursor->index() )->format()->font(); | 2004 | QFont f = c.paragraph()->at( c.index() )->format()->font(); |
1934 | setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), | 2005 | setMicroFocusHint( c.x() - contentsX() + frameWidth(), |
1935 | cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); | 2006 | c.y() + cursor->paragraph()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); |
1936 | } | 2007 | } |
1937 | } | 2008 | } |
1938 | } | 2009 | } |
1939 | 2010 | ||
2011 | |||
2012 | |||
1940 | void QTextEdit::formatMore() | 2013 | void QTextEdit::formatMore() |
1941 | { | 2014 | { |
1942 | if ( !lastFormatted ) | 2015 | if ( !lastFormatted ) |
1943 | return; | 2016 | return; |
1944 | 2017 | ||
1945 | int bottom = contentsHeight(); | 2018 | int bottom = contentsHeight(); |
1946 | int lastBottom = -1; | 2019 | int lastBottom = -1; |
1947 | int to = !sender() ? 2 : 20; | 2020 | int to = 20; |
1948 | bool firstVisible = FALSE; | 2021 | bool firstVisible = FALSE; |
1949 | QRect cr( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); | 2022 | QRect cr( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); |
1950 | for ( int i = 0; ( i < to || firstVisible ) && lastFormatted; ++i ) { | 2023 | for ( int i = 0; ( i < to || firstVisible ) && lastFormatted; ++i ) { |
1951 | lastFormatted->format(); | 2024 | lastFormatted->format(); |
1952 | if ( i == 0 ) | 2025 | if ( i == 0 ) |
1953 | firstVisible = lastFormatted->rect().intersects( cr ); | 2026 | firstVisible = lastFormatted->rect().intersects( cr ); |
1954 | else if ( firstVisible ) | 2027 | else if ( firstVisible ) |
1955 | firstVisible = lastFormatted->rect().intersects( cr ); | 2028 | firstVisible = lastFormatted->rect().intersects( cr ); |
1956 | bottom = QMAX( bottom, lastFormatted->rect().top() + | 2029 | bottom = QMAX( bottom, lastFormatted->rect().top() + |
1957 | lastFormatted->rect().height() ); | 2030 | lastFormatted->rect().height() ); |
1958 | lastBottom = lastFormatted->rect().top() + lastFormatted->rect().height(); | 2031 | lastBottom = lastFormatted->rect().top() + lastFormatted->rect().height(); |
1959 | lastFormatted = lastFormatted->next(); | 2032 | lastFormatted = lastFormatted->next(); |
1960 | if ( lastFormatted ) | 2033 | if ( lastFormatted ) |
1961 | lastBottom = -1; | 2034 | lastBottom = -1; |
1962 | } | 2035 | } |
1963 | 2036 | ||
1964 | if ( bottom > contentsHeight() ) | 2037 | if ( bottom > contentsHeight() ) { |
1965 | resizeContents( contentsWidth(), QMAX( doc->height(), bottom ) ); | 2038 | resizeContents( contentsWidth(), QMAX( doc->height(), bottom ) ); |
1966 | else if ( lastBottom != -1 && lastBottom < contentsHeight() ) | 2039 | } else if ( lastBottom != -1 && lastBottom < contentsHeight() ) { |
1967 | resizeContents( contentsWidth(), QMAX( doc->height(), lastBottom ) ); | 2040 | resizeContents( contentsWidth(), QMAX( doc->height(), lastBottom ) ); |
2041 | if ( contentsHeight() < visibleHeight() ) | ||
2042 | updateContents( 0, contentsHeight(), visibleWidth(), | ||
2043 | visibleHeight() - contentsHeight() ); | ||
2044 | } | ||
1968 | 2045 | ||
1969 | if ( lastFormatted ) | 2046 | if ( lastFormatted ) |
1970 | formatTimer->start( interval, TRUE ); | 2047 | formatTimer->start( interval, TRUE ); |
1971 | else | 2048 | else |
1972 | interval = QMAX( 0, interval ); | 2049 | interval = QMAX( 0, interval ); |
1973 | } | 2050 | } |
1974 | 2051 | ||
1975 | void QTextEdit::doResize() | 2052 | void QTextEdit::doResize() |
1976 | { | 2053 | { |
1977 | if ( wrapMode == FixedPixelWidth ) | 2054 | if ( wrapMode == FixedPixelWidth ) |
1978 | return; | 2055 | return; |
1979 | doc->setMinimumWidth( -1 ); | 2056 | doc->setMinimumWidth( -1 ); |
1980 | resizeContents( 0, 0 ); | 2057 | resizeContents( 0, 0 ); |
1981 | doc->setWidth( visibleWidth() ); | 2058 | doc->setWidth( visibleWidth() ); |
1982 | doc->invalidate(); | 2059 | doc->invalidate(); |
1983 | lastFormatted = doc->firstParag(); | 2060 | lastFormatted = doc->firstParagraph(); |
1984 | interval = 0; | 2061 | interval = 0; |
1985 | formatMore(); | 2062 | formatMore(); |
1986 | repaintContents( contentsX(), contentsY(), visibleWidth(), visibleHeight(), FALSE ); | 2063 | repaintContents( contentsX(), contentsY(), visibleWidth(), visibleHeight(), FALSE ); |
1987 | } | 2064 | } |
1988 | 2065 | ||
1989 | /*! \internal */ | 2066 | /*! \internal */ |
1990 | 2067 | ||
1991 | void QTextEdit::doChangeInterval() | 2068 | void QTextEdit::doChangeInterval() |
1992 | { | 2069 | { |
1993 | interval = 0; | 2070 | interval = 0; |
1994 | } | 2071 | } |
1995 | 2072 | ||
1996 | /*! \reimp */ | 2073 | /*! \reimp */ |
1997 | 2074 | ||
1998 | bool QTextEdit::eventFilter( QObject *o, QEvent *e ) | 2075 | bool QTextEdit::eventFilter( QObject *o, QEvent *e ) |
1999 | { | 2076 | { |
2000 | if ( o == this || o == viewport() ) { | 2077 | if ( o == this || o == viewport() ) { |
2001 | if ( e->type() == QEvent::FocusIn ) { | 2078 | if ( e->type() == QEvent::FocusIn ) { |
2002 | blinkTimer->start( QApplication::cursorFlashTime() / 2 ); | 2079 | blinkTimer->start( QApplication::cursorFlashTime() / 2 ); |
2003 | drawCursor( TRUE ); | 2080 | drawCursor( TRUE ); |
2004 | 2081 | updateMicroFocusHint(); | |
2005 | if ( !readonly ) { | ||
2006 | // make sure the micro focus hint is updated... | ||
2007 | QFont f = cursor->parag()->at( cursor->index() )->format()->font(); | ||
2008 | setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), | ||
2009 | cursor->y() + cursor->parag()->rect().y() - | ||
2010 | contentsY() + frameWidth(), 0, | ||
2011 | cursor->parag()->lineHeightOfChar( cursor->index() ), | ||
2012 | TRUE ); | ||
2013 | } | ||
2014 | } else if ( e->type() == QEvent::FocusOut ) { | 2082 | } else if ( e->type() == QEvent::FocusOut ) { |
2015 | blinkTimer->stop(); | 2083 | blinkTimer->stop(); |
2016 | drawCursor( FALSE ); | 2084 | drawCursor( FALSE ); |
2017 | } | 2085 | } |
2018 | } | 2086 | } |
2019 | 2087 | ||
2020 | return QScrollView::eventFilter( o, e ); | 2088 | return QScrollView::eventFilter( o, e ); |
2021 | } | 2089 | } |
2022 | 2090 | ||
2023 | /*! | 2091 | /*! Inserts \a text at the current cursor position. If \a indent is |
2024 | Inserts \a text at the current cursor position. If \a indent is TRUE, | 2092 | TRUE, the paragraph is re-indented. If \a checkNewLine is TRUE, |
2025 | the paragraph is re-indented. If \a checkNewLine is TRUE, newline | 2093 | newline characters in \a text result in hard line breaks (i.e. new |
2026 | characters in \a text result in hard line breaks (i.e. new | 2094 | paragraphs). If \a checkNewLine is FALSE and there are newlines in |
2027 | paragraphs). If \a checkNewLine is FALSE the behaviour of the editor | 2095 | \a text, the behavior is undefined. If \a checkNewLine is FALSE the |
2028 | is undefined if the \a text contains newlines. If \a removeSelected is | 2096 | behaviour of the editor is undefined if the \a text contains |
2029 | TRUE, any selected text (in selection 0) is removed before the text is | 2097 | newlines. If \a removeSelected is TRUE, any selected text (in |
2030 | inserted. | 2098 | selection 0) is removed before the text is inserted. |
2031 | 2099 | ||
2032 | \sa paste() pasteSubType() | 2100 | \sa paste() pasteSubType() |
2033 | */ | 2101 | */ |
2034 | 2102 | ||
2035 | void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, bool removeSelected ) | 2103 | void QTextEdit::insert( const QString &text, bool indent, bool checkNewLine, bool removeSelected ) |
2036 | { | 2104 | { |
2037 | if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough | 2105 | if ( cursor->nestedDepth() != 0 ) // #### for 3.0, disable editing of tables as this is not advanced enough |
2038 | return; | 2106 | return; |
2039 | QString txt( text ); | 2107 | QString txt( text ); |
2040 | drawCursor( FALSE ); | 2108 | drawCursor( FALSE ); |
2041 | if ( !isReadOnly() && doc->hasSelection( QTextDocument::Standard ) && removeSelected ) | 2109 | if ( !isReadOnly() && doc->hasSelection( QTextDocument::Standard ) && removeSelected ) |
2042 | removeSelectedText(); | 2110 | removeSelectedText(); |
2043 | QTextCursor c2 = *cursor; | 2111 | QTextCursor c2 = *cursor; |
2044 | int oldLen = 0; | 2112 | int oldLen = 0; |
2045 | 2113 | ||
2046 | if ( undoEnabled && !isReadOnly() ) { | 2114 | if ( undoEnabled && !isReadOnly() ) { |
2047 | checkUndoRedoInfo( UndoRedoInfo::Insert ); | 2115 | checkUndoRedoInfo( UndoRedoInfo::Insert ); |
2048 | if ( !undoRedoInfo.valid() ) { | 2116 | if ( !undoRedoInfo.valid() ) { |
2049 | undoRedoInfo.id = cursor->parag()->paragId(); | 2117 | undoRedoInfo.id = cursor->paragraph()->paragId(); |
2050 | undoRedoInfo.index = cursor->index(); | 2118 | undoRedoInfo.index = cursor->index(); |
2051 | undoRedoInfo.d->text = QString::null; | 2119 | undoRedoInfo.d->text = QString::null; |
2052 | } | 2120 | } |
2053 | oldLen = undoRedoInfo.d->text.length(); | 2121 | oldLen = undoRedoInfo.d->text.length(); |
2054 | } | 2122 | } |
2055 | 2123 | ||
2056 | lastFormatted = checkNewLine && cursor->parag()->prev() ? | 2124 | lastFormatted = checkNewLine && cursor->paragraph()->prev() ? |
2057 | cursor->parag()->prev() : cursor->parag(); | 2125 | cursor->paragraph()->prev() : cursor->paragraph(); |
2058 | QTextCursor oldCursor = *cursor; | 2126 | QTextCursor oldCursor = *cursor; |
2059 | cursor->insert( txt, checkNewLine ); | 2127 | cursor->insert( txt, checkNewLine ); |
2060 | if ( doc->useFormatCollection() ) { | 2128 | if ( doc->useFormatCollection() ) { |
2061 | doc->setSelectionStart( QTextDocument::Temp, &oldCursor ); | 2129 | doc->setSelectionStart( QTextDocument::Temp, oldCursor ); |
2062 | doc->setSelectionEnd( QTextDocument::Temp, cursor ); | 2130 | doc->setSelectionEnd( QTextDocument::Temp, *cursor ); |
2063 | doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format ); | 2131 | doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format ); |
2064 | doc->removeSelection( QTextDocument::Temp ); | 2132 | doc->removeSelection( QTextDocument::Temp ); |
2065 | } | 2133 | } |
2066 | 2134 | ||
2067 | if ( indent && ( txt == "{" || txt == "}" || txt == ":" || txt == "#" ) ) | 2135 | if ( indent && ( txt == "{" || txt == "}" || txt == ":" || txt == "#" ) ) |
2068 | cursor->indent(); | 2136 | cursor->indent(); |
2069 | formatMore(); | 2137 | formatMore(); |
2070 | repaintChanged(); | 2138 | repaintChanged(); |
2071 | ensureCursorVisible(); | 2139 | ensureCursorVisible(); |
2072 | drawCursor( TRUE ); | 2140 | drawCursor( TRUE ); |
2073 | 2141 | ||
2074 | if ( undoEnabled && !isReadOnly() ) { | 2142 | if ( undoEnabled && !isReadOnly() ) { |
2075 | undoRedoInfo.d->text += txt; | 2143 | undoRedoInfo.d->text += txt; |
2076 | if ( !doc->preProcessor() ) { | 2144 | if ( !doc->preProcessor() ) { |
2077 | for ( int i = 0; i < (int)txt.length(); ++i ) { | 2145 | for ( int i = 0; i < (int)txt.length(); ++i ) { |
2078 | if ( txt[ i ] != '\n' && c2.parag()->at( c2.index() )->format() ) { | 2146 | if ( txt[ i ] != '\n' && c2.paragraph()->at( c2.index() )->format() ) { |
2079 | c2.parag()->at( c2.index() )->format()->addRef(); | 2147 | c2.paragraph()->at( c2.index() )->format()->addRef(); |
2080 | undoRedoInfo.d->text.setFormat( oldLen + i, c2.parag()->at( c2.index() )->format(), TRUE ); | 2148 | undoRedoInfo.d->text.setFormat( oldLen + i, c2.paragraph()->at( c2.index() )->format(), TRUE ); |
2081 | } | 2149 | } |
2082 | c2.gotoNextLetter(); | 2150 | c2.gotoNextLetter(); |
2083 | } | 2151 | } |
2084 | } | 2152 | } |
2085 | } | 2153 | } |
2086 | 2154 | ||
2087 | setModified(); | ||
2088 | emit textChanged(); | ||
2089 | if ( !removeSelected ) { | 2155 | if ( !removeSelected ) { |
2090 | doc->setSelectionStart( QTextDocument::Standard, &oldCursor ); | 2156 | doc->setSelectionStart( QTextDocument::Standard, oldCursor ); |
2091 | doc->setSelectionEnd( QTextDocument::Standard, cursor ); | 2157 | doc->setSelectionEnd( QTextDocument::Standard, *cursor ); |
2092 | repaintChanged(); | 2158 | repaintChanged(); |
2093 | } | 2159 | } |
2094 | if ( hasFocus() || viewport()->hasFocus() ) { | 2160 | updateMicroFocusHint(); |
2095 | int h = cursor->parag()->lineHeightOfChar( cursor->index() ); | 2161 | setModified(); |
2096 | if ( !readonly ) { | 2162 | emit textChanged(); |
2097 | QFont f = cursor->parag()->at( cursor->index() )->format()->font(); | ||
2098 | setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), | ||
2099 | cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); | ||
2100 | } | ||
2101 | } | ||
2102 | } | 2163 | } |
2103 | 2164 | ||
2104 | /*! Inserts \a text in the paragraph \a para and position \a index */ | 2165 | /*! Inserts \a text in the paragraph \a para and position \a index */ |
2105 | 2166 | ||
2106 | void QTextEdit::insertAt( const QString &text, int para, int index ) | 2167 | void QTextEdit::insertAt( const QString &text, int para, int index ) |
2107 | { | 2168 | { |
2108 | QTextParag *p = doc->paragAt( para ); | 2169 | removeSelection( QTextDocument::Standard ); |
2170 | QTextParagraph *p = doc->paragAt( para ); | ||
2109 | if ( !p ) | 2171 | if ( !p ) |
2110 | return; | 2172 | return; |
2111 | QTextCursor tmp = *cursor; | 2173 | QTextCursor tmp = *cursor; |
2112 | cursor->setParag( p ); | 2174 | cursor->setParagraph( p ); |
2113 | cursor->setIndex( index ); | 2175 | cursor->setIndex( index ); |
2114 | insert( text, FALSE, TRUE, FALSE ); | 2176 | insert( text, FALSE, TRUE, FALSE ); |
2115 | *cursor = tmp; | 2177 | *cursor = tmp; |
2116 | removeSelection( QTextDocument::Standard ); | 2178 | removeSelection( QTextDocument::Standard ); |
2117 | } | 2179 | } |
2118 | 2180 | ||
2119 | /*! Inserts \a text as the paragraph at position \a para. If \a para | 2181 | /*! Inserts \a text as the paragraph at position \a para. If \a para |
2120 | is -1, the text is appended. | 2182 | is -1, the text is appended. |
2121 | */ | 2183 | */ |
2122 | 2184 | ||
2123 | void QTextEdit::insertParagraph( const QString &text, int para ) | 2185 | void QTextEdit::insertParagraph( const QString &text, int para ) |
2124 | { | 2186 | { |
2125 | QTextParag *p = doc->paragAt( para ); | 2187 | QTextParagraph *p = doc->paragAt( para ); |
2126 | if ( p ) { | 2188 | if ( p ) { |
2127 | QTextCursor tmp( doc ); | 2189 | QTextCursor tmp( doc ); |
2128 | tmp.setParag( p ); | 2190 | tmp.setParagraph( p ); |
2129 | tmp.setIndex( 0 ); | 2191 | tmp.setIndex( 0 ); |
2130 | tmp.insert( text, TRUE ); | 2192 | tmp.insert( text, TRUE ); |
2131 | tmp.splitAndInsertEmptyParag(); | 2193 | tmp.splitAndInsertEmptyParagraph(); |
2132 | repaintChanged(); | 2194 | repaintChanged(); |
2133 | } else { | 2195 | } else { |
2134 | append( text ); | 2196 | append( text ); |
2135 | } | 2197 | } |
2136 | } | 2198 | } |
2137 | 2199 | ||
2138 | /*! Removes the paragraph \a para */ | 2200 | /*! Removes the paragraph \a para */ |
2139 | 2201 | ||
2140 | void QTextEdit::removeParagraph( int para ) | 2202 | void QTextEdit::removeParagraph( int para ) |
2141 | { | 2203 | { |
2142 | QTextParag *p = doc->paragAt( para ); | 2204 | QTextParagraph *p = doc->paragAt( para ); |
2143 | if ( !p ) | 2205 | if ( !p ) |
2144 | return; | 2206 | return; |
2145 | for ( int i = 0; i < doc->numSelections(); ++i ) | 2207 | for ( int i = 0; i < doc->numSelections(); ++i ) |
2146 | doc->removeSelection( i ); | 2208 | doc->removeSelection( i ); |
2147 | 2209 | ||
2148 | if ( p == doc->firstParag() && p == doc->lastParag() ) { | 2210 | if ( p == doc->firstParagraph() && p == doc->lastParagraph() ) { |
2149 | p->remove( 0, p->length() - 1 ); | 2211 | p->remove( 0, p->length() - 1 ); |
2150 | repaintChanged(); | 2212 | repaintChanged(); |
2151 | return; | 2213 | return; |
2152 | } | 2214 | } |
2153 | drawCursor( FALSE ); | 2215 | drawCursor( FALSE ); |
2154 | bool resetCursor = cursor->parag() == p; | 2216 | bool resetCursor = cursor->paragraph() == p; |
2155 | if ( p->prev() ) | 2217 | if ( p->prev() ) |
2156 | p->prev()->setNext( p->next() ); | 2218 | p->prev()->setNext( p->next() ); |
2157 | else | 2219 | else |
2158 | doc->setFirstParag( p->next() ); | 2220 | doc->setFirstParagraph( p->next() ); |
2159 | if ( p->next() ) | 2221 | if ( p->next() ) |
2160 | p->next()->setPrev( p->prev() ); | 2222 | p->next()->setPrev( p->prev() ); |
2161 | else | 2223 | else |
2162 | doc->setLastParag( p->prev() ); | 2224 | doc->setLastParagraph( p->prev() ); |
2163 | QTextParag *start = p->next(); | 2225 | QTextParagraph *start = p->next(); |
2164 | int h = p->rect().height(); | 2226 | int h = p->rect().height(); |
2165 | delete p; | 2227 | delete p; |
2166 | p = start; | 2228 | p = start; |
2167 | int dy = -h; | 2229 | int dy = -h; |
2168 | while ( p ) { | 2230 | while ( p ) { |
2169 | p->setParagId( p->prev() ? p->prev()->paragId() + 1 : 0 ); | 2231 | p->setParagId( p->prev() ? p->prev()->paragId() + 1 : 0 ); |
2170 | p->move( dy ); | 2232 | p->move( dy ); |
2171 | p->invalidate( 0 ); | 2233 | p->invalidate( 0 ); |
2172 | p->setEndState( -1 ); | 2234 | p->setEndState( -1 ); |
2173 | p = p->next(); | 2235 | p = p->next(); |
2174 | } | 2236 | } |
2175 | 2237 | ||
2176 | if ( resetCursor ) { | 2238 | if ( resetCursor ) { |
2177 | cursor->setParag( doc->firstParag() ); | 2239 | cursor->setParagraph( doc->firstParagraph() ); |
2178 | cursor->setIndex( 0 ); | 2240 | cursor->setIndex( 0 ); |
2179 | } | 2241 | } |
2180 | repaintChanged(); | 2242 | repaintChanged(); |
2181 | drawCursor( TRUE ); | 2243 | drawCursor( TRUE ); |
2182 | } | 2244 | } |
2183 | 2245 | ||
2184 | /*! | 2246 | /*! |
2185 | Undoes the last operation. | 2247 | Undoes the last operation. |
2186 | 2248 | ||
2187 | If there is no operation to undo, e.g. there is no undo step in the | 2249 | If there is no operation to undo, e.g. there is no undo step in the |
2188 | undo/redo history, nothing happens. | 2250 | undo/redo history, nothing happens. |
2189 | 2251 | ||
2190 | \sa undoAvailable() redo() undoDepth() | 2252 | \sa undoAvailable() redo() undoDepth() |
2191 | */ | 2253 | */ |
2192 | 2254 | ||
2193 | void QTextEdit::undo() | 2255 | void QTextEdit::undo() |
2194 | { | 2256 | { |
2195 | // XXX FIXME The next line is here because there may be a command | 2257 | // XXX FIXME The next line is here because there may be a command |
2196 | // that needs to be 'flushed'. The FIXME is because I am not | 2258 | // that needs to be 'flushed'. The FIXME is because I am not |
2197 | // 100% certain this is the right call to do this. | 2259 | // 100% certain this is the right call to do this. |
2198 | clearUndoRedo(); | 2260 | clearUndoRedo(); |
2199 | if ( isReadOnly() || !doc->commands()->isUndoAvailable() || !undoEnabled ) | 2261 | if ( isReadOnly() || !doc->commands()->isUndoAvailable() || !undoEnabled ) |
2200 | return; | 2262 | return; |
2201 | 2263 | ||
2202 | for ( int i = 0; i < (int)doc->numSelections(); ++i ) | 2264 | for ( int i = 0; i < (int)doc->numSelections(); ++i ) |
2203 | doc->removeSelection( i ); | 2265 | doc->removeSelection( i ); |
2204 | 2266 | ||
2205 | #ifndef QT_NO_CURSOR | 2267 | #ifndef QT_NO_CURSOR |
2206 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); | 2268 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); |
2207 | #endif | 2269 | #endif |
2208 | 2270 | ||
2209 | clearUndoRedo(); | 2271 | clearUndoRedo(); |
2210 | drawCursor( FALSE ); | 2272 | drawCursor( FALSE ); |
2211 | QTextCursor *c = doc->undo( cursor ); | 2273 | QTextCursor *c = doc->undo( cursor ); |
2212 | if ( !c ) { | 2274 | if ( !c ) { |
2213 | drawCursor( TRUE ); | 2275 | drawCursor( TRUE ); |
2214 | return; | 2276 | return; |
2215 | } | 2277 | } |
2216 | lastFormatted = 0; | 2278 | lastFormatted = 0; |
2217 | ensureCursorVisible(); | 2279 | ensureCursorVisible(); |
2218 | repaintChanged(); | 2280 | repaintChanged(); |
2219 | drawCursor( TRUE ); | 2281 | drawCursor( TRUE ); |
2282 | updateMicroFocusHint(); | ||
2220 | setModified(); | 2283 | setModified(); |
2221 | emit textChanged(); | 2284 | emit textChanged(); |
2222 | if ( hasFocus() || viewport()->hasFocus() ) { | ||
2223 | int h = cursor->parag()->lineHeightOfChar( cursor->index() ); | ||
2224 | if ( !readonly ) { | ||
2225 | QFont f = cursor->parag()->at( cursor->index() )->format()->font(); | ||
2226 | setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), | ||
2227 | cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); | ||
2228 | } | ||
2229 | } | ||
2230 | } | 2285 | } |
2231 | 2286 | ||
2232 | /*! | 2287 | /*! |
2233 | Redoes the last operation. | 2288 | Redoes the last operation. |
2234 | 2289 | ||
2235 | If there is no operation to redo, e.g. there is no redo step in the | 2290 | If there is no operation to redo, e.g. there is no redo step in the |
2236 | undo/redo history, nothing happens. | 2291 | undo/redo history, nothing happens. |
2237 | 2292 | ||
2238 | \sa redoAvailable() undo() undoDepth() | 2293 | \sa redoAvailable() undo() undoDepth() |
2239 | */ | 2294 | */ |
2240 | 2295 | ||
2241 | void QTextEdit::redo() | 2296 | void QTextEdit::redo() |
2242 | { | 2297 | { |
2243 | if ( isReadOnly() || !doc->commands()->isRedoAvailable() || !undoEnabled ) | 2298 | if ( isReadOnly() || !doc->commands()->isRedoAvailable() || !undoEnabled ) |
2244 | return; | 2299 | return; |
2245 | 2300 | ||
2246 | for ( int i = 0; i < (int)doc->numSelections(); ++i ) | 2301 | for ( int i = 0; i < (int)doc->numSelections(); ++i ) |
2247 | doc->removeSelection( i ); | 2302 | doc->removeSelection( i ); |
2248 | 2303 | ||
2249 | #ifndef QT_NO_CURSOR | 2304 | #ifndef QT_NO_CURSOR |
2250 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); | 2305 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); |
2251 | #endif | 2306 | #endif |
2252 | 2307 | ||
2253 | clearUndoRedo(); | 2308 | clearUndoRedo(); |
2254 | drawCursor( FALSE ); | 2309 | drawCursor( FALSE ); |
2255 | QTextCursor *c = doc->redo( cursor ); | 2310 | QTextCursor *c = doc->redo( cursor ); |
2256 | if ( !c ) { | 2311 | if ( !c ) { |
2257 | drawCursor( TRUE ); | 2312 | drawCursor( TRUE ); |
2258 | return; | 2313 | return; |
2259 | } | 2314 | } |
2260 | lastFormatted = 0; | 2315 | lastFormatted = 0; |
2261 | ensureCursorVisible(); | 2316 | ensureCursorVisible(); |
2262 | repaintChanged(); | 2317 | repaintChanged(); |
2263 | ensureCursorVisible(); | 2318 | ensureCursorVisible(); |
2264 | drawCursor( TRUE ); | 2319 | drawCursor( TRUE ); |
2320 | updateMicroFocusHint(); | ||
2265 | setModified(); | 2321 | setModified(); |
2266 | emit textChanged(); | 2322 | emit textChanged(); |
2267 | if ( hasFocus() || viewport()->hasFocus() ) { | ||
2268 | int h = cursor->parag()->lineHeightOfChar( cursor->index() ); | ||
2269 | if ( !readonly ) { | ||
2270 | QFont f = cursor->parag()->at( cursor->index() )->format()->font(); | ||
2271 | setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), | ||
2272 | cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); | ||
2273 | } | ||
2274 | } | ||
2275 | } | 2323 | } |
2276 | 2324 | ||
2277 | /*! | 2325 | /*! |
2278 | Pastes the text from the clipboard into the text edit at the current | 2326 | Pastes the text from the clipboard into the text edit at the current |
2279 | cursor position. Only plain text is pasted. | 2327 | cursor position. Only plain text is pasted. |
2280 | 2328 | ||
2281 | If there is no text in the clipboard nothing happens. | 2329 | If there is no text in the clipboard nothing happens. |
2282 | 2330 | ||
2283 | \sa pasteSubType() cut() QTextEdit::copy() | 2331 | \sa pasteSubType() cut() QTextEdit::copy() |
2284 | */ | 2332 | */ |
2285 | 2333 | ||
2286 | void QTextEdit::paste() | 2334 | void QTextEdit::paste() |
2287 | { | 2335 | { |
2288 | #ifndef QT_NO_CLIPBOARD | 2336 | #ifndef QT_NO_CLIPBOARD |
2289 | if ( isReadOnly() ) | 2337 | if ( isReadOnly() ) |
2290 | return; | 2338 | return; |
2291 | pasteSubType( "plain" ); | 2339 | pasteSubType( "plain" ); |
2292 | if ( hasFocus() || viewport()->hasFocus() ) { | 2340 | updateMicroFocusHint(); |
2293 | int h = cursor->parag()->lineHeightOfChar( cursor->index() ); | ||
2294 | if ( !readonly ) { | ||
2295 | QFont f = cursor->parag()->at( cursor->index() )->format()->font(); | ||
2296 | setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), | ||
2297 | cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); | ||
2298 | } | ||
2299 | } | ||
2300 | #endif | 2341 | #endif |
2301 | } | 2342 | } |
2302 | 2343 | ||
2303 | void QTextEdit::checkUndoRedoInfo( UndoRedoInfo::Type t ) | 2344 | void QTextEdit::checkUndoRedoInfo( UndoRedoInfo::Type t ) |
2304 | { | 2345 | { |
2305 | if ( undoRedoInfo.valid() && t != undoRedoInfo.type ) { | 2346 | if ( undoRedoInfo.valid() && t != undoRedoInfo.type ) { |
2306 | clearUndoRedo(); | 2347 | clearUndoRedo(); |
2307 | } | 2348 | } |
2308 | undoRedoInfo.type = t; | 2349 | undoRedoInfo.type = t; |
2309 | } | 2350 | } |
2310 | 2351 | ||
2311 | /*! Repaints any paragraphs that have changed. | 2352 | /*! Repaints any paragraphs that have changed. |
2312 | 2353 | ||
2313 | Although used extensively internally you shouldn't need to call this | 2354 | Although used extensively internally you shouldn't need to call this |
2314 | yourself. | 2355 | yourself. |
2315 | */ | 2356 | */ |
2316 | 2357 | ||
2317 | void QTextEdit::repaintChanged() | 2358 | void QTextEdit::repaintChanged() |
2318 | { | 2359 | { |
2319 | if ( !isUpdatesEnabled() || !viewport()->isUpdatesEnabled() ) | 2360 | if ( !isUpdatesEnabled() || !viewport()->isUpdatesEnabled() ) |
2320 | return; | 2361 | return; |
2321 | QPainter p( viewport() ); | 2362 | QPainter p( viewport() ); |
2322 | p.translate( -contentsX(), -contentsY() ); | 2363 | p.translate( -contentsX(), -contentsY() ); |
2323 | paintDocument( FALSE, &p, contentsX(), contentsY(), visibleWidth(), visibleHeight() ); | 2364 | paintDocument( FALSE, &p, contentsX(), contentsY(), visibleWidth(), visibleHeight() ); |
2324 | } | 2365 | } |
2325 | 2366 | ||
2326 | /*! | 2367 | /*! |
2327 | Copies the selected text (from selection 0) to the clipboard and | 2368 | Copies the selected text (from selection 0) to the clipboard and |
2328 | deletes it from the text edit. | 2369 | deletes it from the text edit. |
2329 | 2370 | ||
2330 | If there is no selected text (in selection 0) nothing happens. | 2371 | If there is no selected text (in selection 0) nothing happens. |
2331 | 2372 | ||
2332 | \sa QTextEdit::copy() paste() pasteSubType() | 2373 | \sa QTextEdit::copy() paste() pasteSubType() |
2333 | */ | 2374 | */ |
2334 | 2375 | ||
2335 | void QTextEdit::cut() | 2376 | void QTextEdit::cut() |
2336 | { | 2377 | { |
2337 | if ( isReadOnly() ) | 2378 | if ( isReadOnly() ) |
2338 | return; | 2379 | return; |
2339 | 2380 | ||
2340 | if ( doc->hasSelection( QTextDocument::Standard ) ) { | 2381 | QString t; |
2341 | doc->copySelectedText( QTextDocument::Standard ); | 2382 | if ( doc->hasSelection( QTextDocument::Standard ) && |
2383 | !( t = doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ) ).isEmpty() ) { | ||
2384 | QApplication::clipboard()->setText( t ); | ||
2342 | removeSelectedText(); | 2385 | removeSelectedText(); |
2343 | } | 2386 | } |
2344 | if ( hasFocus() || viewport()->hasFocus() ) { | 2387 | updateMicroFocusHint(); |
2345 | int h = cursor->parag()->lineHeightOfChar( cursor->index() ); | ||
2346 | if ( !readonly ) { | ||
2347 | QFont f = cursor->parag()->at( cursor->index() )->format()->font(); | ||
2348 | setMicroFocusHint( cursor->x() - contentsX() + frameWidth(), | ||
2349 | cursor->y() + cursor->parag()->rect().y() - contentsY() + frameWidth(), 0, h, TRUE ); | ||
2350 | } | ||
2351 | } | ||
2352 | } | 2388 | } |
2353 | 2389 | ||
2354 | /*! Copies any selected text (from selection 0) to the clipboard. | 2390 | /*! Copies any selected text (from selection 0) to the clipboard. |
2355 | 2391 | ||
2356 | \sa hasSelectedText() copyAvailable() | 2392 | \sa hasSelectedText() copyAvailable() |
2357 | */ | 2393 | */ |
2358 | 2394 | ||
2359 | void QTextEdit::copy() | 2395 | void QTextEdit::copy() |
2360 | { | 2396 | { |
2361 | if ( !doc->selectedText( QTextDocument::Standard ).isEmpty() ) | 2397 | QString t = doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ); |
2362 | doc->copySelectedText( QTextDocument::Standard ); | 2398 | if ( doc->hasSelection( QTextDocument::Standard ) && |
2399 | !t.isEmpty() && t.simplifyWhiteSpace() != "<selstart/>" ) | ||
2400 | QApplication::clipboard()->setText( t ); | ||
2363 | } | 2401 | } |
2364 | 2402 | ||
2365 | /*! | 2403 | /*! |
2366 | Re-indents the current paragraph. | 2404 | Re-indents the current paragraph. |
2367 | */ | 2405 | */ |
2368 | 2406 | ||
2369 | void QTextEdit::indent() | 2407 | void QTextEdit::indent() |
2370 | { | 2408 | { |
2371 | if ( isReadOnly() ) | 2409 | if ( isReadOnly() ) |
2372 | return; | 2410 | return; |
2373 | 2411 | ||
2374 | drawCursor( FALSE ); | 2412 | drawCursor( FALSE ); |
2375 | if ( !doc->hasSelection( QTextDocument::Standard ) ) | 2413 | if ( !doc->hasSelection( QTextDocument::Standard ) ) |
2376 | cursor->indent(); | 2414 | cursor->indent(); |
2377 | else | 2415 | else |
2378 | doc->indentSelection( QTextDocument::Standard ); | 2416 | doc->indentSelection( QTextDocument::Standard ); |
2379 | repaintChanged(); | 2417 | repaintChanged(); |
2380 | drawCursor( TRUE ); | 2418 | drawCursor( TRUE ); |
2381 | setModified(); | 2419 | setModified(); |
2382 | emit textChanged(); | 2420 | emit textChanged(); |
2383 | } | 2421 | } |
2384 | 2422 | ||
2385 | /*! Reimplemented to allow tabbing through links. | 2423 | /*! Reimplemented to allow tabbing through links. |
2386 | If \a n is TRUE the tab moves the focus to the next child; if \a n | 2424 | If \a n is TRUE the tab moves the focus to the next child; if \a n |
@@ -2391,253 +2429,224 @@ void QTextEdit::indent() | |||
2391 | bool QTextEdit::focusNextPrevChild( bool n ) | 2429 | bool QTextEdit::focusNextPrevChild( bool n ) |
2392 | { | 2430 | { |
2393 | if ( !isReadOnly() || !linksEnabled() ) | 2431 | if ( !isReadOnly() || !linksEnabled() ) |
2394 | return FALSE; | 2432 | return FALSE; |
2395 | bool b = doc->focusNextPrevChild( n ); | 2433 | bool b = doc->focusNextPrevChild( n ); |
2396 | repaintChanged(); | 2434 | repaintChanged(); |
2397 | if ( b ) | 2435 | if ( b ) |
2398 | //##### this does not work with tables. The focusIndicator | 2436 | //##### this does not work with tables. The focusIndicator |
2399 | //should really be a QTextCursor. Fix 3.1 | 2437 | //should really be a QTextCursor. Fix 3.1 |
2400 | makeParagVisible( doc->focusIndicator.parag ); | 2438 | makeParagVisible( doc->focusIndicator.parag ); |
2401 | return b; | 2439 | return b; |
2402 | } | 2440 | } |
2403 | 2441 | ||
2404 | /*! | 2442 | /*! |
2405 | \internal | 2443 | \internal |
2406 | 2444 | ||
2407 | This functions sets the current format to \a f. Only the fields of \a | 2445 | This functions sets the current format to \a f. Only the fields of \a |
2408 | f which are specified by the \a flags are used. | 2446 | f which are specified by the \a flags are used. |
2409 | */ | 2447 | */ |
2410 | 2448 | ||
2411 | void QTextEdit::setFormat( QTextFormat *f, int flags ) | 2449 | void QTextEdit::setFormat( QTextFormat *f, int flags ) |
2412 | { | 2450 | { |
2413 | if ( doc->hasSelection( QTextDocument::Standard ) ) { | 2451 | if ( doc->hasSelection( QTextDocument::Standard ) ) { |
2414 | drawCursor( FALSE ); | 2452 | drawCursor( FALSE ); |
2415 | QString str = doc->selectedText( QTextDocument::Standard ); | ||
2416 | QTextCursor c1 = doc->selectionStartCursor( QTextDocument::Standard ); | 2453 | QTextCursor c1 = doc->selectionStartCursor( QTextDocument::Standard ); |
2454 | c1.restoreState(); | ||
2417 | QTextCursor c2 = doc->selectionEndCursor( QTextDocument::Standard ); | 2455 | QTextCursor c2 = doc->selectionEndCursor( QTextDocument::Standard ); |
2456 | c2.restoreState(); | ||
2418 | clearUndoRedo(); | 2457 | clearUndoRedo(); |
2419 | undoRedoInfo.type = UndoRedoInfo::Format; | 2458 | undoRedoInfo.type = UndoRedoInfo::Format; |
2420 | undoRedoInfo.id = c1.parag()->paragId(); | 2459 | undoRedoInfo.id = c1.paragraph()->paragId(); |
2421 | undoRedoInfo.index = c1.index(); | 2460 | undoRedoInfo.index = c1.index(); |
2422 | undoRedoInfo.eid = c2.parag()->paragId(); | 2461 | undoRedoInfo.eid = c2.paragraph()->paragId(); |
2423 | undoRedoInfo.eindex = c2.index(); | 2462 | undoRedoInfo.eindex = c2.index(); |
2424 | undoRedoInfo.d->text = str; | 2463 | readFormats( c1, c2, undoRedoInfo.d->text ); |
2425 | readFormats( c1, c2, 0, undoRedoInfo.d->text ); | ||
2426 | undoRedoInfo.format = f; | 2464 | undoRedoInfo.format = f; |
2427 | undoRedoInfo.flags = flags; | 2465 | undoRedoInfo.flags = flags; |
2428 | clearUndoRedo(); | 2466 | clearUndoRedo(); |
2429 | doc->setFormat( QTextDocument::Standard, f, flags ); | 2467 | doc->setFormat( QTextDocument::Standard, f, flags ); |
2430 | repaintChanged(); | 2468 | repaintChanged(); |
2431 | formatMore(); | 2469 | formatMore(); |
2432 | drawCursor( TRUE ); | 2470 | drawCursor( TRUE ); |
2433 | setModified(); | 2471 | setModified(); |
2434 | emit textChanged(); | 2472 | emit textChanged(); |
2435 | } | 2473 | } |
2436 | if ( currentFormat && currentFormat->key() != f->key() ) { | 2474 | if ( currentFormat && currentFormat->key() != f->key() ) { |
2437 | currentFormat->removeRef(); | 2475 | currentFormat->removeRef(); |
2438 | currentFormat = doc->formatCollection()->format( f ); | 2476 | currentFormat = doc->formatCollection()->format( f ); |
2439 | if ( currentFormat->isMisspelled() ) { | 2477 | if ( currentFormat->isMisspelled() ) { |
2440 | currentFormat->removeRef(); | 2478 | currentFormat->removeRef(); |
2441 | currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); | 2479 | currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); |
2442 | } | 2480 | } |
2443 | emit currentFontChanged( currentFormat->font() ); | 2481 | emit currentFontChanged( currentFormat->font() ); |
2444 | emit currentColorChanged( currentFormat->color() ); | 2482 | emit currentColorChanged( currentFormat->color() ); |
2445 | emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); | 2483 | emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); |
2446 | if ( cursor->index() == cursor->parag()->length() - 1 ) { | 2484 | if ( cursor->index() == cursor->paragraph()->length() - 1 ) { |
2447 | currentFormat->addRef(); | 2485 | currentFormat->addRef(); |
2448 | cursor->parag()->string()->setFormat( cursor->index(), currentFormat, TRUE ); | 2486 | cursor->paragraph()->string()->setFormat( cursor->index(), currentFormat, TRUE ); |
2449 | if ( cursor->parag()->length() == 1 ) { | 2487 | if ( cursor->paragraph()->length() == 1 ) { |
2450 | cursor->parag()->invalidate( 0 ); | 2488 | cursor->paragraph()->invalidate( 0 ); |
2451 | cursor->parag()->format(); | 2489 | cursor->paragraph()->format(); |
2452 | repaintChanged(); | 2490 | repaintChanged(); |
2453 | } | 2491 | } |
2454 | } | 2492 | } |
2455 | } | 2493 | } |
2456 | } | 2494 | } |
2457 | 2495 | ||
2458 | /*! \reimp */ | 2496 | /*! \reimp */ |
2459 | 2497 | ||
2460 | void QTextEdit::setPalette( const QPalette &p ) | 2498 | void QTextEdit::setPalette( const QPalette &p ) |
2461 | { | 2499 | { |
2462 | QScrollView::setPalette( p ); | 2500 | QScrollView::setPalette( p ); |
2463 | if ( textFormat() == PlainText ) { | 2501 | if ( textFormat() == PlainText ) { |
2464 | QTextFormat *f = doc->formatCollection()->defaultFormat(); | 2502 | QTextFormat *f = doc->formatCollection()->defaultFormat(); |
2465 | f->setColor( colorGroup().text() ); | 2503 | f->setColor( colorGroup().text() ); |
2466 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); | 2504 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); |
2467 | } | 2505 | } |
2468 | } | 2506 | } |
2469 | 2507 | ||
2470 | /*! | 2508 | /*! \internal |
2509 | |||
2510 | \warning In Qt 3.1 we will provide a cleaer API for the | ||
2511 | functionality which is provided by this function and in Qt 4.0 this | ||
2512 | function will go away. | ||
2513 | |||
2471 | Sets the paragraph style of the current paragraph | 2514 | Sets the paragraph style of the current paragraph |
2472 | to \a dm. If \a dm is QStyleSheetItem::DisplayListItem, the | 2515 | to \a dm. If \a dm is QStyleSheetItem::DisplayListItem, the |
2473 | type of the list item is set to \a listStyle. | 2516 | type of the list item is set to \a listStyle. |
2474 | 2517 | ||
2475 | \sa setAlignment() | 2518 | \sa setAlignment() |
2476 | */ | 2519 | */ |
2477 | 2520 | ||
2478 | void QTextEdit::setParagType( QStyleSheetItem::DisplayMode dm, QStyleSheetItem::ListStyle listStyle ) | 2521 | void QTextEdit::setParagType( QStyleSheetItem::DisplayMode dm, QStyleSheetItem::ListStyle listStyle ) |
2479 | { | 2522 | { |
2480 | if ( isReadOnly() ) | 2523 | if ( isReadOnly() ) |
2481 | return; | 2524 | return; |
2482 | 2525 | ||
2483 | drawCursor( FALSE ); | 2526 | drawCursor( FALSE ); |
2484 | if ( !doc->hasSelection( QTextDocument::Standard ) ) { | 2527 | QTextParagraph *start = cursor->paragraph(); |
2485 | clearUndoRedo(); | 2528 | QTextParagraph *end = start; |
2486 | undoRedoInfo.type = UndoRedoInfo::ParagType; | 2529 | if ( doc->hasSelection( QTextDocument::Standard ) ) { |
2487 | QValueList< QPtrVector<QStyleSheetItem> > oldStyles; | 2530 | start = doc->selectionStartCursor( QTextDocument::Standard ).topParagraph(); |
2488 | undoRedoInfo.oldStyles.clear(); | 2531 | end = doc->selectionEndCursor( QTextDocument::Standard ).topParagraph(); |
2489 | undoRedoInfo.oldStyles << cursor->parag()->styleSheetItems(); | 2532 | if ( end->paragId() < start->paragId() ) |
2490 | undoRedoInfo.oldListStyles.clear(); | 2533 | return; // do not trust our selections |
2491 | undoRedoInfo.oldListStyles << cursor->parag()->listStyle(); | 2534 | } |
2492 | undoRedoInfo.list = dm == QStyleSheetItem::DisplayListItem; | 2535 | |
2493 | undoRedoInfo.listStyle = listStyle; | ||
2494 | undoRedoInfo.id = cursor->parag()->paragId(); | ||
2495 | undoRedoInfo.eid = cursor->parag()->paragId(); | ||
2496 | undoRedoInfo.d->text = " "; | ||
2497 | undoRedoInfo.index = 1; | ||
2498 | clearUndoRedo(); | ||
2499 | cursor->parag()->setList( dm == QStyleSheetItem::DisplayListItem, listStyle ); | ||
2500 | repaintChanged(); | ||
2501 | } else { | ||
2502 | QTextParag *start = doc->selectionStart( QTextDocument::Standard ); | ||
2503 | QTextParag *end = doc->selectionEnd( QTextDocument::Standard ); | ||
2504 | lastFormatted = start; | ||
2505 | clearUndoRedo(); | 2536 | clearUndoRedo(); |
2506 | undoRedoInfo.type = UndoRedoInfo::ParagType; | 2537 | undoRedoInfo.type = UndoRedoInfo::Style; |
2507 | undoRedoInfo.id = start->paragId(); | 2538 | undoRedoInfo.id = start->paragId(); |
2508 | undoRedoInfo.eid = end->paragId(); | 2539 | undoRedoInfo.eid = end->paragId(); |
2509 | undoRedoInfo.list = dm == QStyleSheetItem::DisplayListItem; | 2540 | undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); |
2510 | undoRedoInfo.listStyle = listStyle; | 2541 | |
2511 | undoRedoInfo.oldStyles.clear(); | 2542 | while ( start != end->next() ) { |
2512 | undoRedoInfo.oldListStyles.clear(); | 2543 | start->setListStyle( listStyle ); |
2513 | while ( start ) { | 2544 | if ( dm == QStyleSheetItem::DisplayListItem ) { |
2514 | undoRedoInfo.oldStyles << start->styleSheetItems(); | 2545 | start->setListItem( TRUE ); |
2515 | undoRedoInfo.oldListStyles << start->listStyle(); | 2546 | if( start->listDepth() == 0 ) |
2516 | start->setList( dm == QStyleSheetItem::DisplayListItem, listStyle ); | 2547 | start->setListDepth( 1 ); |
2517 | if ( start == end ) | 2548 | } else if ( start->isListItem() ) { |
2518 | break; | 2549 | start->setListItem( FALSE ); |
2550 | start->setListDepth( QMAX( start->listDepth()-1, 0 ) ); | ||
2551 | } | ||
2519 | start = start->next(); | 2552 | start = start->next(); |
2520 | } | 2553 | } |
2521 | undoRedoInfo.d->text = " "; | 2554 | |
2522 | undoRedoInfo.index = 1; | ||
2523 | clearUndoRedo(); | 2555 | clearUndoRedo(); |
2524 | repaintChanged(); | 2556 | repaintChanged(); |
2525 | formatMore(); | 2557 | formatMore(); |
2526 | } | ||
2527 | drawCursor( TRUE ); | 2558 | drawCursor( TRUE ); |
2528 | setModified(); | 2559 | setModified(); |
2529 | emit textChanged(); | 2560 | emit textChanged(); |
2530 | } | 2561 | } |
2531 | 2562 | ||
2532 | /*! | 2563 | /*! |
2533 | Sets the alignment of the current paragraph to \a a. Valid alignments | 2564 | Sets the alignment of the current paragraph to \a a. Valid alignments |
2534 | are \c Qt::AlignLeft, \c Qt::AlignRight, Qt::AlignJustify and | 2565 | are \c Qt::AlignLeft, \c Qt::AlignRight, Qt::AlignJustify and |
2535 | Qt::AlignCenter (which centers horizontally). | 2566 | Qt::AlignCenter (which centers horizontally). |
2536 | 2567 | ||
2537 | \sa setParagType() | ||
2538 | */ | 2568 | */ |
2539 | 2569 | ||
2540 | void QTextEdit::setAlignment( int a ) | 2570 | void QTextEdit::setAlignment( int a ) |
2541 | { | 2571 | { |
2542 | if ( isReadOnly() || block_set_alignment ) | 2572 | if ( isReadOnly() || block_set_alignment ) |
2543 | return; | 2573 | return; |
2544 | 2574 | ||
2545 | drawCursor( FALSE ); | 2575 | drawCursor( FALSE ); |
2546 | if ( !doc->hasSelection( QTextDocument::Standard ) ) { | 2576 | QTextParagraph *start = cursor->paragraph(); |
2547 | if ( cursor->parag()->alignment() != a ) { | 2577 | QTextParagraph *end = start; |
2548 | clearUndoRedo(); | 2578 | if ( doc->hasSelection( QTextDocument::Standard ) ) { |
2549 | undoRedoInfo.type = UndoRedoInfo::Alignment; | 2579 | start = doc->selectionStartCursor( QTextDocument::Standard ).topParagraph(); |
2550 | QMemArray<int> oa( 1 ); | 2580 | end = doc->selectionEndCursor( QTextDocument::Standard ).topParagraph(); |
2551 | oa[ 0 ] = cursor->parag()->alignment(); | 2581 | if ( end->paragId() < start->paragId() ) |
2552 | undoRedoInfo.oldAligns = oa; | 2582 | return; // do not trust our selections |
2553 | undoRedoInfo.newAlign = a; | ||
2554 | undoRedoInfo.id = cursor->parag()->paragId(); | ||
2555 | undoRedoInfo.eid = cursor->parag()->paragId(); | ||
2556 | undoRedoInfo.d->text = " "; | ||
2557 | undoRedoInfo.index = 1; | ||
2558 | clearUndoRedo(); | ||
2559 | cursor->parag()->setAlignment( a ); | ||
2560 | repaintChanged(); | ||
2561 | } | 2583 | } |
2562 | } else { | 2584 | |
2563 | QTextParag *start = doc->selectionStart( QTextDocument::Standard ); | ||
2564 | QTextParag *end = doc->selectionEnd( QTextDocument::Standard ); | ||
2565 | lastFormatted = start; | ||
2566 | int len = end->paragId() - start->paragId() + 1; | ||
2567 | clearUndoRedo(); | 2585 | clearUndoRedo(); |
2568 | undoRedoInfo.type = UndoRedoInfo::Alignment; | 2586 | undoRedoInfo.type = UndoRedoInfo::Style; |
2569 | undoRedoInfo.id = start->paragId(); | 2587 | undoRedoInfo.id = start->paragId(); |
2570 | undoRedoInfo.eid = end->paragId(); | 2588 | undoRedoInfo.eid = end->paragId(); |
2571 | QMemArray<int> oa( QMAX( 0, len ) ); | 2589 | undoRedoInfo.styleInformation = QTextStyleCommand::readStyleInformation( doc, undoRedoInfo.id, undoRedoInfo.eid ); |
2572 | int i = 0; | 2590 | |
2573 | while ( start ) { | 2591 | while ( start != end->next() ) { |
2574 | if ( i < (int)oa.size() ) | ||
2575 | oa[ i ] = start->alignment(); | ||
2576 | start->setAlignment( a ); | 2592 | start->setAlignment( a ); |
2577 | if ( start == end ) | ||
2578 | break; | ||
2579 | start = start->next(); | 2593 | start = start->next(); |
2580 | ++i; | ||
2581 | } | 2594 | } |
2582 | undoRedoInfo.oldAligns = oa; | 2595 | |
2583 | undoRedoInfo.newAlign = a; | ||
2584 | undoRedoInfo.d->text = " "; | ||
2585 | undoRedoInfo.index = 1; | ||
2586 | clearUndoRedo(); | 2596 | clearUndoRedo(); |
2587 | repaintChanged(); | 2597 | repaintChanged(); |
2588 | formatMore(); | 2598 | formatMore(); |
2589 | } | ||
2590 | drawCursor( TRUE ); | 2599 | drawCursor( TRUE ); |
2591 | if ( currentAlignment != a ) { | 2600 | if ( currentAlignment != a ) { |
2592 | currentAlignment = a; | 2601 | currentAlignment = a; |
2593 | emit currentAlignmentChanged( currentAlignment ); | 2602 | emit currentAlignmentChanged( currentAlignment ); |
2594 | } | 2603 | } |
2595 | setModified(); | 2604 | setModified(); |
2596 | emit textChanged(); | 2605 | emit textChanged(); |
2597 | } | 2606 | } |
2598 | 2607 | ||
2599 | void QTextEdit::updateCurrentFormat() | 2608 | void QTextEdit::updateCurrentFormat() |
2600 | { | 2609 | { |
2601 | int i = cursor->index(); | 2610 | int i = cursor->index(); |
2602 | if ( i > 0 ) | 2611 | if ( i > 0 ) |
2603 | --i; | 2612 | --i; |
2604 | if ( doc->useFormatCollection() && | 2613 | if ( doc->useFormatCollection() && |
2605 | ( !currentFormat || currentFormat->key() != cursor->parag()->at( i )->format()->key() ) ) { | 2614 | ( !currentFormat || currentFormat->key() != cursor->paragraph()->at( i )->format()->key() ) ) { |
2606 | if ( currentFormat ) | 2615 | if ( currentFormat ) |
2607 | currentFormat->removeRef(); | 2616 | currentFormat->removeRef(); |
2608 | currentFormat = doc->formatCollection()->format( cursor->parag()->at( i )->format() ); | 2617 | currentFormat = doc->formatCollection()->format( cursor->paragraph()->at( i )->format() ); |
2609 | if ( currentFormat->isMisspelled() ) { | 2618 | if ( currentFormat->isMisspelled() ) { |
2610 | currentFormat->removeRef(); | 2619 | currentFormat->removeRef(); |
2611 | currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); | 2620 | currentFormat = doc->formatCollection()->format( currentFormat->font(), currentFormat->color() ); |
2612 | } | 2621 | } |
2613 | emit currentFontChanged( currentFormat->font() ); | 2622 | emit currentFontChanged( currentFormat->font() ); |
2614 | emit currentColorChanged( currentFormat->color() ); | 2623 | emit currentColorChanged( currentFormat->color() ); |
2615 | emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); | 2624 | emit currentVerticalAlignmentChanged( (VerticalAlignment)currentFormat->vAlign() ); |
2616 | } | 2625 | } |
2617 | 2626 | ||
2618 | if ( currentAlignment != cursor->parag()->alignment() ) { | 2627 | if ( currentAlignment != cursor->paragraph()->alignment() ) { |
2619 | currentAlignment = cursor->parag()->alignment(); | 2628 | currentAlignment = cursor->paragraph()->alignment(); |
2620 | block_set_alignment = TRUE; | 2629 | block_set_alignment = TRUE; |
2621 | emit currentAlignmentChanged( currentAlignment ); | 2630 | emit currentAlignmentChanged( currentAlignment ); |
2622 | block_set_alignment = FALSE; | 2631 | block_set_alignment = FALSE; |
2623 | } | 2632 | } |
2624 | } | 2633 | } |
2625 | 2634 | ||
2626 | /*! | 2635 | /*! |
2627 | If \a b is TRUE sets the current format to italic; otherwise sets | 2636 | If \a b is TRUE sets the current format to italic; otherwise sets |
2628 | the current format to non-italic. | 2637 | the current format to non-italic. |
2629 | 2638 | ||
2630 | \sa italic() | 2639 | \sa italic() |
2631 | */ | 2640 | */ |
2632 | 2641 | ||
2633 | void QTextEdit::setItalic( bool b ) | 2642 | void QTextEdit::setItalic( bool b ) |
2634 | { | 2643 | { |
2635 | QTextFormat f( *currentFormat ); | 2644 | QTextFormat f( *currentFormat ); |
2636 | f.setItalic( b ); | 2645 | f.setItalic( b ); |
2637 | QTextFormat *f2 = doc->formatCollection()->format( &f ); | 2646 | QTextFormat *f2 = doc->formatCollection()->format( &f ); |
2638 | setFormat( f2, QTextFormat::Italic ); | 2647 | setFormat( f2, QTextFormat::Italic ); |
2639 | } | 2648 | } |
2640 | 2649 | ||
2641 | /*! | 2650 | /*! |
2642 | If \a b is TRUE sets the current format to bold; otherwise sets the | 2651 | If \a b is TRUE sets the current format to bold; otherwise sets the |
2643 | current format to non-bold. | 2652 | current format to non-bold. |
@@ -2757,249 +2766,271 @@ QString QTextEdit::text( int para ) const | |||
2757 | } | 2766 | } |
2758 | 2767 | ||
2759 | /*! | 2768 | /*! |
2760 | \overload | 2769 | \overload |
2761 | 2770 | ||
2762 | Changes the text of the text edit to the string \a text and the | 2771 | Changes the text of the text edit to the string \a text and the |
2763 | context to \a context. Any previous text is removed. | 2772 | context to \a context. Any previous text is removed. |
2764 | 2773 | ||
2765 | \a text may be interpreted either as plain text or as rich text, | 2774 | \a text may be interpreted either as plain text or as rich text, |
2766 | depending on the textFormat(). The default setting is \c AutoText, | 2775 | depending on the textFormat(). The default setting is \c AutoText, |
2767 | i.e. the text edit autodetects the format from \a text. | 2776 | i.e. the text edit autodetects the format from \a text. |
2768 | 2777 | ||
2769 | The optional \a context is a path which the text edit's | 2778 | The optional \a context is a path which the text edit's |
2770 | QMimeSourceFactory uses to resolve the locations of files and images. | 2779 | QMimeSourceFactory uses to resolve the locations of files and images. |
2771 | (See \l{QTextEdit::QTextEdit()}.) It is passed to the text edit's | 2780 | (See \l{QTextEdit::QTextEdit()}.) It is passed to the text edit's |
2772 | QMimeSourceFactory when quering data. | 2781 | QMimeSourceFactory when quering data. |
2773 | 2782 | ||
2774 | Note that the undo/redo history is cleared by this function. | 2783 | Note that the undo/redo history is cleared by this function. |
2775 | 2784 | ||
2776 | \sa text(), setTextFormat() | 2785 | \sa text(), setTextFormat() |
2777 | */ | 2786 | */ |
2778 | 2787 | ||
2779 | void QTextEdit::setText( const QString &text, const QString &context ) | 2788 | void QTextEdit::setText( const QString &text, const QString &context ) |
2780 | { | 2789 | { |
2781 | if ( !isModified() && this->context() == context && this->text() == text ) | 2790 | if ( !isModified() && isReadOnly() && |
2791 | this->context() == context && this->text() == text ) | ||
2782 | return; | 2792 | return; |
2783 | 2793 | ||
2784 | emit undoAvailable( FALSE ); | 2794 | emit undoAvailable( FALSE ); |
2785 | emit redoAvailable( FALSE ); | 2795 | emit redoAvailable( FALSE ); |
2786 | undoRedoInfo.clear(); | 2796 | undoRedoInfo.clear(); |
2787 | doc->commands()->clear(); | 2797 | doc->commands()->clear(); |
2788 | 2798 | ||
2789 | lastFormatted = 0; | 2799 | lastFormatted = 0; |
2790 | cursor->restoreState(); | 2800 | cursor->restoreState(); |
2791 | doc->setText( text, context ); | 2801 | doc->setText( text, context ); |
2792 | 2802 | ||
2793 | if ( wrapMode == FixedPixelWidth ) { | 2803 | if ( wrapMode == FixedPixelWidth ) { |
2794 | resizeContents( wrapWidth, 0 ); | 2804 | resizeContents( wrapWidth, 0 ); |
2795 | doc->setWidth( wrapWidth ); | 2805 | doc->setWidth( wrapWidth ); |
2796 | doc->setMinimumWidth( wrapWidth ); | 2806 | doc->setMinimumWidth( wrapWidth ); |
2797 | } else { | 2807 | } else { |
2798 | doc->setMinimumWidth( -1 ); | 2808 | doc->setMinimumWidth( -1 ); |
2799 | resizeContents( 0, 0 ); | 2809 | resizeContents( 0, 0 ); |
2800 | } | 2810 | } |
2801 | 2811 | ||
2802 | cursor->setDocument( doc ); | 2812 | lastFormatted = doc->firstParagraph(); |
2803 | lastFormatted = doc->firstParag(); | 2813 | delete cursor; |
2804 | cursor->setParag( doc->firstParag() ); | 2814 | cursor = new QTextCursor( doc ); |
2805 | cursor->setIndex( 0 ); | ||
2806 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); | 2815 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); |
2807 | 2816 | ||
2808 | if ( isModified() ) | 2817 | if ( isModified() ) |
2809 | setModified( FALSE ); | 2818 | setModified( FALSE ); |
2810 | emit textChanged(); | 2819 | emit textChanged(); |
2811 | formatMore(); | 2820 | formatMore(); |
2812 | updateCurrentFormat(); | 2821 | updateCurrentFormat(); |
2822 | d->scrollToAnchor = QString::null; | ||
2813 | } | 2823 | } |
2814 | 2824 | ||
2815 | /*! | 2825 | /*! |
2816 | \property QTextEdit::text | 2826 | \property QTextEdit::text |
2817 | \brief the text edit's text | 2827 | \brief the text edit's text |
2818 | 2828 | ||
2819 | There is no default text. | 2829 | There is no default text. |
2820 | 2830 | ||
2821 | On setting, any previous text is deleted. | 2831 | On setting, any previous text is deleted. |
2822 | 2832 | ||
2823 | The text may be interpreted either as plain text or as rich text, | 2833 | The text may be interpreted either as plain text or as rich text, |
2824 | depending on the textFormat(). The default setting is \c AutoText, | 2834 | depending on the textFormat(). The default setting is \c AutoText, |
2825 | i.e. the text edit autodetects the format of the text. | 2835 | i.e. the text edit autodetects the format of the text. |
2826 | 2836 | ||
2827 | For richtext, calling text() on an editable QTextEdit will cause the text | 2837 | For richtext, calling text() on an editable QTextEdit will cause the text |
2828 | to be regenerated from the textedit. This may mean that the QString returned | 2838 | to be regenerated from the textedit. This may mean that the QString returned |
2829 | may not be exactly the same as the one that was set. | 2839 | may not be exactly the same as the one that was set. |
2830 | 2840 | ||
2831 | \sa textFormat | 2841 | \sa textFormat |
2832 | */ | 2842 | */ |
2833 | 2843 | ||
2834 | 2844 | ||
2835 | /*! | 2845 | /*! |
2836 | \property QTextEdit::readOnly | 2846 | \property QTextEdit::readOnly |
2837 | \brief whether the text edit is read-only | 2847 | \brief whether the text edit is read-only |
2838 | 2848 | ||
2839 | In a read-only text edit the user can only navigate through the text | 2849 | In a read-only text edit the user can only navigate through the text |
2840 | and select text; modifying the text is not possible. | 2850 | and select text; modifying the text is not possible. |
2841 | 2851 | ||
2842 | This property's default is FALSE. | 2852 | This property's default is FALSE. |
2843 | */ | 2853 | */ |
2844 | 2854 | ||
2845 | /*! | 2855 | /*! |
2846 | Finds the next occurrence of the string, \a expr. Returns TRUE if | 2856 | Finds the next occurrence of the string, \a expr. Returns TRUE if |
2847 | \a expr is found; otherwise returns FALSE. | 2857 | \a expr is found; otherwise returns FALSE. |
2848 | 2858 | ||
2849 | If \a para and \a index are both null the search begins from the | 2859 | If \a para and \a index are both null the search begins from the |
2850 | start of the text. If \a para and \a index are both not null, the | 2860 | current cursor position. If \a para and \a index are both not |
2851 | search begins from the \e *\a index character position in the \e | 2861 | null, the search begins from the \e *\a index character position |
2852 | *\a para paragraph. | 2862 | in the \e *\a para paragraph. |
2853 | 2863 | ||
2854 | If \a cs is TRUE the search is case sensitive, otherwise it is | 2864 | If \a cs is TRUE the search is case sensitive, otherwise it is |
2855 | case insensitive. If \a wo is TRUE the search looks for whole word | 2865 | case insensitive. If \a wo is TRUE the search looks for whole word |
2856 | matches only; otherwise it searches for any matching text. If \a | 2866 | matches only; otherwise it searches for any matching text. If \a |
2857 | forward is TRUE (the default) the search works forward from the | 2867 | forward is TRUE (the default) the search works forward from the |
2858 | starting position to the end of the text, otherwise it works | 2868 | starting position to the end of the text, otherwise it works |
2859 | backwards to the beginning of the text. | 2869 | backwards to the beginning of the text. |
2860 | 2870 | ||
2861 | If \a expr is found the function returns TRUE. If \a index and \a | 2871 | If \a expr is found the function returns TRUE. If \a index and \a |
2862 | para are not null, the number of the paragraph in which the first | 2872 | para are not null, the number of the paragraph in which the first |
2863 | character of the match was found is put into \e *\a para, and the | 2873 | character of the match was found is put into \e *\a para, and the |
2864 | index position of that character within the paragraph is put into | 2874 | index position of that character within the paragraph is put into |
2865 | \e *\a index. | 2875 | \e *\a index. |
2866 | 2876 | ||
2867 | If \a expr is not found the function returns FALSE. If \a index | 2877 | If \a expr is not found the function returns FALSE. If \a index |
2868 | and \a para are not null and \a expr is not found, \e *\a index | 2878 | and \a para are not null and \a expr is not found, \e *\a index |
2869 | and \e *\a para are undefined. | 2879 | and \e *\a para are undefined. |
2870 | */ | 2880 | */ |
2871 | 2881 | ||
2872 | bool QTextEdit::find( const QString &expr, bool cs, bool wo, bool forward, | 2882 | bool QTextEdit::find( const QString &expr, bool cs, bool wo, bool forward, |
2873 | int *para, int *index ) | 2883 | int *para, int *index ) |
2874 | { | 2884 | { |
2875 | drawCursor( FALSE ); | 2885 | drawCursor( FALSE ); |
2876 | doc->removeSelection( QTextDocument::Standard ); | ||
2877 | #ifndef QT_NO_CURSOR | 2886 | #ifndef QT_NO_CURSOR |
2878 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); | 2887 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); |
2879 | #endif | 2888 | #endif |
2880 | bool found = doc->find( expr, cs, wo, forward, para, index, cursor ); | 2889 | QTextCursor findcur = *cursor; |
2890 | if ( para && index ) { | ||
2891 | if ( doc->paragAt( *para ) ) | ||
2892 | findcur.gotoPosition( doc->paragAt(*para), *index ); | ||
2893 | else | ||
2894 | findcur.gotoEnd(); | ||
2895 | } else if ( doc->hasSelection( QTextDocument::Standard ) ){ | ||
2896 | // maks sure we do not find the same selection again | ||
2897 | if ( forward ) | ||
2898 | findcur.gotoNextLetter(); | ||
2899 | else | ||
2900 | findcur.gotoPreviousLetter(); | ||
2901 | } | ||
2902 | removeSelection( QTextDocument::Standard ); | ||
2903 | bool found = doc->find( findcur, expr, cs, wo, forward ); | ||
2904 | if ( found ) { | ||
2905 | if ( para ) | ||
2906 | *para = findcur.paragraph()->paragId(); | ||
2907 | if ( index ) | ||
2908 | *index = findcur.index(); | ||
2909 | *cursor = findcur; | ||
2910 | repaintChanged(); | ||
2881 | ensureCursorVisible(); | 2911 | ensureCursorVisible(); |
2912 | } | ||
2882 | drawCursor( TRUE ); | 2913 | drawCursor( TRUE ); |
2883 | repaintChanged(); | ||
2884 | return found; | 2914 | return found; |
2885 | } | 2915 | } |
2886 | 2916 | ||
2887 | void QTextEdit::blinkCursor() | 2917 | void QTextEdit::blinkCursor() |
2888 | { | 2918 | { |
2889 | if ( !cursorVisible ) | 2919 | if ( !cursorVisible ) |
2890 | return; | 2920 | return; |
2891 | bool cv = cursorVisible; | 2921 | bool cv = cursorVisible; |
2892 | blinkCursorVisible = !blinkCursorVisible; | 2922 | blinkCursorVisible = !blinkCursorVisible; |
2893 | drawCursor( blinkCursorVisible ); | 2923 | drawCursor( blinkCursorVisible ); |
2894 | cursorVisible = cv; | 2924 | cursorVisible = cv; |
2895 | } | 2925 | } |
2896 | 2926 | ||
2897 | /*! | 2927 | /*! |
2898 | Sets the cursor to position \a index in paragraph \a para. | 2928 | Sets the cursor to position \a index in paragraph \a para. |
2899 | 2929 | ||
2900 | \sa getCursorPosition() | 2930 | \sa getCursorPosition() |
2901 | */ | 2931 | */ |
2902 | 2932 | ||
2903 | void QTextEdit::setCursorPosition( int para, int index ) | 2933 | void QTextEdit::setCursorPosition( int para, int index ) |
2904 | { | 2934 | { |
2905 | QTextParag *p = doc->paragAt( para ); | 2935 | QTextParagraph *p = doc->paragAt( para ); |
2906 | if ( !p ) | 2936 | if ( !p ) |
2907 | return; | 2937 | return; |
2908 | 2938 | ||
2909 | if ( index > p->length() - 1 ) | 2939 | if ( index > p->length() - 1 ) |
2910 | index = p->length() - 1; | 2940 | index = p->length() - 1; |
2911 | 2941 | ||
2912 | drawCursor( FALSE ); | 2942 | drawCursor( FALSE ); |
2913 | cursor->setParag( p ); | 2943 | cursor->setParagraph( p ); |
2914 | cursor->setIndex( index ); | 2944 | cursor->setIndex( index ); |
2915 | ensureCursorVisible(); | 2945 | ensureCursorVisible(); |
2916 | drawCursor( TRUE ); | 2946 | drawCursor( TRUE ); |
2947 | updateCurrentFormat(); | ||
2917 | emit cursorPositionChanged( cursor ); | 2948 | emit cursorPositionChanged( cursor ); |
2918 | emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); | 2949 | emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); |
2919 | } | 2950 | } |
2920 | 2951 | ||
2921 | /*! | 2952 | /*! |
2922 | This function sets the \e *\a para and \e *\a index parameters to the | 2953 | This function sets the \e *\a para and \e *\a index parameters to the |
2923 | current cursor position. \a para and \a index must be non-null int | 2954 | current cursor position. \a para and \a index must be non-null int |
2924 | pointers. | 2955 | pointers. |
2925 | 2956 | ||
2926 | \sa setCursorPosition() | 2957 | \sa setCursorPosition() |
2927 | */ | 2958 | */ |
2928 | 2959 | ||
2929 | void QTextEdit::getCursorPosition( int *para, int *index ) const | 2960 | void QTextEdit::getCursorPosition( int *para, int *index ) const |
2930 | { | 2961 | { |
2931 | if ( !para || !index ) | 2962 | if ( !para || !index ) |
2932 | return; | 2963 | return; |
2933 | *para = cursor->parag()->paragId(); | 2964 | *para = cursor->paragraph()->paragId(); |
2934 | *index = cursor->index(); | 2965 | *index = cursor->index(); |
2935 | } | 2966 | } |
2936 | 2967 | ||
2937 | /*! Sets a selection which starts at position \a indexFrom in | 2968 | /*! Sets a selection which starts at position \a indexFrom in |
2938 | paragraph \a paraFrom and ends at position \a indexTo in paragraph | 2969 | paragraph \a paraFrom and ends at position \a indexTo in paragraph |
2939 | \a paraTo. Existing selections which have a different id (selNum) | 2970 | \a paraTo. Existing selections which have a different id (selNum) |
2940 | are not removed, existing selections which have the same id as \a | 2971 | are not removed, existing selections which have the same id as \a |
2941 | selNum are removed. | 2972 | selNum are removed. |
2942 | 2973 | ||
2943 | Uses the selection settings of selection \a selNum. If \a selNum is 0, | 2974 | Uses the selection settings of selection \a selNum. If \a selNum is 0, |
2944 | this is the default selection. | 2975 | this is the default selection. |
2945 | 2976 | ||
2946 | The cursor is moved to the end of the selection if \a selNum is 0, | 2977 | The cursor is moved to the end of the selection if \a selNum is 0, |
2947 | otherwise the cursor position remains unchanged. | 2978 | otherwise the cursor position remains unchanged. |
2948 | 2979 | ||
2949 | \sa getSelection() selectedText | 2980 | \sa getSelection() selectedText |
2950 | */ | 2981 | */ |
2951 | 2982 | ||
2952 | void QTextEdit::setSelection( int paraFrom, int indexFrom, | 2983 | void QTextEdit::setSelection( int paraFrom, int indexFrom, |
2953 | int paraTo, int indexTo, int selNum ) | 2984 | int paraTo, int indexTo, int selNum ) |
2954 | { | 2985 | { |
2955 | if ( doc->hasSelection( selNum ) ) { | 2986 | if ( doc->hasSelection( selNum ) ) { |
2956 | doc->removeSelection( selNum ); | 2987 | doc->removeSelection( selNum ); |
2957 | repaintChanged(); | 2988 | repaintChanged(); |
2958 | } | 2989 | } |
2959 | if ( selNum > doc->numSelections() - 1 ) | 2990 | if ( selNum > doc->numSelections() - 1 ) |
2960 | doc->addSelection( selNum ); | 2991 | doc->addSelection( selNum ); |
2961 | QTextParag *p1 = doc->paragAt( paraFrom ); | 2992 | QTextParagraph *p1 = doc->paragAt( paraFrom ); |
2962 | if ( !p1 ) | 2993 | if ( !p1 ) |
2963 | return; | 2994 | return; |
2964 | QTextParag *p2 = doc->paragAt( paraTo ); | 2995 | QTextParagraph *p2 = doc->paragAt( paraTo ); |
2965 | if ( !p2 ) | 2996 | if ( !p2 ) |
2966 | return; | 2997 | return; |
2967 | 2998 | ||
2968 | if ( indexFrom > p1->length() - 1 ) | 2999 | if ( indexFrom > p1->length() - 1 ) |
2969 | indexFrom = p1->length() - 1; | 3000 | indexFrom = p1->length() - 1; |
2970 | if ( indexTo > p2->length() - 1 ) | 3001 | if ( indexTo > p2->length() - 1 ) |
2971 | indexTo = p2->length() - 1; | 3002 | indexTo = p2->length() - 1; |
2972 | 3003 | ||
2973 | drawCursor( FALSE ); | 3004 | drawCursor( FALSE ); |
2974 | QTextCursor c = *cursor; | 3005 | QTextCursor c = *cursor; |
2975 | QTextCursor oldCursor = *cursor; | 3006 | QTextCursor oldCursor = *cursor; |
2976 | c.setParag( p1 ); | 3007 | c.setParagraph( p1 ); |
2977 | c.setIndex( indexFrom ); | 3008 | c.setIndex( indexFrom ); |
2978 | cursor->setParag( p2 ); | 3009 | cursor->setParagraph( p2 ); |
2979 | cursor->setIndex( indexTo ); | 3010 | cursor->setIndex( indexTo ); |
2980 | doc->setSelectionStart( selNum, &c ); | 3011 | doc->setSelectionStart( selNum, c ); |
2981 | doc->setSelectionEnd( selNum, cursor ); | 3012 | doc->setSelectionEnd( selNum, *cursor ); |
2982 | repaintChanged(); | 3013 | repaintChanged(); |
2983 | ensureCursorVisible(); | 3014 | ensureCursorVisible(); |
2984 | if ( selNum != QTextDocument::Standard ) | 3015 | if ( selNum != QTextDocument::Standard ) |
2985 | *cursor = oldCursor; | 3016 | *cursor = oldCursor; |
2986 | drawCursor( TRUE ); | 3017 | drawCursor( TRUE ); |
2987 | } | 3018 | } |
2988 | 3019 | ||
2989 | /*! | 3020 | /*! |
2990 | If there is a selection, \e *\a paraFrom is set to the number of the | 3021 | If there is a selection, \e *\a paraFrom is set to the number of the |
2991 | paragraph in which the selection begins and \e *\a paraTo is set to | 3022 | paragraph in which the selection begins and \e *\a paraTo is set to |
2992 | the number of the paragraph in which the selection ends. (They could | 3023 | the number of the paragraph in which the selection ends. (They could |
2993 | be the same.) \e *\a indexFrom is set to the index at which the | 3024 | be the same.) \e *\a indexFrom is set to the index at which the |
2994 | selection begins within \e *\a paraFrom, and \e *\a indexTo is set to | 3025 | selection begins within \e *\a paraFrom, and \e *\a indexTo is set to |
2995 | the index at which the selection ends within \e *\a paraTo. | 3026 | the index at which the selection ends within \e *\a paraTo. |
2996 | 3027 | ||
2997 | If there is no selection, \e *\a paraFrom, \e *\a indexFrom, \e *\a | 3028 | If there is no selection, \e *\a paraFrom, \e *\a indexFrom, \e *\a |
2998 | paraTo and \e *\a indexTo are all set to -1. | 3029 | paraTo and \e *\a indexTo are all set to -1. |
2999 | 3030 | ||
3000 | \a paraFrom, \a indexFrom, \a paraTo and \a indexTo must be non-null | 3031 | \a paraFrom, \a indexFrom, \a paraTo and \a indexTo must be non-null |
3001 | int pointers. | 3032 | int pointers. |
3002 | 3033 | ||
3003 | The \a selNum is the number of the selection (multiple selections | 3034 | The \a selNum is the number of the selection (multiple selections |
3004 | are supported). It defaults to 0 (the default selection). | 3035 | are supported). It defaults to 0 (the default selection). |
3005 | 3036 | ||
@@ -3035,108 +3066,108 @@ void QTextEdit::getSelection( int *paraFrom, int *indexFrom, | |||
3035 | \i RichText - rich text rendering. The available styles are | 3066 | \i RichText - rich text rendering. The available styles are |
3036 | defined in the default stylesheet QStyleSheet::defaultSheet(). | 3067 | defined in the default stylesheet QStyleSheet::defaultSheet(). |
3037 | \i AutoText - this is the default. The text edit autodetects | 3068 | \i AutoText - this is the default. The text edit autodetects |
3038 | which rendering style is best, \c PlainText or \c RichText. This is | 3069 | which rendering style is best, \c PlainText or \c RichText. This is |
3039 | done by using the QStyleSheet::mightBeRichText() function. | 3070 | done by using the QStyleSheet::mightBeRichText() function. |
3040 | \endlist | 3071 | \endlist |
3041 | */ | 3072 | */ |
3042 | 3073 | ||
3043 | void QTextEdit::setTextFormat( TextFormat format ) | 3074 | void QTextEdit::setTextFormat( TextFormat format ) |
3044 | { | 3075 | { |
3045 | doc->setTextFormat( format ); | 3076 | doc->setTextFormat( format ); |
3046 | } | 3077 | } |
3047 | 3078 | ||
3048 | Qt::TextFormat QTextEdit::textFormat() const | 3079 | Qt::TextFormat QTextEdit::textFormat() const |
3049 | { | 3080 | { |
3050 | return doc->textFormat(); | 3081 | return doc->textFormat(); |
3051 | } | 3082 | } |
3052 | 3083 | ||
3053 | /*! | 3084 | /*! |
3054 | Returns the number of paragraphs in the text; this could be 0. | 3085 | Returns the number of paragraphs in the text; this could be 0. |
3055 | */ | 3086 | */ |
3056 | 3087 | ||
3057 | int QTextEdit::paragraphs() const | 3088 | int QTextEdit::paragraphs() const |
3058 | { | 3089 | { |
3059 | return doc->lastParag()->paragId() + 1; | 3090 | return doc->lastParagraph()->paragId() + 1; |
3060 | } | 3091 | } |
3061 | 3092 | ||
3062 | /*! | 3093 | /*! |
3063 | Returns the number of lines in paragraph \a para, or -1 if there | 3094 | Returns the number of lines in paragraph \a para, or -1 if there |
3064 | is no paragraph with index \a para. | 3095 | is no paragraph with index \a para. |
3065 | */ | 3096 | */ |
3066 | 3097 | ||
3067 | int QTextEdit::linesOfParagraph( int para ) const | 3098 | int QTextEdit::linesOfParagraph( int para ) const |
3068 | { | 3099 | { |
3069 | QTextParag *p = doc->paragAt( para ); | 3100 | QTextParagraph *p = doc->paragAt( para ); |
3070 | if ( !p ) | 3101 | if ( !p ) |
3071 | return -1; | 3102 | return -1; |
3072 | return p->lines(); | 3103 | return p->lines(); |
3073 | } | 3104 | } |
3074 | 3105 | ||
3075 | /*! | 3106 | /*! |
3076 | Returns the length of the paragraph \a para (number of | 3107 | Returns the length of the paragraph \a para (number of |
3077 | characters), or -1 if there is no paragraph with index \a para | 3108 | characters), or -1 if there is no paragraph with index \a para |
3078 | */ | 3109 | */ |
3079 | 3110 | ||
3080 | int QTextEdit::paragraphLength( int para ) const | 3111 | int QTextEdit::paragraphLength( int para ) const |
3081 | { | 3112 | { |
3082 | QTextParag *p = doc->paragAt( para ); | 3113 | QTextParagraph *p = doc->paragAt( para ); |
3083 | if ( !p ) | 3114 | if ( !p ) |
3084 | return -1; | 3115 | return -1; |
3085 | return p->length() - 1; | 3116 | return p->length() - 1; |
3086 | } | 3117 | } |
3087 | 3118 | ||
3088 | /*! | 3119 | /*! |
3089 | Returns the number of lines in the text edit; this could be 0. | 3120 | Returns the number of lines in the text edit; this could be 0. |
3090 | 3121 | ||
3091 | \warning This function may be slow. Lines change all the time | 3122 | \warning This function may be slow. Lines change all the time |
3092 | during word wrapping, so this function has to iterate over all the | 3123 | during word wrapping, so this function has to iterate over all the |
3093 | paragraphs and get the number of lines from each one individually. | 3124 | paragraphs and get the number of lines from each one individually. |
3094 | */ | 3125 | */ |
3095 | 3126 | ||
3096 | int QTextEdit::lines() const | 3127 | int QTextEdit::lines() const |
3097 | { | 3128 | { |
3098 | QTextParag *p = doc->firstParag(); | 3129 | QTextParagraph *p = doc->firstParagraph(); |
3099 | int l = 0; | 3130 | int l = 0; |
3100 | while ( p ) { | 3131 | while ( p ) { |
3101 | l += p->lines(); | 3132 | l += p->lines(); |
3102 | p = p->next(); | 3133 | p = p->next(); |
3103 | } | 3134 | } |
3104 | 3135 | ||
3105 | return l; | 3136 | return l; |
3106 | } | 3137 | } |
3107 | 3138 | ||
3108 | /*! | 3139 | /*! |
3109 | Returns the line number of the line in paragraph \a para in which | 3140 | Returns the line number of the line in paragraph \a para in which |
3110 | the character at position \a index appears. The \a index position is | 3141 | the character at position \a index appears. The \a index position is |
3111 | relative to the beginning of the paragraph. If there is no such | 3142 | relative to the beginning of the paragraph. If there is no such |
3112 | paragraph or no such character at the \a index position (e.g. the | 3143 | paragraph or no such character at the \a index position (e.g. the |
3113 | index is out of range) -1 is returned. | 3144 | index is out of range) -1 is returned. |
3114 | */ | 3145 | */ |
3115 | 3146 | ||
3116 | int QTextEdit::lineOfChar( int para, int index ) | 3147 | int QTextEdit::lineOfChar( int para, int index ) |
3117 | { | 3148 | { |
3118 | QTextParag *p = doc->paragAt( para ); | 3149 | QTextParagraph *p = doc->paragAt( para ); |
3119 | if ( !p ) | 3150 | if ( !p ) |
3120 | return -1; | 3151 | return -1; |
3121 | 3152 | ||
3122 | int idx, line; | 3153 | int idx, line; |
3123 | QTextStringChar *c = p->lineStartOfChar( index, &idx, &line ); | 3154 | QTextStringChar *c = p->lineStartOfChar( index, &idx, &line ); |
3124 | if ( !c ) | 3155 | if ( !c ) |
3125 | return -1; | 3156 | return -1; |
3126 | 3157 | ||
3127 | return line; | 3158 | return line; |
3128 | } | 3159 | } |
3129 | 3160 | ||
3130 | void QTextEdit::setModified( bool m ) | 3161 | void QTextEdit::setModified( bool m ) |
3131 | { | 3162 | { |
3132 | bool oldModified = modified; | 3163 | bool oldModified = modified; |
3133 | modified = m; | 3164 | modified = m; |
3134 | if ( modified && doc->oTextValid ) | 3165 | if ( modified && doc->oTextValid ) |
3135 | doc->invalidateOriginalText(); | 3166 | doc->invalidateOriginalText(); |
3136 | if ( oldModified != modified ) | 3167 | if ( oldModified != modified ) |
3137 | emit modificationChanged( modified ); | 3168 | emit modificationChanged( modified ); |
3138 | } | 3169 | } |
3139 | 3170 | ||
3140 | /*! \property QTextEdit::modified | 3171 | /*! \property QTextEdit::modified |
3141 | \brief whether the document has been modified by the user | 3172 | \brief whether the document has been modified by the user |
3142 | */ | 3173 | */ |
@@ -3227,141 +3258,139 @@ QColor QTextEdit::color() const | |||
3227 | 3258 | ||
3228 | */ | 3259 | */ |
3229 | 3260 | ||
3230 | QFont QTextEdit::font() const | 3261 | QFont QTextEdit::font() const |
3231 | { | 3262 | { |
3232 | return currentFormat->font(); | 3263 | return currentFormat->font(); |
3233 | } | 3264 | } |
3234 | 3265 | ||
3235 | /*! | 3266 | /*! |
3236 | Returns the alignment of the current paragraph. | 3267 | Returns the alignment of the current paragraph. |
3237 | 3268 | ||
3238 | \sa setAlignment() | 3269 | \sa setAlignment() |
3239 | */ | 3270 | */ |
3240 | 3271 | ||
3241 | int QTextEdit::alignment() const | 3272 | int QTextEdit::alignment() const |
3242 | { | 3273 | { |
3243 | return currentAlignment; | 3274 | return currentAlignment; |
3244 | } | 3275 | } |
3245 | 3276 | ||
3246 | void QTextEdit::startDrag() | 3277 | void QTextEdit::startDrag() |
3247 | { | 3278 | { |
3248 | #ifndef QT_NO_DRAGANDDROP | 3279 | #ifndef QT_NO_DRAGANDDROP |
3249 | mousePressed = FALSE; | 3280 | mousePressed = FALSE; |
3250 | inDoubleClick = FALSE; | 3281 | inDoubleClick = FALSE; |
3251 | QDragObject *drag = new QTextDrag( doc->selectedText( QTextDocument::Standard ), viewport() ); | 3282 | QDragObject *drag = new QTextDrag( doc->selectedText( QTextDocument::Standard, qt_enable_richtext_copy ), viewport() ); |
3252 | if ( isReadOnly() ) { | 3283 | if ( isReadOnly() ) { |
3253 | drag->dragCopy(); | 3284 | drag->dragCopy(); |
3254 | } else { | 3285 | } else { |
3255 | if ( drag->drag() && QDragObject::target() != this && QDragObject::target() != viewport() ) | 3286 | if ( drag->drag() && QDragObject::target() != this && QDragObject::target() != viewport() ) |
3256 | removeSelectedText(); | 3287 | removeSelectedText(); |
3257 | } | 3288 | } |
3258 | #endif | 3289 | #endif |
3259 | } | 3290 | } |
3260 | 3291 | ||
3261 | /*! | 3292 | /*! |
3262 | If \a select is TRUE (the default), all the text is selected as | 3293 | If \a select is TRUE (the default), all the text is selected as |
3263 | selection 0. | 3294 | selection 0. |
3264 | If \a select is FALSE any selected text is unselected, i.e., the | 3295 | If \a select is FALSE any selected text is unselected, i.e., the |
3265 | default selection (selection 0) is cleared. | 3296 | default selection (selection 0) is cleared. |
3266 | 3297 | ||
3267 | \sa selectedText | 3298 | \sa selectedText |
3268 | */ | 3299 | */ |
3269 | 3300 | ||
3270 | void QTextEdit::selectAll( bool select ) | 3301 | void QTextEdit::selectAll( bool select ) |
3271 | { | 3302 | { |
3272 | if ( !select ) | 3303 | if ( !select ) |
3273 | doc->removeSelection( QTextDocument::Standard ); | 3304 | doc->removeSelection( QTextDocument::Standard ); |
3274 | else | 3305 | else |
3275 | doc->selectAll( QTextDocument::Standard ); | 3306 | doc->selectAll( QTextDocument::Standard ); |
3276 | repaintChanged(); | 3307 | repaintChanged(); |
3277 | emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) ); | 3308 | emit copyAvailable( doc->hasSelection( QTextDocument::Standard ) ); |
3278 | emit selectionChanged(); | 3309 | emit selectionChanged(); |
3279 | #ifndef QT_NO_CURSOR | 3310 | #ifndef QT_NO_CURSOR |
3280 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); | 3311 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); |
3281 | #endif | 3312 | #endif |
3282 | } | 3313 | } |
3283 | 3314 | ||
3284 | void QTextEdit::UndoRedoInfo::clear() | 3315 | void QTextEdit::UndoRedoInfo::clear() |
3285 | { | 3316 | { |
3286 | if ( valid() ) { | 3317 | if ( valid() ) { |
3287 | if ( type == Insert || type == Return ) | 3318 | if ( type == Insert || type == Return ) |
3288 | doc->addCommand( new QTextInsertCommand( doc, id, index, d->text.rawData(), oldStyles, oldListStyles, oldAligns ) ); | 3319 | doc->addCommand( new QTextInsertCommand( doc, id, index, d->text.rawData(), styleInformation ) ); |
3289 | else if ( type == Format ) | 3320 | else if ( type == Format ) |
3290 | doc->addCommand( new QTextFormatCommand( doc, id, index, eid, eindex, d->text.rawData(), format, flags ) ); | 3321 | doc->addCommand( new QTextFormatCommand( doc, id, index, eid, eindex, d->text.rawData(), format, flags ) ); |
3291 | else if ( type == Alignment ) | 3322 | else if ( type == Style ) |
3292 | doc->addCommand( new QTextAlignmentCommand( doc, id, eid, newAlign, oldAligns ) ); | 3323 | doc->addCommand( new QTextStyleCommand( doc, id, eid, styleInformation ) ); |
3293 | else if ( type == ParagType ) | 3324 | else if ( type != Invalid ) { |
3294 | doc->addCommand( new QTextParagTypeCommand( doc, id, eid, list, listStyle, oldStyles, oldListStyles ) ); | 3325 | doc->addCommand( new QTextDeleteCommand( doc, id, index, d->text.rawData(), styleInformation ) ); |
3295 | else if ( type != Invalid ) | 3326 | } |
3296 | doc->addCommand( new QTextDeleteCommand( doc, id, index, d->text.rawData(), oldStyles, oldListStyles, oldAligns ) ); | ||
3297 | } | 3327 | } |
3328 | type = Invalid; | ||
3298 | d->text = QString::null; | 3329 | d->text = QString::null; |
3299 | id = -1; | 3330 | id = -1; |
3300 | index = -1; | 3331 | index = -1; |
3301 | oldStyles.clear(); | 3332 | styleInformation = QByteArray(); |
3302 | oldListStyles.clear(); | ||
3303 | oldAligns.resize( 0 ); | ||
3304 | } | 3333 | } |
3305 | 3334 | ||
3306 | 3335 | ||
3307 | /*! | 3336 | /*! |
3308 | If there is some selected text (in selection 0) it is deleted. If | 3337 | If there is some selected text (in selection 0) it is deleted. If |
3309 | there is no selected text (in selection 0) the character to the | 3338 | there is no selected text (in selection 0) the character to the |
3310 | right of the text cursor is deleted. | 3339 | right of the text cursor is deleted. |
3311 | 3340 | ||
3312 | \sa removeSelectedText() cut() | 3341 | \sa removeSelectedText() cut() |
3313 | 3342 | ||
3314 | */ | 3343 | */ |
3315 | 3344 | ||
3316 | void QTextEdit::del() | 3345 | void QTextEdit::del() |
3317 | { | 3346 | { |
3318 | if ( doc->hasSelection( QTextDocument::Standard ) ) { | 3347 | if ( doc->hasSelection( QTextDocument::Standard ) ) { |
3319 | removeSelectedText(); | 3348 | removeSelectedText(); |
3320 | return; | 3349 | return; |
3321 | } | 3350 | } |
3322 | 3351 | ||
3323 | doKeyboardAction( ActionDelete ); | 3352 | doKeyboardAction( ActionDelete ); |
3324 | } | 3353 | } |
3325 | 3354 | ||
3326 | 3355 | ||
3327 | QTextEdit::UndoRedoInfo::UndoRedoInfo( QTextDocument *dc ) | 3356 | QTextEdit::UndoRedoInfo::UndoRedoInfo( QTextDocument *dc ) |
3328 | : type( Invalid ), doc( dc ) | 3357 | : type( Invalid ), doc( dc ) |
3329 | { | 3358 | { |
3330 | d = new QUndoRedoInfoPrivate; | 3359 | d = new QUndoRedoInfoPrivate; |
3331 | d->text = QString::null; | 3360 | d->text = QString::null; |
3332 | id = -1; | 3361 | id = -1; |
3333 | index = -1; | 3362 | index = -1; |
3334 | } | 3363 | } |
3335 | 3364 | ||
3336 | QTextEdit::UndoRedoInfo::~UndoRedoInfo() | 3365 | QTextEdit::UndoRedoInfo::~UndoRedoInfo() |
3337 | { | 3366 | { |
3338 | delete d; | 3367 | delete d; |
3339 | } | 3368 | } |
3340 | 3369 | ||
3341 | bool QTextEdit::UndoRedoInfo::valid() const | 3370 | bool QTextEdit::UndoRedoInfo::valid() const |
3342 | { | 3371 | { |
3343 | return d->text.length() > 0 && id >= 0 && index >= 0; | 3372 | return id >= 0 && type != Invalid; |
3344 | } | 3373 | } |
3345 | 3374 | ||
3346 | /*! | 3375 | /*! |
3347 | \internal | 3376 | \internal |
3348 | 3377 | ||
3349 | Resets the current format to the default format. | 3378 | Resets the current format to the default format. |
3350 | */ | 3379 | */ |
3351 | 3380 | ||
3352 | void QTextEdit::resetFormat() | 3381 | void QTextEdit::resetFormat() |
3353 | { | 3382 | { |
3354 | setAlignment( Qt3::AlignAuto ); | 3383 | setAlignment( Qt3::AlignAuto ); |
3355 | setParagType( QStyleSheetItem::DisplayBlock, QStyleSheetItem::ListDisc ); | 3384 | setParagType( QStyleSheetItem::DisplayBlock, QStyleSheetItem::ListDisc ); |
3356 | setFormat( doc->formatCollection()->defaultFormat(), QTextFormat::Format ); | 3385 | setFormat( doc->formatCollection()->defaultFormat(), QTextFormat::Format ); |
3357 | } | 3386 | } |
3358 | 3387 | ||
3359 | /*! Returns the QStyleSheet which is currently used in this text edit. | 3388 | /*! Returns the QStyleSheet which is currently used in this text edit. |
3360 | 3389 | ||
3361 | \sa setStyleSheet() | 3390 | \sa setStyleSheet() |
3362 | */ | 3391 | */ |
3363 | 3392 | ||
3364 | QStyleSheet* QTextEdit::styleSheet() const | 3393 | QStyleSheet* QTextEdit::styleSheet() const |
3365 | { | 3394 | { |
3366 | return doc->styleSheet(); | 3395 | return doc->styleSheet(); |
3367 | } | 3396 | } |
@@ -3388,52 +3417,49 @@ void QTextEdit::setStyleSheet( QStyleSheet* styleSheet ) | |||
3388 | void QTextEdit::setPaper( const QBrush& pap ) | 3417 | void QTextEdit::setPaper( const QBrush& pap ) |
3389 | { | 3418 | { |
3390 | doc->setPaper( new QBrush( pap ) ); | 3419 | doc->setPaper( new QBrush( pap ) ); |
3391 | viewport()->setBackgroundColor( pap.color() ); | 3420 | viewport()->setBackgroundColor( pap.color() ); |
3392 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); | 3421 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); |
3393 | } | 3422 | } |
3394 | 3423 | ||
3395 | QBrush QTextEdit::paper() const | 3424 | QBrush QTextEdit::paper() const |
3396 | { | 3425 | { |
3397 | if ( doc->paper() ) | 3426 | if ( doc->paper() ) |
3398 | return *doc->paper(); | 3427 | return *doc->paper(); |
3399 | return QBrush(); | 3428 | return QBrush(); |
3400 | } | 3429 | } |
3401 | 3430 | ||
3402 | /*! | 3431 | /*! |
3403 | \property QTextEdit::linkUnderline | 3432 | \property QTextEdit::linkUnderline |
3404 | \brief whether hypertext links will be underlined | 3433 | \brief whether hypertext links will be underlined |
3405 | 3434 | ||
3406 | If TRUE (the default) hypertext links will be displayed underlined. | 3435 | If TRUE (the default) hypertext links will be displayed underlined. |
3407 | If FALSE links will not be displayed underlined. | 3436 | If FALSE links will not be displayed underlined. |
3408 | */ | 3437 | */ |
3409 | 3438 | ||
3410 | void QTextEdit::setLinkUnderline( bool b ) | 3439 | void QTextEdit::setLinkUnderline( bool b ) |
3411 | { | 3440 | { |
3412 | if ( b == doc->underlineLinks() ) | ||
3413 | return; | ||
3414 | doc->setUnderlineLinks( b ); | 3441 | doc->setUnderlineLinks( b ); |
3415 | updateStyles(); | ||
3416 | } | 3442 | } |
3417 | 3443 | ||
3418 | bool QTextEdit::linkUnderline() const | 3444 | bool QTextEdit::linkUnderline() const |
3419 | { | 3445 | { |
3420 | return doc->underlineLinks(); | 3446 | return doc->underlineLinks(); |
3421 | } | 3447 | } |
3422 | 3448 | ||
3423 | /*! Sets the text edit's mimesource factory to \a factory. See | 3449 | /*! Sets the text edit's mimesource factory to \a factory. See |
3424 | QMimeSourceFactory for further details. | 3450 | QMimeSourceFactory for further details. |
3425 | 3451 | ||
3426 | \sa mimeSourceFactory() | 3452 | \sa mimeSourceFactory() |
3427 | */ | 3453 | */ |
3428 | 3454 | ||
3429 | void QTextEdit::setMimeSourceFactory( QMimeSourceFactory* factory ) | 3455 | void QTextEdit::setMimeSourceFactory( QMimeSourceFactory* factory ) |
3430 | { | 3456 | { |
3431 | doc->setMimeSourceFactory( factory ); | 3457 | doc->setMimeSourceFactory( factory ); |
3432 | } | 3458 | } |
3433 | 3459 | ||
3434 | /*! Returns the QMimeSourceFactory which is currently used by this | 3460 | /*! Returns the QMimeSourceFactory which is currently used by this |
3435 | text edit. | 3461 | text edit. |
3436 | 3462 | ||
3437 | \sa setMimeSourceFactory() | 3463 | \sa setMimeSourceFactory() |
3438 | */ | 3464 | */ |
3439 | 3465 | ||
@@ -3444,89 +3470,90 @@ QMimeSourceFactory* QTextEdit::mimeSourceFactory() const | |||
3444 | 3470 | ||
3445 | /*! | 3471 | /*! |
3446 | Returns how many pixels high the text edit needs to be to display | 3472 | Returns how many pixels high the text edit needs to be to display |
3447 | all the text if the text edit is \a w pixels wide. | 3473 | all the text if the text edit is \a w pixels wide. |
3448 | */ | 3474 | */ |
3449 | 3475 | ||
3450 | int QTextEdit::heightForWidth( int w ) const | 3476 | int QTextEdit::heightForWidth( int w ) const |
3451 | { | 3477 | { |
3452 | int oldw = doc->width(); | 3478 | int oldw = doc->width(); |
3453 | doc->doLayout( 0, w ); | 3479 | doc->doLayout( 0, w ); |
3454 | int h = doc->height(); | 3480 | int h = doc->height(); |
3455 | doc->setWidth( oldw ); | 3481 | doc->setWidth( oldw ); |
3456 | doc->invalidate(); | 3482 | doc->invalidate(); |
3457 | ( (QTextEdit*)this )->formatMore(); | 3483 | ( (QTextEdit*)this )->formatMore(); |
3458 | return h; | 3484 | return h; |
3459 | } | 3485 | } |
3460 | 3486 | ||
3461 | /*! Appends the text \a text to the end of the text edit. | 3487 | /*! Appends the text \a text to the end of the text edit. |
3462 | Note that the undo/redo history is cleared by this function. | 3488 | Note that the undo/redo history is cleared by this function. |
3463 | */ | 3489 | */ |
3464 | 3490 | ||
3465 | void QTextEdit::append( const QString &text ) | 3491 | void QTextEdit::append( const QString &text ) |
3466 | { | 3492 | { |
3467 | // flush and clear the undo/redo stack if necessary | 3493 | // flush and clear the undo/redo stack if necessary |
3468 | if ( isReadOnly() && undoRedoInfo.valid() ) { | ||
3469 | undoRedoInfo.clear(); | 3494 | undoRedoInfo.clear(); |
3470 | doc->commands()->clear(); | 3495 | doc->commands()->clear(); |
3471 | } | 3496 | |
3472 | doc->removeSelection( QTextDocument::Standard ); | 3497 | doc->removeSelection( QTextDocument::Standard ); |
3473 | TextFormat f = doc->textFormat(); | 3498 | TextFormat f = doc->textFormat(); |
3474 | if ( f == AutoText ) { | 3499 | if ( f == AutoText ) { |
3475 | if ( QStyleSheet::mightBeRichText( text ) ) | 3500 | if ( QStyleSheet::mightBeRichText( text ) ) |
3476 | f = RichText; | 3501 | f = RichText; |
3477 | else | 3502 | else |
3478 | f = PlainText; | 3503 | f = PlainText; |
3479 | } | 3504 | } |
3480 | if ( f == PlainText ) { | 3505 | |
3506 | drawCursor( FALSE ); | ||
3481 | QTextCursor oldc( *cursor ); | 3507 | QTextCursor oldc( *cursor ); |
3482 | ensureFormatted( doc->lastParag() ); | 3508 | ensureFormatted( doc->lastParagraph() ); |
3483 | bool scrollToEnd = contentsY() >= contentsHeight() - visibleHeight() - | 3509 | bool atBottom = contentsY() >= contentsHeight() - visibleHeight(); |
3484 | ( horizontalScrollBar()->isVisible() ? horizontalScrollBar()->height() : 0 ); | ||
3485 | if ( !scrollToEnd ) | ||
3486 | blockEnsureCursorVisible = TRUE; | ||
3487 | cursor->gotoEnd(); | 3510 | cursor->gotoEnd(); |
3488 | if ( cursor->index() > 0 ) | 3511 | if ( cursor->index() > 0 ) |
3489 | cursor->splitAndInsertEmptyParag(); | 3512 | cursor->splitAndInsertEmptyParagraph(); |
3490 | QTextCursor oldCursor2 = *cursor; | 3513 | QTextCursor oldCursor2 = *cursor; |
3514 | |||
3515 | if ( f == Qt::PlainText ) { | ||
3491 | cursor->insert( text, TRUE ); | 3516 | cursor->insert( text, TRUE ); |
3492 | if ( doc->useFormatCollection() && currentFormat != cursor->parag()->at( cursor->index() )->format() ) { | 3517 | if ( doc->useFormatCollection() && |
3493 | doc->setSelectionStart( QTextDocument::Temp, &oldCursor2 ); | 3518 | currentFormat != cursor->paragraph()->at( cursor->index() )->format() ) { |
3494 | doc->setSelectionEnd( QTextDocument::Temp, cursor ); | 3519 | doc->setSelectionStart( QTextDocument::Temp, oldCursor2 ); |
3520 | doc->setSelectionEnd( QTextDocument::Temp, *cursor ); | ||
3495 | doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format ); | 3521 | doc->setFormat( QTextDocument::Temp, currentFormat, QTextFormat::Format ); |
3496 | doc->removeSelection( QTextDocument::Temp ); | 3522 | doc->removeSelection( QTextDocument::Temp ); |
3497 | } | 3523 | } |
3524 | } else { | ||
3525 | if ( cursor->paragraph()->prev() ) | ||
3526 | cursor->paragraph()->prev()->invalidate(0); // vertical margins might have to change | ||
3527 | doc->setRichTextInternal( text ); | ||
3528 | } | ||
3498 | formatMore(); | 3529 | formatMore(); |
3499 | repaintChanged(); | 3530 | repaintChanged(); |
3500 | ensureCursorVisible(); | 3531 | if ( atBottom ) |
3501 | drawCursor( TRUE ); | 3532 | scrollToBottom(); |
3502 | *cursor = oldc; | 3533 | *cursor = oldc; |
3503 | if ( !scrollToEnd ) | 3534 | if ( !isReadOnly() ) |
3504 | blockEnsureCursorVisible = FALSE; | 3535 | cursorVisible = TRUE; |
3505 | } else if ( f == RichText ) { | ||
3506 | doc->setRichTextInternal( text ); | ||
3507 | repaintChanged(); | ||
3508 | } | ||
3509 | setModified(); | 3536 | setModified(); |
3510 | emit textChanged(); | 3537 | emit textChanged(); |
3511 | } | 3538 | } |
3512 | 3539 | ||
3513 | /*! \property QTextEdit::hasSelectedText | 3540 | /*! \property QTextEdit::hasSelectedText |
3514 | \brief whether some text is selected in selection 0 | 3541 | \brief whether some text is selected in selection 0 |
3515 | */ | 3542 | */ |
3516 | 3543 | ||
3517 | bool QTextEdit::hasSelectedText() const | 3544 | bool QTextEdit::hasSelectedText() const |
3518 | { | 3545 | { |
3519 | return doc->hasSelection( QTextDocument::Standard ); | 3546 | return doc->hasSelection( QTextDocument::Standard ); |
3520 | } | 3547 | } |
3521 | 3548 | ||
3522 | /*!\property QTextEdit::selectedText | 3549 | /*!\property QTextEdit::selectedText |
3523 | \brief The selected text (from selection 0) or an empty string if | 3550 | \brief The selected text (from selection 0) or an empty string if |
3524 | there is no currently selected text (in selection 0). | 3551 | there is no currently selected text (in selection 0). |
3525 | 3552 | ||
3526 | The text is always returned as \c PlainText regardless of the text | 3553 | The text is always returned as \c PlainText regardless of the text |
3527 | format. In a future version of Qt an HTML subset \e may be returned | 3554 | format. In a future version of Qt an HTML subset \e may be returned |
3528 | depending on the text format. | 3555 | depending on the text format. |
3529 | 3556 | ||
3530 | \sa hasSelectedText | 3557 | \sa hasSelectedText |
3531 | */ | 3558 | */ |
3532 | 3559 | ||
@@ -3596,135 +3623,186 @@ bool QTextEdit::handleReadOnlyKeyEvent( QKeyEvent *e ) | |||
3596 | uses to resolve the locations of files and images. | 3623 | uses to resolve the locations of files and images. |
3597 | 3624 | ||
3598 | \sa text | 3625 | \sa text |
3599 | */ | 3626 | */ |
3600 | 3627 | ||
3601 | QString QTextEdit::context() const | 3628 | QString QTextEdit::context() const |
3602 | { | 3629 | { |
3603 | return doc->context(); | 3630 | return doc->context(); |
3604 | } | 3631 | } |
3605 | 3632 | ||
3606 | /*! | 3633 | /*! |
3607 | \property QTextEdit::documentTitle | 3634 | \property QTextEdit::documentTitle |
3608 | \brief the title of the document parsed from the text. | 3635 | \brief the title of the document parsed from the text. |
3609 | 3636 | ||
3610 | For \c PlainText the title will be an empty string. For \c RichText | 3637 | For \c PlainText the title will be an empty string. For \c RichText |
3611 | the title will be the text between the \c{<title>} tags, if present, | 3638 | the title will be the text between the \c{<title>} tags, if present, |
3612 | otherwise an empty string. | 3639 | otherwise an empty string. |
3613 | */ | 3640 | */ |
3614 | 3641 | ||
3615 | QString QTextEdit::documentTitle() const | 3642 | QString QTextEdit::documentTitle() const |
3616 | { | 3643 | { |
3617 | return doc->attributes()[ "title" ]; | 3644 | return doc->attributes()[ "title" ]; |
3618 | } | 3645 | } |
3619 | 3646 | ||
3620 | void QTextEdit::makeParagVisible( QTextParag *p ) | 3647 | void QTextEdit::makeParagVisible( QTextParagraph *p ) |
3621 | { | 3648 | { |
3622 | setContentsPos( contentsX(), QMIN( p->rect().y(), contentsHeight() - visibleHeight() ) ); | 3649 | setContentsPos( contentsX(), QMIN( p->rect().y(), contentsHeight() - visibleHeight() ) ); |
3623 | } | 3650 | } |
3624 | 3651 | ||
3625 | /*! Scrolls the text edit to make the text at the anchor called \a name | 3652 | /*! Scrolls the text edit to make the text at the anchor called \a name |
3626 | visible, if it can be found in the document. If the anchor isn't found | 3653 | visible, if it can be found in the document. If the anchor isn't found |
3627 | no scrolling will occur. An anchor is defined using the HTML anchor | 3654 | no scrolling will occur. An anchor is defined using the HTML anchor |
3628 | tag, e.g. \c{<a name="target">}. | 3655 | tag, e.g. \c{<a name="target">}. |
3629 | */ | 3656 | */ |
3630 | 3657 | ||
3631 | void QTextEdit::scrollToAnchor( const QString& name ) | 3658 | void QTextEdit::scrollToAnchor( const QString& name ) |
3632 | { | 3659 | { |
3660 | if ( !isVisible() ) { | ||
3661 | d->scrollToAnchor = name; | ||
3662 | return; | ||
3663 | } | ||
3633 | if ( name.isEmpty() ) | 3664 | if ( name.isEmpty() ) |
3634 | return; | 3665 | return; |
3635 | sync(); | 3666 | sync(); |
3636 | QTextCursor cursor( doc ); | 3667 | QTextCursor cursor( doc ); |
3637 | QTextParag* last = doc->lastParag(); | 3668 | QTextParagraph* last = doc->lastParagraph(); |
3638 | do { | 3669 | for (;;) { |
3639 | QTextStringChar* c = cursor.parag()->at( cursor.index() ); | 3670 | QTextStringChar* c = cursor.paragraph()->at( cursor.index() ); |
3640 | if( c->isAnchor() ) { | 3671 | if( c->isAnchor() ) { |
3641 | QString a = c->anchorName(); | 3672 | QString a = c->anchorName(); |
3642 | if ( a == name || | 3673 | if ( a == name || |
3643 | (a.contains( '#' ) && QStringList::split( '#', a ).contains( name ) ) ) { | 3674 | (a.contains( '#' ) && QStringList::split( '#', a ).contains( name ) ) ) { |
3644 | setContentsPos( contentsX(), QMIN( cursor.parag()->rect().top() + cursor.totalOffsetY(), contentsHeight() - visibleHeight() ) ); | 3675 | setContentsPos( contentsX(), QMIN( cursor.paragraph()->rect().top() + cursor.totalOffsetY(), contentsHeight() - visibleHeight() ) ); |
3645 | return; | 3676 | break; |
3646 | } | 3677 | } |
3647 | } | 3678 | } |
3679 | if ( cursor.paragraph() == last && cursor.atParagEnd() ) | ||
3680 | break; | ||
3648 | cursor.gotoNextLetter(); | 3681 | cursor.gotoNextLetter(); |
3649 | } while( cursor.parag() != last || !cursor.atParagEnd() ); | 3682 | } |
3650 | } | 3683 | } |
3651 | 3684 | ||
3652 | /*! If there is an anchor at position \a pos (in contents | 3685 | /*! If there is an anchor at position \a pos (in contents |
3653 | coordinates), its name is returned, otherwise an empty string is | 3686 | coordinates), its name is returned, otherwise an empty string is |
3654 | returned. | 3687 | returned. |
3655 | */ | 3688 | */ |
3656 | 3689 | ||
3657 | QString QTextEdit::anchorAt( const QPoint& pos ) | 3690 | QString QTextEdit::anchorAt( const QPoint& pos ) |
3658 | { | 3691 | { |
3659 | QTextCursor c( doc ); | 3692 | QTextCursor c( doc ); |
3660 | placeCursor( pos, &c ); | 3693 | placeCursor( pos, &c ); |
3661 | return c.parag()->at( c.index() )->anchorHref(); | 3694 | return c.paragraph()->at( c.index() )->anchorHref(); |
3662 | } | 3695 | } |
3663 | 3696 | ||
3664 | void QTextEdit::documentWidthChanged( int w ) | 3697 | void QTextEdit::documentWidthChanged( int w ) |
3665 | { | 3698 | { |
3666 | resizeContents( QMAX( visibleWidth(), w), contentsHeight() ); | 3699 | resizeContents( QMAX( visibleWidth(), w), contentsHeight() ); |
3667 | } | 3700 | } |
3668 | 3701 | ||
3669 | /*! | 3702 | /*! \internal |
3670 | Updates all the rendering styles used to display the text. You will | 3703 | |
3671 | probably want to call this function after calling setStyleSheet(). | 3704 | This function does nothing |
3672 | */ | 3705 | */ |
3673 | 3706 | ||
3674 | void QTextEdit::updateStyles() | 3707 | void QTextEdit::updateStyles() |
3675 | { | 3708 | { |
3676 | doc->updateStyles(); | ||
3677 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); | ||
3678 | } | 3709 | } |
3679 | 3710 | ||
3680 | void QTextEdit::setDocument( QTextDocument *dc ) | 3711 | void QTextEdit::setDocument( QTextDocument *dc ) |
3681 | { | 3712 | { |
3682 | if ( dc == doc ) | 3713 | if ( dc == doc ) |
3683 | return; | 3714 | return; |
3684 | doc = dc; | 3715 | doc = dc; |
3685 | cursor->setDocument( doc ); | 3716 | delete cursor; |
3717 | cursor = new QTextCursor( doc ); | ||
3686 | clearUndoRedo(); | 3718 | clearUndoRedo(); |
3719 | undoRedoInfo.doc = doc; | ||
3687 | lastFormatted = 0; | 3720 | lastFormatted = 0; |
3688 | } | 3721 | } |
3689 | 3722 | ||
3690 | #ifndef QT_NO_CLIPBOARD | 3723 | #ifndef QT_NO_CLIPBOARD |
3691 | 3724 | ||
3692 | /*! | 3725 | /*! |
3693 | Pastes the text with format \a subtype from the clipboard into the | 3726 | Pastes the text with format \a subtype from the clipboard into the |
3694 | text edit at the current cursor position. The \a subtype can be | 3727 | text edit at the current cursor position. The \a subtype can be |
3695 | "plain" or "html". | 3728 | "plain" or "html". |
3696 | 3729 | ||
3697 | If there is no text with format \a subtype in the clipboard nothing | 3730 | If there is no text with format \a subtype in the clipboard nothing |
3698 | happens. | 3731 | happens. |
3699 | 3732 | ||
3700 | \sa paste() cut() QTextEdit::copy() | 3733 | \sa paste() cut() QTextEdit::copy() |
3701 | */ | 3734 | */ |
3702 | void QTextEdit::pasteSubType( const QCString& subtype ) | 3735 | void QTextEdit::pasteSubType( const QCString& subtype ) |
3703 | { | 3736 | { |
3704 | QCString st = subtype; | 3737 | QCString st = subtype; |
3705 | QString t = QApplication::clipboard()->text(st); | 3738 | QString t = QApplication::clipboard()->text(st); |
3739 | if ( doc->hasSelection( QTextDocument::Standard ) ) | ||
3740 | removeSelectedText(); | ||
3706 | if ( !t.isEmpty() ) { | 3741 | if ( !t.isEmpty() ) { |
3742 | if ( t.startsWith( "<selstart/>" ) ) { | ||
3743 | t.remove( 0, 11 ); | ||
3744 | QTextCursor oldC = *cursor; | ||
3745 | lastFormatted = cursor->paragraph(); | ||
3746 | if ( lastFormatted->prev() ) | ||
3747 | lastFormatted = lastFormatted->prev(); | ||
3748 | doc->setRichTextInternal( t, cursor ); | ||
3749 | |||
3750 | if ( undoEnabled && !isReadOnly() ) { | ||
3751 | doc->setSelectionStart( QTextDocument::Temp, oldC ); | ||
3752 | doc->setSelectionEnd( QTextDocument::Temp, *cursor ); | ||
3753 | |||
3754 | checkUndoRedoInfo( UndoRedoInfo::Insert ); | ||
3755 | if ( !undoRedoInfo.valid() ) { | ||
3756 | undoRedoInfo.id = oldC.paragraph()->paragId(); | ||
3757 | undoRedoInfo.index = oldC.index(); | ||
3758 | undoRedoInfo.d->text = QString::null; | ||
3759 | } | ||
3760 | int oldLen = undoRedoInfo.d->text.length(); | ||
3761 | if ( !doc->preProcessor() ) { | ||
3762 | QString txt = doc->selectedText( QTextDocument::Temp ); | ||
3763 | undoRedoInfo.d->text += txt; | ||
3764 | for ( int i = 0; i < (int)txt.length(); ++i ) { | ||
3765 | if ( txt[ i ] != '\n' && oldC.paragraph()->at( oldC.index() )->format() ) { | ||
3766 | oldC.paragraph()->at( oldC.index() )->format()->addRef(); | ||
3767 | undoRedoInfo.d->text. | ||
3768 | setFormat( oldLen + i, oldC.paragraph()->at( oldC.index() )->format(), TRUE ); | ||
3769 | } | ||
3770 | oldC.gotoNextLetter(); | ||
3771 | } | ||
3772 | } | ||
3773 | undoRedoInfo.clear(); | ||
3774 | removeSelection( QTextDocument::Temp ); | ||
3775 | } | ||
3776 | |||
3777 | formatMore(); | ||
3778 | setModified(); | ||
3779 | emit textChanged(); | ||
3780 | repaintChanged(); | ||
3781 | ensureCursorVisible(); | ||
3782 | return; | ||
3783 | } | ||
3784 | |||
3707 | #if defined(Q_OS_WIN32) | 3785 | #if defined(Q_OS_WIN32) |
3708 | // Need to convert CRLF to LF | 3786 | // Need to convert CRLF to LF |
3709 | int index = t.find( QString::fromLatin1("\r\n"), 0 ); | 3787 | int index = t.find( QString::fromLatin1("\r\n"), 0 ); |
3710 | while ( index != -1 ) { | 3788 | while ( index != -1 ) { |
3711 | t.replace( index, 2, QChar('\n') ); | 3789 | t.replace( index, 2, QChar('\n') ); |
3712 | index = t.find( "\r\n", index ); | 3790 | index = t.find( "\r\n", index ); |
3713 | } | 3791 | } |
3714 | #elif defined(Q_OS_MAC) | 3792 | #elif defined(Q_OS_MAC) |
3715 | //need to convert CR to LF | 3793 | //need to convert CR to LF |
3716 | for( unsigned int index = 0; index < t.length(); index++ ) | 3794 | for( unsigned int index = 0; index < t.length(); index++ ) |
3717 | if(t[index] == '\r') | 3795 | if(t[index] == '\r') |
3718 | t[index] = '\n'; | 3796 | t[index] = '\n'; |
3719 | #endif | 3797 | #endif |
3720 | for ( int i=0; (uint) i<t.length(); i++ ) { | 3798 | for ( int i=0; (uint) i<t.length(); i++ ) { |
3721 | if ( t[ i ] < ' ' && t[ i ] != '\n' && t[ i ] != '\t' ) | 3799 | if ( t[ i ] < ' ' && t[ i ] != '\n' && t[ i ] != '\t' ) |
3722 | t[ i ] = ' '; | 3800 | t[ i ] = ' '; |
3723 | } | 3801 | } |
3724 | if ( !t.isEmpty() ) | 3802 | if ( !t.isEmpty() ) |
3725 | insert( t, FALSE, TRUE, TRUE ); | 3803 | insert( t, FALSE, TRUE, TRUE ); |
3726 | } | 3804 | } |
3727 | } | 3805 | } |
3728 | 3806 | ||
3729 | #ifndef QT_NO_MIMECLIPBOARD | 3807 | #ifndef QT_NO_MIMECLIPBOARD |
3730 | /*! | 3808 | /*! |
@@ -3817,49 +3895,49 @@ QCString QTextEdit::pickSpecial( QMimeSource* ms, bool always_ask, const QPoint& | |||
3817 | 3895 | ||
3818 | The default mode is \c WidgetWidth which causes words to be wrapped | 3896 | The default mode is \c WidgetWidth which causes words to be wrapped |
3819 | at the right edge of the text edit. Wrapping occurs at whitespace, | 3897 | at the right edge of the text edit. Wrapping occurs at whitespace, |
3820 | keeping whole words intact. If you want wrapping to occur within | 3898 | keeping whole words intact. If you want wrapping to occur within |
3821 | words use setWrapPolicy(). If you set a wrap mode of \c | 3899 | words use setWrapPolicy(). If you set a wrap mode of \c |
3822 | FixedPixelWidth or \c FixedColumnWidth you should also call | 3900 | FixedPixelWidth or \c FixedColumnWidth you should also call |
3823 | setWrapColumnOrWidth() with the width you want. | 3901 | setWrapColumnOrWidth() with the width you want. |
3824 | 3902 | ||
3825 | \sa WordWrap, wrapColumnOrWidth, wrapPolicy, | 3903 | \sa WordWrap, wrapColumnOrWidth, wrapPolicy, |
3826 | */ | 3904 | */ |
3827 | 3905 | ||
3828 | void QTextEdit::setWordWrap( WordWrap mode ) | 3906 | void QTextEdit::setWordWrap( WordWrap mode ) |
3829 | { | 3907 | { |
3830 | if ( wrapMode == mode ) | 3908 | if ( wrapMode == mode ) |
3831 | return; | 3909 | return; |
3832 | wrapMode = mode; | 3910 | wrapMode = mode; |
3833 | switch ( mode ) { | 3911 | switch ( mode ) { |
3834 | case NoWrap: | 3912 | case NoWrap: |
3835 | document()->formatter()->setWrapEnabled( FALSE ); | 3913 | document()->formatter()->setWrapEnabled( FALSE ); |
3836 | document()->formatter()->setWrapAtColumn( -1 ); | 3914 | document()->formatter()->setWrapAtColumn( -1 ); |
3837 | doc->setWidth( visibleWidth() ); | 3915 | doc->setWidth( visibleWidth() ); |
3838 | doc->setMinimumWidth( -1 ); | 3916 | doc->setMinimumWidth( -1 ); |
3839 | doc->invalidate(); | 3917 | doc->invalidate(); |
3840 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); | 3918 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); |
3841 | lastFormatted = doc->firstParag(); | 3919 | lastFormatted = doc->firstParagraph(); |
3842 | interval = 0; | 3920 | interval = 0; |
3843 | formatMore(); | 3921 | formatMore(); |
3844 | break; | 3922 | break; |
3845 | case WidgetWidth: | 3923 | case WidgetWidth: |
3846 | document()->formatter()->setWrapEnabled( TRUE ); | 3924 | document()->formatter()->setWrapEnabled( TRUE ); |
3847 | document()->formatter()->setWrapAtColumn( -1 ); | 3925 | document()->formatter()->setWrapAtColumn( -1 ); |
3848 | doResize(); | 3926 | doResize(); |
3849 | break; | 3927 | break; |
3850 | case FixedPixelWidth: | 3928 | case FixedPixelWidth: |
3851 | document()->formatter()->setWrapEnabled( TRUE ); | 3929 | document()->formatter()->setWrapEnabled( TRUE ); |
3852 | document()->formatter()->setWrapAtColumn( -1 ); | 3930 | document()->formatter()->setWrapAtColumn( -1 ); |
3853 | if ( wrapWidth < 0 ) | 3931 | if ( wrapWidth < 0 ) |
3854 | wrapWidth = 200; | 3932 | wrapWidth = 200; |
3855 | setWrapColumnOrWidth( wrapWidth ); | 3933 | setWrapColumnOrWidth( wrapWidth ); |
3856 | break; | 3934 | break; |
3857 | case FixedColumnWidth: | 3935 | case FixedColumnWidth: |
3858 | if ( wrapWidth < 0 ) | 3936 | if ( wrapWidth < 0 ) |
3859 | wrapWidth = 80; | 3937 | wrapWidth = 80; |
3860 | document()->formatter()->setWrapEnabled( TRUE ); | 3938 | document()->formatter()->setWrapEnabled( TRUE ); |
3861 | document()->formatter()->setWrapAtColumn( wrapWidth ); | 3939 | document()->formatter()->setWrapAtColumn( wrapWidth ); |
3862 | setWrapColumnOrWidth( wrapWidth ); | 3940 | setWrapColumnOrWidth( wrapWidth ); |
3863 | break; | 3941 | break; |
3864 | } | 3942 | } |
3865 | } | 3943 | } |
@@ -3878,49 +3956,49 @@ QTextEdit::WordWrap QTextEdit::wordWrap() const | |||
3878 | be wrapped. If the wrap mode is \c FixedColumnWidth, the value is | 3956 | be wrapped. If the wrap mode is \c FixedColumnWidth, the value is |
3879 | the column number (in character columns) from the left edge of the | 3957 | the column number (in character columns) from the left edge of the |
3880 | text edit at which text should be wrapped. | 3958 | text edit at which text should be wrapped. |
3881 | 3959 | ||
3882 | \sa wordWrap | 3960 | \sa wordWrap |
3883 | */ | 3961 | */ |
3884 | void QTextEdit::setWrapColumnOrWidth( int value ) | 3962 | void QTextEdit::setWrapColumnOrWidth( int value ) |
3885 | { | 3963 | { |
3886 | wrapWidth = value; | 3964 | wrapWidth = value; |
3887 | if ( wrapMode == FixedColumnWidth ) { | 3965 | if ( wrapMode == FixedColumnWidth ) { |
3888 | document()->formatter()->setWrapAtColumn( wrapWidth ); | 3966 | document()->formatter()->setWrapAtColumn( wrapWidth ); |
3889 | resizeContents( 0, 0 ); | 3967 | resizeContents( 0, 0 ); |
3890 | doc->setWidth( visibleWidth() ); | 3968 | doc->setWidth( visibleWidth() ); |
3891 | doc->setMinimumWidth( -1 ); | 3969 | doc->setMinimumWidth( -1 ); |
3892 | } else if (wrapMode == FixedPixelWidth ) { | 3970 | } else if (wrapMode == FixedPixelWidth ) { |
3893 | document()->formatter()->setWrapAtColumn( -1 ); | 3971 | document()->formatter()->setWrapAtColumn( -1 ); |
3894 | resizeContents( wrapWidth, 0 ); | 3972 | resizeContents( wrapWidth, 0 ); |
3895 | doc->setWidth( wrapWidth ); | 3973 | doc->setWidth( wrapWidth ); |
3896 | doc->setMinimumWidth( wrapWidth ); | 3974 | doc->setMinimumWidth( wrapWidth ); |
3897 | } else { | 3975 | } else { |
3898 | return; | 3976 | return; |
3899 | } | 3977 | } |
3900 | doc->invalidate(); | 3978 | doc->invalidate(); |
3901 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); | 3979 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); |
3902 | lastFormatted = doc->firstParag(); | 3980 | lastFormatted = doc->firstParagraph(); |
3903 | interval = 0; | 3981 | interval = 0; |
3904 | formatMore(); | 3982 | formatMore(); |
3905 | } | 3983 | } |
3906 | 3984 | ||
3907 | int QTextEdit::wrapColumnOrWidth() const | 3985 | int QTextEdit::wrapColumnOrWidth() const |
3908 | { | 3986 | { |
3909 | if ( wrapMode == WidgetWidth ) | 3987 | if ( wrapMode == WidgetWidth ) |
3910 | return visibleWidth(); | 3988 | return visibleWidth(); |
3911 | return wrapWidth; | 3989 | return wrapWidth; |
3912 | } | 3990 | } |
3913 | 3991 | ||
3914 | 3992 | ||
3915 | /*! \enum QTextEdit::WrapPolicy | 3993 | /*! \enum QTextEdit::WrapPolicy |
3916 | 3994 | ||
3917 | This enum defines where text can be wrapped in word wrap mode. | 3995 | This enum defines where text can be wrapped in word wrap mode. |
3918 | 3996 | ||
3919 | The following values are valid: | 3997 | The following values are valid: |
3920 | \value AtWhiteSpace Break lines at whitespace, e.g. spaces or | 3998 | \value AtWhiteSpace Break lines at whitespace, e.g. spaces or |
3921 | newlines. | 3999 | newlines. |
3922 | \value Anywhere Break anywhere, including within words. | 4000 | \value Anywhere Break anywhere, including within words. |
3923 | \value AtWordBoundary Don't use this deprecated value (it is a | 4001 | \value AtWordBoundary Don't use this deprecated value (it is a |
3924 | synonym for AtWhiteSpace which you should use instead). | 4002 | synonym for AtWhiteSpace which you should use instead). |
3925 | 4003 | ||
3926 | \sa setWrapPolicy() | 4004 | \sa setWrapPolicy() |
@@ -3931,194 +4009,205 @@ int QTextEdit::wrapColumnOrWidth() const | |||
3931 | \brief the word wrap policy, at whitespace or anywhere | 4009 | \brief the word wrap policy, at whitespace or anywhere |
3932 | 4010 | ||
3933 | Defines where text can be wrapped when word wrap mode is not | 4011 | Defines where text can be wrapped when word wrap mode is not |
3934 | \c NoWrap. The choices are \c AtWhiteSpace (the default) and \c | 4012 | \c NoWrap. The choices are \c AtWhiteSpace (the default) and \c |
3935 | Anywhere. | 4013 | Anywhere. |
3936 | 4014 | ||
3937 | \sa wordWrap | 4015 | \sa wordWrap |
3938 | */ | 4016 | */ |
3939 | 4017 | ||
3940 | void QTextEdit::setWrapPolicy( WrapPolicy policy ) | 4018 | void QTextEdit::setWrapPolicy( WrapPolicy policy ) |
3941 | { | 4019 | { |
3942 | if ( wPolicy == policy ) | 4020 | if ( wPolicy == policy ) |
3943 | return; | 4021 | return; |
3944 | wPolicy = policy; | 4022 | wPolicy = policy; |
3945 | QTextFormatter *formatter; | 4023 | QTextFormatter *formatter; |
3946 | if ( policy == AtWhiteSpace ) | 4024 | if ( policy == AtWhiteSpace ) |
3947 | formatter = new QTextFormatterBreakWords; | 4025 | formatter = new QTextFormatterBreakWords; |
3948 | else | 4026 | else |
3949 | formatter = new QTextFormatterBreakInWords; | 4027 | formatter = new QTextFormatterBreakInWords; |
3950 | formatter->setWrapAtColumn( document()->formatter()->wrapAtColumn() ); | 4028 | formatter->setWrapAtColumn( document()->formatter()->wrapAtColumn() ); |
3951 | formatter->setWrapEnabled( document()->formatter()->isWrapEnabled( 0 ) ); | 4029 | formatter->setWrapEnabled( document()->formatter()->isWrapEnabled( 0 ) ); |
3952 | document()->setFormatter( formatter ); | 4030 | document()->setFormatter( formatter ); |
3953 | doc->invalidate(); | 4031 | doc->invalidate(); |
3954 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); | 4032 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); |
3955 | lastFormatted = doc->firstParag(); | 4033 | lastFormatted = doc->firstParagraph(); |
3956 | interval = 0; | 4034 | interval = 0; |
3957 | formatMore(); | 4035 | formatMore(); |
3958 | } | 4036 | } |
3959 | 4037 | ||
3960 | QTextEdit::WrapPolicy QTextEdit::wrapPolicy() const | 4038 | QTextEdit::WrapPolicy QTextEdit::wrapPolicy() const |
3961 | { | 4039 | { |
3962 | return wPolicy; | 4040 | return wPolicy; |
3963 | } | 4041 | } |
3964 | 4042 | ||
3965 | /*! | 4043 | /*! |
3966 | Deletes all the text in the text edit. | 4044 | Deletes all the text in the text edit. |
3967 | 4045 | ||
3968 | \sa cut() removeSelectedText() setText() | 4046 | \sa cut() removeSelectedText() setText() |
3969 | 4047 | ||
3970 | */ | 4048 | */ |
3971 | 4049 | ||
3972 | void QTextEdit::clear() | 4050 | void QTextEdit::clear() |
3973 | { | 4051 | { |
3974 | // make clear undoable | 4052 | // make clear undoable |
3975 | doc->selectAll( QTextDocument::Temp ); | 4053 | doc->selectAll( QTextDocument::Temp ); |
3976 | removeSelectedText( QTextDocument::Temp ); | 4054 | removeSelectedText( QTextDocument::Temp ); |
3977 | 4055 | ||
3978 | setContentsPos( 0, 0 ); | 4056 | setContentsPos( 0, 0 ); |
3979 | if ( cursor->isValid() ) | 4057 | if ( cursor->isValid() ) |
3980 | cursor->restoreState(); | 4058 | cursor->restoreState(); |
3981 | doc->clear( TRUE ); | 4059 | doc->clear( TRUE ); |
3982 | cursor->setDocument( doc ); | 4060 | delete cursor; |
3983 | cursor->setParag( doc->firstParag() ); | 4061 | cursor = new QTextCursor( doc ); |
3984 | cursor->setIndex( 0 ); | ||
3985 | lastFormatted = 0; | 4062 | lastFormatted = 0; |
3986 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); | 4063 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); |
3987 | 4064 | ||
3988 | emit cursorPositionChanged( cursor ); | 4065 | emit cursorPositionChanged( cursor ); |
3989 | emit cursorPositionChanged( cursor->parag()->paragId(), cursor->index() ); | 4066 | emit cursorPositionChanged( cursor->paragraph()->paragId(), cursor->index() ); |
3990 | } | 4067 | } |
3991 | 4068 | ||
3992 | int QTextEdit::undoDepth() const | 4069 | int QTextEdit::undoDepth() const |
3993 | { | 4070 | { |
3994 | return document()->undoDepth(); | 4071 | return document()->undoDepth(); |
3995 | } | 4072 | } |
3996 | 4073 | ||
3997 | /*! | 4074 | /*! |
3998 | \property QTextEdit::length | 4075 | \property QTextEdit::length |
3999 | \brief the number of characters in the text | 4076 | \brief the number of characters in the text |
4000 | 4077 | ||
4001 | */ | 4078 | */ |
4002 | 4079 | ||
4003 | int QTextEdit::length() const | 4080 | int QTextEdit::length() const |
4004 | { | 4081 | { |
4005 | return document()->length(); | 4082 | return document()->length(); |
4006 | } | 4083 | } |
4007 | 4084 | ||
4008 | /*! | 4085 | /*! |
4009 | \property QTextEdit::tabStopWidth | 4086 | \property QTextEdit::tabStopWidth |
4010 | \brief the tab stop width in pixels | 4087 | \brief the tab stop width in pixels |
4011 | 4088 | ||
4012 | */ | 4089 | */ |
4013 | 4090 | ||
4014 | int QTextEdit::tabStopWidth() const | 4091 | int QTextEdit::tabStopWidth() const |
4015 | { | 4092 | { |
4016 | return document()->tabStopWidth(); | 4093 | return document()->tabStopWidth(); |
4017 | } | 4094 | } |
4018 | 4095 | ||
4019 | void QTextEdit::setUndoDepth( int d ) | 4096 | void QTextEdit::setUndoDepth( int d ) |
4020 | { | 4097 | { |
4021 | document()->setUndoDepth( d ); | 4098 | document()->setUndoDepth( d ); |
4022 | } | 4099 | } |
4023 | 4100 | ||
4024 | void QTextEdit::setTabStopWidth( int ts ) | 4101 | void QTextEdit::setTabStopWidth( int ts ) |
4025 | { | 4102 | { |
4026 | document()->setTabStops( ts ); | 4103 | document()->setTabStops( ts ); |
4027 | doc->invalidate(); | 4104 | doc->invalidate(); |
4028 | lastFormatted = doc->firstParag(); | 4105 | lastFormatted = doc->firstParagraph(); |
4029 | interval = 0; | 4106 | interval = 0; |
4030 | formatMore(); | 4107 | formatMore(); |
4031 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); | 4108 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); |
4032 | } | 4109 | } |
4033 | 4110 | ||
4034 | /*! \reimp */ | 4111 | /*! \reimp */ |
4035 | 4112 | ||
4036 | QSize QTextEdit::sizeHint() const | 4113 | QSize QTextEdit::sizeHint() const |
4037 | { | 4114 | { |
4038 | // ### calculate a reasonable one | 4115 | // ### calculate a reasonable one |
4039 | return QSize( 100, 100 ); | 4116 | return QSize( 100, 100 ); |
4040 | } | 4117 | } |
4041 | 4118 | ||
4042 | void QTextEdit::clearUndoRedo() | 4119 | void QTextEdit::clearUndoRedo() |
4043 | { | 4120 | { |
4044 | undoRedoInfo.clear(); | 4121 | undoRedoInfo.clear(); |
4045 | emit undoAvailable( doc->commands()->isUndoAvailable() ); | 4122 | emit undoAvailable( doc->commands()->isUndoAvailable() ); |
4046 | emit redoAvailable( doc->commands()->isRedoAvailable() ); | 4123 | emit redoAvailable( doc->commands()->isRedoAvailable() ); |
4047 | } | 4124 | } |
4048 | 4125 | ||
4049 | /*! This function gets the format of the character at position \a | 4126 | /*! \internal |
4127 | |||
4128 | \warning In Qt 3.1 we will provide a cleaer API for the | ||
4129 | functionality which is provided by this function and in Qt 4.0 this | ||
4130 | function will go away. | ||
4131 | |||
4132 | This function gets the format of the character at position \a | ||
4050 | index in paragraph \a para. Sets \a font to the character's font, \a | 4133 | index in paragraph \a para. Sets \a font to the character's font, \a |
4051 | color to the character's color and \a verticalAlignment to the | 4134 | color to the character's color and \a verticalAlignment to the |
4052 | character's vertical alignment. | 4135 | character's vertical alignment. |
4053 | 4136 | ||
4054 | Returns FALSE if \a para or \a index is out of range otherwise | 4137 | Returns FALSE if \a para or \a index is out of range otherwise |
4055 | returns TRUE. | 4138 | returns TRUE. |
4056 | */ | 4139 | */ |
4057 | 4140 | ||
4058 | bool QTextEdit::getFormat( int para, int index, QFont *font, QColor *color, VerticalAlignment *verticalAlignment ) | 4141 | bool QTextEdit::getFormat( int para, int index, QFont *font, QColor *color, VerticalAlignment *verticalAlignment ) |
4059 | { | 4142 | { |
4060 | if ( !font || !color ) | 4143 | if ( !font || !color ) |
4061 | return FALSE; | 4144 | return FALSE; |
4062 | QTextParag *p = doc->paragAt( para ); | 4145 | QTextParagraph *p = doc->paragAt( para ); |
4063 | if ( !p ) | 4146 | if ( !p ) |
4064 | return FALSE; | 4147 | return FALSE; |
4065 | if ( index < 0 || index >= p->length() ) | 4148 | if ( index < 0 || index >= p->length() ) |
4066 | return FALSE; | 4149 | return FALSE; |
4067 | *font = p->at( index )->format()->font(); | 4150 | *font = p->at( index )->format()->font(); |
4068 | *color = p->at( index )->format()->color(); | 4151 | *color = p->at( index )->format()->color(); |
4069 | *verticalAlignment = (VerticalAlignment)p->at( index )->format()->vAlign(); | 4152 | *verticalAlignment = (VerticalAlignment)p->at( index )->format()->vAlign(); |
4070 | return TRUE; | 4153 | return TRUE; |
4071 | } | 4154 | } |
4072 | 4155 | ||
4073 | /*! This function gets the format of the paragraph \a para. Sets \a | 4156 | /*! \internal |
4157 | |||
4158 | \warning In Qt 3.1 we will provide a cleaer API for the | ||
4159 | functionality which is provided by this function and in Qt 4.0 this | ||
4160 | function will go away. | ||
4161 | |||
4162 | This function gets the format of the paragraph \a para. Sets \a | ||
4074 | font to the paragraphs's font, \a color to the paragraph's color, \a | 4163 | font to the paragraphs's font, \a color to the paragraph's color, \a |
4075 | verticalAlignment to the paragraph's vertical alignment, \a | 4164 | verticalAlignment to the paragraph's vertical alignment, \a |
4076 | alignment to the paragraph's alignment, \a displayMode to the | 4165 | alignment to the paragraph's alignment, \a displayMode to the |
4077 | paragraph's display mode, \a listStyle to the paragraph's list style | 4166 | paragraph's display mode, \a listStyle to the paragraph's list style |
4078 | (if the display mode is QStyleSheetItem::DisplayListItem) and \a | 4167 | (if the display mode is QStyleSheetItem::DisplayListItem) and \a |
4079 | listDepth to the depth of the list (if the display mode is | 4168 | listDepth to the depth of the list (if the display mode is |
4080 | QStyleSheetItem::DisplayListItem). | 4169 | QStyleSheetItem::DisplayListItem). |
4081 | 4170 | ||
4082 | Returns FALSE if \a para is out of range otherwise returns TRUE. | 4171 | Returns FALSE if \a para is out of range otherwise returns TRUE. |
4083 | */ | 4172 | */ |
4084 | 4173 | ||
4085 | bool QTextEdit::getParagraphFormat( int para, QFont *font, QColor *color, | 4174 | bool QTextEdit::getParagraphFormat( int para, QFont *font, QColor *color, |
4086 | VerticalAlignment *verticalAlignment, int *alignment, | 4175 | VerticalAlignment *verticalAlignment, int *alignment, |
4087 | QStyleSheetItem::DisplayMode *displayMode, | 4176 | QStyleSheetItem::DisplayMode *displayMode, |
4088 | QStyleSheetItem::ListStyle *listStyle, | 4177 | QStyleSheetItem::ListStyle *listStyle, |
4089 | int *listDepth ) | 4178 | int *listDepth ) |
4090 | { | 4179 | { |
4091 | if ( !font || !color || !alignment || !displayMode || !listStyle ) | 4180 | if ( !font || !color || !alignment || !displayMode || !listStyle ) |
4092 | return FALSE; | 4181 | return FALSE; |
4093 | QTextParag *p = doc->paragAt( para ); | 4182 | QTextParagraph *p = doc->paragAt( para ); |
4094 | if ( !p ) | 4183 | if ( !p ) |
4095 | return FALSE; | 4184 | return FALSE; |
4096 | *font = p->paragFormat()->font(); | 4185 | *font = p->at(0)->format()->font(); |
4097 | *color = p->paragFormat()->color(); | 4186 | *color = p->at(0)->format()->color(); |
4098 | *verticalAlignment = (VerticalAlignment)p->paragFormat()->vAlign(); | 4187 | *verticalAlignment = (VerticalAlignment)p->at(0)->format()->vAlign(); |
4099 | *alignment = p->alignment(); | 4188 | *alignment = p->alignment(); |
4100 | *displayMode = p->style() ? p->style()->displayMode() : QStyleSheetItem::DisplayBlock; | 4189 | *displayMode = p->isListItem() ? QStyleSheetItem::DisplayListItem : QStyleSheetItem::DisplayBlock; |
4101 | *listStyle = p->listStyle(); | 4190 | *listStyle = p->listStyle(); |
4102 | *listDepth = p->listDepth(); | 4191 | *listDepth = p->listDepth(); |
4103 | return TRUE; | 4192 | return TRUE; |
4104 | } | 4193 | } |
4105 | 4194 | ||
4106 | 4195 | ||
4107 | 4196 | ||
4108 | /*! | 4197 | /*! |
4109 | 4198 | ||
4110 | This function is called to create a right mouse button popup menu | 4199 | This function is called to create a right mouse button popup menu |
4111 | at the document position \a pos. If you want to create a custom | 4200 | at the document position \a pos. If you want to create a custom |
4112 | popup menu, reimplement this function and return the created | 4201 | popup menu, reimplement this function and return the created |
4113 | popup menu. Ownership of the popup menu is transferred to the | 4202 | popup menu. Ownership of the popup menu is transferred to the |
4114 | caller. | 4203 | caller. |
4115 | */ | 4204 | */ |
4116 | 4205 | ||
4117 | QPopupMenu *QTextEdit::createPopupMenu( const QPoint& pos ) | 4206 | QPopupMenu *QTextEdit::createPopupMenu( const QPoint& pos ) |
4118 | { | 4207 | { |
4119 | #ifndef QT_NO_POPUPMENU | 4208 | #ifndef QT_NO_POPUPMENU |
4120 | QPopupMenu *popup = new QPopupMenu( this, "qt_edit_menu" ); | 4209 | QPopupMenu *popup = new QPopupMenu( this, "qt_edit_menu" ); |
4121 | if ( !isReadOnly() ) { | 4210 | if ( !isReadOnly() ) { |
4122 | d->id[ IdUndo ] = popup->insertItem( tr( "&Undo" ) + ACCEL_KEY( Z ) ); | 4211 | d->id[ IdUndo ] = popup->insertItem( tr( "&Undo" ) + ACCEL_KEY( Z ) ); |
4123 | d->id[ IdRedo ] = popup->insertItem( tr( "&Redo" ) + ACCEL_KEY( Y ) ); | 4212 | d->id[ IdRedo ] = popup->insertItem( tr( "&Redo" ) + ACCEL_KEY( Y ) ); |
4124 | popup->insertSeparator(); | 4213 | popup->insertSeparator(); |
@@ -4134,81 +4223,72 @@ QPopupMenu *QTextEdit::createPopupMenu( const QPoint& pos ) | |||
4134 | d->id[ IdClear ] = popup->insertItem( tr( "Clear" ) ); | 4223 | d->id[ IdClear ] = popup->insertItem( tr( "Clear" ) ); |
4135 | popup->insertSeparator(); | 4224 | popup->insertSeparator(); |
4136 | } | 4225 | } |
4137 | #if defined(Q_WS_X11) | 4226 | #if defined(Q_WS_X11) |
4138 | d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) ); | 4227 | d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) ); |
4139 | #else | 4228 | #else |
4140 | d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) + ACCEL_KEY( A ) ); | 4229 | d->id[ IdSelectAll ] = popup->insertItem( tr( "Select All" ) + ACCEL_KEY( A ) ); |
4141 | #endif | 4230 | #endif |
4142 | popup->setItemEnabled( d->id[ IdUndo ], !isReadOnly() && doc->commands()->isUndoAvailable() ); | 4231 | popup->setItemEnabled( d->id[ IdUndo ], !isReadOnly() && doc->commands()->isUndoAvailable() ); |
4143 | popup->setItemEnabled( d->id[ IdRedo ], !isReadOnly() && doc->commands()->isRedoAvailable() ); | 4232 | popup->setItemEnabled( d->id[ IdRedo ], !isReadOnly() && doc->commands()->isRedoAvailable() ); |
4144 | #ifndef QT_NO_CLIPBOARD | 4233 | #ifndef QT_NO_CLIPBOARD |
4145 | popup->setItemEnabled( d->id[ IdCut ], !isReadOnly() && doc->hasSelection( QTextDocument::Standard, TRUE ) ); | 4234 | popup->setItemEnabled( d->id[ IdCut ], !isReadOnly() && doc->hasSelection( QTextDocument::Standard, TRUE ) ); |
4146 | popup->setItemEnabled( d->id[ IdCopy ], doc->hasSelection( QTextDocument::Standard, TRUE ) ); | 4235 | popup->setItemEnabled( d->id[ IdCopy ], doc->hasSelection( QTextDocument::Standard, TRUE ) ); |
4147 | popup->setItemEnabled( d->id[ IdPaste ], !isReadOnly() && !QApplication::clipboard()->text().isEmpty() ); | 4236 | popup->setItemEnabled( d->id[ IdPaste ], !isReadOnly() && !QApplication::clipboard()->text().isEmpty() ); |
4148 | #endif | 4237 | #endif |
4149 | popup->setItemEnabled( d->id[ IdClear ], !isReadOnly() && !text().isEmpty() ); | 4238 | popup->setItemEnabled( d->id[ IdClear ], !isReadOnly() && !text().isEmpty() ); |
4150 | popup->setItemEnabled( d->id[ IdSelectAll ], (bool)text().length() ); | 4239 | popup->setItemEnabled( d->id[ IdSelectAll ], (bool)text().length() ); |
4151 | return popup; | 4240 | return popup; |
4152 | #else | 4241 | #else |
4153 | return 0; | 4242 | return 0; |
4154 | #endif | 4243 | #endif |
4155 | } | 4244 | } |
4156 | 4245 | ||
4157 | /*! \overload | 4246 | /*! \overload |
4247 | \obsolete | ||
4158 | This function is called to create a right mouse button popup menu. | 4248 | This function is called to create a right mouse button popup menu. |
4159 | If you want to create a custom popup menu, reimplement this function | 4249 | If you want to create a custom popup menu, reimplement this function |
4160 | and return the created popup menu. Ownership of the popup menu is | 4250 | and return the created popup menu. Ownership of the popup menu is |
4161 | transferred to the caller. | 4251 | transferred to the caller. |
4252 | |||
4253 | This function is only called if createPopupMenu( const QPoint & ) | ||
4254 | returns 0. | ||
4162 | */ | 4255 | */ |
4163 | 4256 | ||
4164 | QPopupMenu *QTextEdit::createPopupMenu() | 4257 | QPopupMenu *QTextEdit::createPopupMenu() |
4165 | { | 4258 | { |
4166 | return 0; | 4259 | return 0; |
4167 | } | 4260 | } |
4168 | 4261 | ||
4169 | /*! \reimp */ | 4262 | /*! \reimp */ |
4170 | 4263 | ||
4171 | void QTextEdit::setFont( const QFont &f ) | 4264 | void QTextEdit::setFont( const QFont &f ) |
4172 | { | 4265 | { |
4173 | QFont old( QScrollView::font() ); | 4266 | QFont old( QScrollView::font() ); |
4174 | QScrollView::setFont( f ); | 4267 | QScrollView::setFont( f ); |
4175 | doc->setMinimumWidth( -1 ); | 4268 | doc->setMinimumWidth( -1 ); |
4176 | 4269 | doc->setDefaultFormat( f, doc->formatCollection()->defaultFormat()->color() ); | |
4177 | // ### that is a bit hacky | 4270 | lastFormatted = doc->firstParagraph(); |
4178 | static short diff = 1; | ||
4179 | diff *= -1; | ||
4180 | doc->setWidth( visibleWidth() + diff ); | ||
4181 | |||
4182 | int s = f.pointSize(); | ||
4183 | bool usePixels = FALSE; | ||
4184 | if ( s == -1 ) { | ||
4185 | s = f.pixelSize(); | ||
4186 | usePixels = TRUE; | ||
4187 | } | ||
4188 | doc->updateFontSizes( s, usePixels ); | ||
4189 | doc->updateFontAttributes( f, old ); | ||
4190 | lastFormatted = doc->firstParag(); | ||
4191 | formatMore(); | 4271 | formatMore(); |
4192 | repaintChanged(); | 4272 | repaintChanged(); |
4193 | } | 4273 | } |
4194 | 4274 | ||
4195 | /*! \fn QTextEdit::zoomIn() | 4275 | /*! \fn QTextEdit::zoomIn() |
4196 | 4276 | ||
4197 | \overload | 4277 | \overload |
4198 | 4278 | ||
4199 | Zooms in on the text by by making the base font size one | 4279 | Zooms in on the text by by making the base font size one |
4200 | point larger and recalculating all font sizes. This does not change | 4280 | point larger and recalculating all font sizes. This does not change |
4201 | the size of any images. | 4281 | the size of any images. |
4202 | 4282 | ||
4203 | \sa zoomOut() | 4283 | \sa zoomOut() |
4204 | 4284 | ||
4205 | */ | 4285 | */ |
4206 | 4286 | ||
4207 | /*! \fn QTextEdit::zoomOut() | 4287 | /*! \fn QTextEdit::zoomOut() |
4208 | 4288 | ||
4209 | \overload | 4289 | \overload |
4210 | 4290 | ||
4211 | Zooms out on the text by by making the base font size one | 4291 | Zooms out on the text by by making the base font size one |
4212 | point smaller and recalculating all font sizes. This does not change | 4292 | point smaller and recalculating all font sizes. This does not change |
4213 | the size of any images. | 4293 | the size of any images. |
4214 | 4294 | ||
@@ -4252,52 +4332,51 @@ void QTextEdit::zoomOut( int range ) | |||
4252 | 4332 | ||
4253 | void QTextEdit::zoomTo( int size ) | 4333 | void QTextEdit::zoomTo( int size ) |
4254 | { | 4334 | { |
4255 | QFont f( QScrollView::font() ); | 4335 | QFont f( QScrollView::font() ); |
4256 | f.setPointSize( size ); | 4336 | f.setPointSize( size ); |
4257 | setFont( f ); | 4337 | setFont( f ); |
4258 | } | 4338 | } |
4259 | 4339 | ||
4260 | /*! | 4340 | /*! |
4261 | \internal | 4341 | \internal |
4262 | 4342 | ||
4263 | QTextEdit is optimized for large amounts text. One of its | 4343 | QTextEdit is optimized for large amounts text. One of its |
4264 | optimizations is to format only the visible text, formatting the rest | 4344 | optimizations is to format only the visible text, formatting the rest |
4265 | on demand, e.g. as the user scrolls, so you don't usually need to | 4345 | on demand, e.g. as the user scrolls, so you don't usually need to |
4266 | call this function. | 4346 | call this function. |
4267 | 4347 | ||
4268 | In some situations you may want to force the whole text | 4348 | In some situations you may want to force the whole text |
4269 | to be formatted. For example, if after calling setText(), you wanted | 4349 | to be formatted. For example, if after calling setText(), you wanted |
4270 | to know the height of the document (using contentsHeight()), you | 4350 | to know the height of the document (using contentsHeight()), you |
4271 | would call this function first. | 4351 | would call this function first. |
4272 | */ | 4352 | */ |
4273 | 4353 | ||
4274 | void QTextEdit::sync() | 4354 | void QTextEdit::sync() |
4275 | { | 4355 | { |
4276 | QTextParag *p = lastFormatted; | 4356 | while ( lastFormatted ) { |
4277 | while ( p ) { | 4357 | lastFormatted->format(); |
4278 | p->format(); | 4358 | lastFormatted = lastFormatted->next(); |
4279 | p = p->next(); | ||
4280 | } | 4359 | } |
4281 | resizeContents( contentsWidth(), doc->height() ); | 4360 | resizeContents( contentsWidth(), doc->height() ); |
4282 | } | 4361 | } |
4283 | 4362 | ||
4284 | /*! \reimp */ | 4363 | /*! \reimp */ |
4285 | 4364 | ||
4286 | void QTextEdit::setEnabled( bool b ) | 4365 | void QTextEdit::setEnabled( bool b ) |
4287 | { | 4366 | { |
4288 | QScrollView::setEnabled( b ); | 4367 | QScrollView::setEnabled( b ); |
4289 | if ( !b ) { | 4368 | if ( !b ) { |
4290 | blinkTimer->stop(); | 4369 | blinkTimer->stop(); |
4291 | drawCursor( FALSE ); | 4370 | drawCursor( FALSE ); |
4292 | } | 4371 | } |
4293 | if ( textFormat() == PlainText ) { | 4372 | if ( textFormat() == PlainText ) { |
4294 | QTextFormat *f = doc->formatCollection()->defaultFormat(); | 4373 | QTextFormat *f = doc->formatCollection()->defaultFormat(); |
4295 | f->setColor( colorGroup().text() ); | 4374 | f->setColor( colorGroup().text() ); |
4296 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); | 4375 | updateContents( contentsX(), contentsY(), visibleWidth(), visibleHeight() ); |
4297 | } | 4376 | } |
4298 | if ( b ) { | 4377 | if ( b ) { |
4299 | blinkTimer->start( QApplication::cursorFlashTime() / 2 ); | 4378 | blinkTimer->start( QApplication::cursorFlashTime() / 2 ); |
4300 | drawCursor( TRUE ); | 4379 | drawCursor( TRUE ); |
4301 | } | 4380 | } |
4302 | } | 4381 | } |
4303 | 4382 | ||
@@ -4339,178 +4418,178 @@ void QTextEdit::setReadOnly( bool b ) | |||
4339 | if ( readonly ) | 4418 | if ( readonly ) |
4340 | viewport()->setCursor( arrowCursor ); | 4419 | viewport()->setCursor( arrowCursor ); |
4341 | else | 4420 | else |
4342 | viewport()->setCursor( ibeamCursor ); | 4421 | viewport()->setCursor( ibeamCursor ); |
4343 | #endif | 4422 | #endif |
4344 | } | 4423 | } |
4345 | 4424 | ||
4346 | /*! Scrolls to the bottom of the document and does formatting if | 4425 | /*! Scrolls to the bottom of the document and does formatting if |
4347 | required */ | 4426 | required */ |
4348 | 4427 | ||
4349 | void QTextEdit::scrollToBottom() | 4428 | void QTextEdit::scrollToBottom() |
4350 | { | 4429 | { |
4351 | sync(); | 4430 | sync(); |
4352 | setContentsPos( contentsX(), contentsHeight() - visibleHeight() ); | 4431 | setContentsPos( contentsX(), contentsHeight() - visibleHeight() ); |
4353 | } | 4432 | } |
4354 | 4433 | ||
4355 | /*! Returns the rectangle of the paragraph \a para in contents | 4434 | /*! Returns the rectangle of the paragraph \a para in contents |
4356 | coordinates, or an invalid rectangle if \a para is out of range. | 4435 | coordinates, or an invalid rectangle if \a para is out of range. |
4357 | */ | 4436 | */ |
4358 | 4437 | ||
4359 | QRect QTextEdit::paragraphRect( int para ) const | 4438 | QRect QTextEdit::paragraphRect( int para ) const |
4360 | { | 4439 | { |
4361 | QTextEdit *that = (QTextEdit *)this; | 4440 | QTextEdit *that = (QTextEdit *)this; |
4362 | that->sync(); | 4441 | that->sync(); |
4363 | QTextParag *p = doc->paragAt( para ); | 4442 | QTextParagraph *p = doc->paragAt( para ); |
4364 | if ( !p ) | 4443 | if ( !p ) |
4365 | return QRect( -1, -1, -1, -1 ); | 4444 | return QRect( -1, -1, -1, -1 ); |
4366 | return p->rect(); | 4445 | return p->rect(); |
4367 | } | 4446 | } |
4368 | 4447 | ||
4369 | /*! | 4448 | /*! |
4370 | Returns the paragraph which is at position \a pos (in contents | 4449 | Returns the paragraph which is at position \a pos (in contents |
4371 | coordinates), or -1 if there is no paragraph with index \a pos. | 4450 | coordinates), or -1 if there is no paragraph with index \a pos. |
4372 | */ | 4451 | */ |
4373 | 4452 | ||
4374 | int QTextEdit::paragraphAt( const QPoint &pos ) const | 4453 | int QTextEdit::paragraphAt( const QPoint &pos ) const |
4375 | { | 4454 | { |
4376 | QTextCursor c( doc ); | 4455 | QTextCursor c( doc ); |
4377 | c.place( pos, doc->firstParag() ); | 4456 | c.place( pos, doc->firstParagraph() ); |
4378 | if ( c.parag() ) | 4457 | if ( c.paragraph() ) |
4379 | return c.parag()->paragId(); | 4458 | return c.paragraph()->paragId(); |
4380 | return -1; | 4459 | return -1; |
4381 | } | 4460 | } |
4382 | 4461 | ||
4383 | /*! | 4462 | /*! |
4384 | Returns the index of the character (relative to its paragraph) at | 4463 | Returns the index of the character (relative to its paragraph) at |
4385 | position \a pos (in contents coordinates). If \a para is not null, | 4464 | position \a pos (in contents coordinates). If \a para is not null, |
4386 | \e *\a para is set to this paragraph. If there is no character at | 4465 | \e *\a para is set to this paragraph. If there is no character at |
4387 | \a pos, -1 is returned. | 4466 | \a pos, -1 is returned. |
4388 | */ | 4467 | */ |
4389 | 4468 | ||
4390 | int QTextEdit::charAt( const QPoint &pos, int *para ) const | 4469 | int QTextEdit::charAt( const QPoint &pos, int *para ) const |
4391 | { | 4470 | { |
4392 | QTextCursor c( doc ); | 4471 | QTextCursor c( doc ); |
4393 | c.place( pos, doc->firstParag() ); | 4472 | c.place( pos, doc->firstParagraph() ); |
4394 | if ( c.parag() ) { | 4473 | if ( c.paragraph() ) { |
4395 | if ( para ) | 4474 | if ( para ) |
4396 | *para = c.parag()->paragId(); | 4475 | *para = c.paragraph()->paragId(); |
4397 | return c.index(); | 4476 | return c.index(); |
4398 | } | 4477 | } |
4399 | return -1; | 4478 | return -1; |
4400 | } | 4479 | } |
4401 | 4480 | ||
4402 | /*! Sets the background color of the paragraph \a para to \a bg */ | 4481 | /*! Sets the background color of the paragraph \a para to \a bg */ |
4403 | 4482 | ||
4404 | void QTextEdit::setParagraphBackgroundColor( int para, const QColor &bg ) | 4483 | void QTextEdit::setParagraphBackgroundColor( int para, const QColor &bg ) |
4405 | { | 4484 | { |
4406 | QTextParag *p = doc->paragAt( para ); | 4485 | QTextParagraph *p = doc->paragAt( para ); |
4407 | if ( !p ) | 4486 | if ( !p ) |
4408 | return; | 4487 | return; |
4409 | p->setBackgroundColor( bg ); | 4488 | p->setBackgroundColor( bg ); |
4410 | repaintChanged(); | 4489 | repaintChanged(); |
4411 | } | 4490 | } |
4412 | 4491 | ||
4413 | /*! Clears the background color of the paragraph \a para, so that the | 4492 | /*! Clears the background color of the paragraph \a para, so that the |
4414 | default color is used again. | 4493 | default color is used again. |
4415 | */ | 4494 | */ |
4416 | 4495 | ||
4417 | void QTextEdit::clearParagraphBackground( int para ) | 4496 | void QTextEdit::clearParagraphBackground( int para ) |
4418 | { | 4497 | { |
4419 | QTextParag *p = doc->paragAt( para ); | 4498 | QTextParagraph *p = doc->paragAt( para ); |
4420 | if ( !p ) | 4499 | if ( !p ) |
4421 | return; | 4500 | return; |
4422 | p->clearBackgroundColor(); | 4501 | p->clearBackgroundColor(); |
4423 | repaintChanged(); | 4502 | repaintChanged(); |
4424 | } | 4503 | } |
4425 | 4504 | ||
4426 | /*! Returns the background color of the paragraph \a para or an | 4505 | /*! Returns the background color of the paragraph \a para or an |
4427 | invalid color if \a para is out of range or the paragraph has no | 4506 | invalid color if \a para is out of range or the paragraph has no |
4428 | background set | 4507 | background set |
4429 | */ | 4508 | */ |
4430 | 4509 | ||
4431 | QColor QTextEdit::paragraphBackgroundColor( int para ) const | 4510 | QColor QTextEdit::paragraphBackgroundColor( int para ) const |
4432 | { | 4511 | { |
4433 | QTextParag *p = doc->paragAt( para ); | 4512 | QTextParagraph *p = doc->paragAt( para ); |
4434 | if ( !p ) | 4513 | if ( !p ) |
4435 | return QColor(); | 4514 | return QColor(); |
4436 | QColor *c = p->backgroundColor(); | 4515 | QColor *c = p->backgroundColor(); |
4437 | if ( c ) | 4516 | if ( c ) |
4438 | return *c; | 4517 | return *c; |
4439 | return QColor(); | 4518 | return QColor(); |
4440 | } | 4519 | } |
4441 | 4520 | ||
4442 | /*! \property QTextEdit::undoRedoEnabled | 4521 | /*! \property QTextEdit::undoRedoEnabled |
4443 | \brief whether undo/redo is enabled | 4522 | \brief whether undo/redo is enabled |
4444 | 4523 | ||
4445 | The default is TRUE. | 4524 | The default is TRUE. |
4446 | */ | 4525 | */ |
4447 | 4526 | ||
4448 | void QTextEdit::setUndoRedoEnabled( bool b ) | 4527 | void QTextEdit::setUndoRedoEnabled( bool b ) |
4449 | { | 4528 | { |
4450 | undoEnabled = b; | 4529 | undoEnabled = b; |
4451 | } | 4530 | } |
4452 | 4531 | ||
4453 | bool QTextEdit::isUndoRedoEnabled() const | 4532 | bool QTextEdit::isUndoRedoEnabled() const |
4454 | { | 4533 | { |
4455 | return undoEnabled; | 4534 | return undoEnabled; |
4456 | } | 4535 | } |
4457 | 4536 | ||
4458 | /*! Returns whether undo is available */ | 4537 | /*! Returns whether undo is available */ |
4459 | 4538 | ||
4460 | bool QTextEdit::isUndoAvailable() const | 4539 | bool QTextEdit::isUndoAvailable() const |
4461 | { | 4540 | { |
4462 | return doc->commands()->isUndoAvailable() || undoRedoInfo.valid(); | 4541 | return doc->commands()->isUndoAvailable() || undoRedoInfo.valid(); |
4463 | } | 4542 | } |
4464 | 4543 | ||
4465 | /*! Returns whether redo is available */ | 4544 | /*! Returns whether redo is available */ |
4466 | 4545 | ||
4467 | bool QTextEdit::isRedoAvailable() const | 4546 | bool QTextEdit::isRedoAvailable() const |
4468 | { | 4547 | { |
4469 | return doc->commands()->isRedoAvailable(); | 4548 | return doc->commands()->isRedoAvailable(); |
4470 | } | 4549 | } |
4471 | 4550 | ||
4472 | void QTextEdit::ensureFormatted( QTextParag *p ) | 4551 | void QTextEdit::ensureFormatted( QTextParagraph *p ) |
4473 | { | 4552 | { |
4474 | while ( !p->isValid() ) { | 4553 | while ( !p->isValid() ) { |
4475 | if ( !lastFormatted ) | 4554 | if ( !lastFormatted ) |
4476 | return; | 4555 | return; |
4477 | formatMore(); | 4556 | formatMore(); |
4478 | } | 4557 | } |
4479 | } | 4558 | } |
4480 | 4559 | ||
4481 | /*! \internal */ | 4560 | /*! \internal */ |
4482 | void QTextEdit::updateCursor( const QPoint & pos ) | 4561 | void QTextEdit::updateCursor( const QPoint & pos ) |
4483 | { | 4562 | { |
4484 | if ( isReadOnly() && linksEnabled() ) { | 4563 | if ( isReadOnly() && linksEnabled() ) { |
4485 | QTextCursor c = *cursor; | 4564 | QTextCursor c = *cursor; |
4486 | placeCursor( pos, &c, TRUE ); | 4565 | placeCursor( pos, &c, TRUE ); |
4487 | 4566 | ||
4488 | #ifndef QT_NO_NETWORKPROTOCOL | 4567 | #ifndef QT_NO_NETWORKPROTOCOL |
4489 | if ( c.parag() && c.parag()->at( c.index() ) && | 4568 | if ( c.paragraph() && c.paragraph()->at( c.index() ) && |
4490 | c.parag()->at( c.index() )->isAnchor() && | 4569 | c.paragraph()->at( c.index() )->isAnchor() && |
4491 | !c.parag()->at( c.index() )->anchorHref().isEmpty() ) { | 4570 | !c.paragraph()->at( c.index() )->anchorHref().isEmpty() ) { |
4492 | if ( c.index() < c.parag()->length() - 1 ) | 4571 | if ( c.index() < c.paragraph()->length() - 1 ) |
4493 | onLink = c.parag()->at( c.index() )->anchorHref(); | 4572 | onLink = c.paragraph()->at( c.index() )->anchorHref(); |
4494 | else | 4573 | else |
4495 | onLink = QString::null; | 4574 | onLink = QString::null; |
4496 | 4575 | ||
4497 | #ifndef QT_NO_CURSOR | 4576 | #ifndef QT_NO_CURSOR |
4498 | viewport()->setCursor( onLink.isEmpty() ? arrowCursor : pointingHandCursor ); | 4577 | viewport()->setCursor( onLink.isEmpty() ? arrowCursor : pointingHandCursor ); |
4499 | #endif | 4578 | #endif |
4500 | QUrl u( doc->context(), onLink, TRUE ); | 4579 | QUrl u( doc->context(), onLink, TRUE ); |
4501 | emitHighlighted( u.toString( FALSE, FALSE ) ); | 4580 | emitHighlighted( u.toString( FALSE, FALSE ) ); |
4502 | } else { | 4581 | } else { |
4503 | #ifndef QT_NO_CURSOR | 4582 | #ifndef QT_NO_CURSOR |
4504 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); | 4583 | viewport()->setCursor( isReadOnly() ? arrowCursor : ibeamCursor ); |
4505 | #endif | 4584 | #endif |
4506 | onLink = QString::null; | 4585 | onLink = QString::null; |
4507 | emitHighlighted( QString::null ); | 4586 | emitHighlighted( QString::null ); |
4508 | } | 4587 | } |
4509 | #endif | 4588 | #endif |
4510 | } | 4589 | } |
4511 | } | 4590 | } |
4512 | 4591 | ||
4513 | void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c ) | 4592 | void QTextEdit::placeCursor( const QPoint &pos, QTextCursor *c ) |
4514 | { | 4593 | { |
4515 | placeCursor( pos, c, FALSE ); | 4594 | placeCursor( pos, c, FALSE ); |
4516 | } | 4595 | } |