1 | /* |
2 | Copyright (c) 2009 Thomas McGuire <mcguire@kde.org> |
3 | |
4 | Based on KMail and libkdepim code by: |
5 | Copyright 2007 - 2010 Laurent Montel <montel@kde.org> |
6 | |
7 | This library is free software; you can redistribute it and/or modify it |
8 | under the terms of the GNU Library General Public License as published by |
9 | the Free Software Foundation; either version 2 of the License, or (at your |
10 | option) any later version. |
11 | |
12 | This library is distributed in the hope that it will be useful, but WITHOUT |
13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public |
15 | License for more details. |
16 | |
17 | You should have received a copy of the GNU Library General Public License |
18 | along with this library; see the file COPYING.LIB. If not, write to the |
19 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
20 | 02110-1301, USA. |
21 | */ |
22 | #ifndef KPIMTEXTEDIT_TEXTEDIT_H |
23 | #define KPIMTEXTEDIT_TEXTEDIT_H |
24 | |
25 | #include "kpimtextedit_export.h" |
26 | |
27 | #include <kpimidentities/signature.h> // TODO KF5: remove this |
28 | |
29 | #include <KDE/KRichTextWidget> |
30 | #include <KActionCollection> |
31 | |
32 | #include <QtCore/QSharedPointer> |
33 | |
34 | #include <memory> |
35 | // TODO KF5: remove this |
36 | #define FIX_KMAIL_INSERT_IMAGE 1 |
37 | |
38 | class KUrl; |
39 | class QFileInfo; |
40 | |
41 | namespace KPIMTextEdit { |
42 | |
43 | class TextEditPrivate; |
44 | class EMailQuoteHighlighter; |
45 | |
46 | /** |
47 | * Holds information about an embedded HTML image that will be useful for mail clients. |
48 | * A list with all images can be retrieved with TextEdit::embeddedImages(). |
49 | */ |
50 | struct EmbeddedImage |
51 | { |
52 | QByteArray image; ///< The image, encoded as PNG with base64 encoding |
53 | QString contentID; ///< The content id of the embedded image |
54 | QString imageName; ///< Name of the image as it is available as a resource in the editor |
55 | }; |
56 | |
57 | /** |
58 | * Holds information about an embedded HTML image that will be generally useful. |
59 | * A list with all images can be retrieved with TextEdit::imagesWithName(). |
60 | * |
61 | * @since 4.4 |
62 | */ |
63 | struct ImageWithName |
64 | { |
65 | QImage image; ///< The image |
66 | QString name; ///< The name of the image as it is available as a resource in the editor |
67 | }; |
68 | |
69 | typedef QSharedPointer<ImageWithName> ImageWithNamePtr; |
70 | typedef QList< ImageWithNamePtr > ImageWithNameList; |
71 | typedef QList< QSharedPointer<EmbeddedImage> > ImageList; |
72 | |
73 | /** |
74 | * Special textedit that provides additional features which are useful for PIM applications |
75 | * like mail clients. |
76 | * Additional features this class provides: |
77 | * - Highlighting quoted text |
78 | * - Handling of inline images |
79 | * - Auto-Hiding the cursor |
80 | * - Handling of pastes and drops of images |
81 | * |
82 | * @since 4.3 |
83 | */ |
84 | class KPIMTEXTEDIT_EXPORT TextEdit : public KRichTextWidget, |
85 | // TODO: KDE5: get rid of the spell interface |
86 | protected KTextEditSpellInterface |
87 | { |
88 | Q_OBJECT |
89 | |
90 | public: |
91 | |
92 | /** |
93 | * Constructs a TextEdit object |
94 | * @param text the initial plain text of the text edit, interpreted as HTML |
95 | * @param parent the parent widget |
96 | */ |
97 | explicit TextEdit( const QString &text, QWidget *parent = 0 ); |
98 | |
99 | /** |
100 | * Constructs a TextEdit object. |
101 | * @param parent the parent widget |
102 | */ |
103 | explicit TextEdit( QWidget *parent = 0 ); |
104 | |
105 | /** |
106 | * Constructs a TextEdit object |
107 | * @param parent the parent widget |
108 | * @param configFile the config file |
109 | * @since 4.6 |
110 | * |
111 | * TODO KDE-5 merge with other constructor |
112 | */ |
113 | explicit TextEdit( QWidget *parent, const QString &configFile ); |
114 | |
115 | /** |
116 | * Calling this allows createActions() to create the add image actions. |
117 | * Call this method before calling createActions(), otherwise the action |
118 | * will not be added. |
119 | * Also, if image actions is enabled, the user can paste PNG images. |
120 | * |
121 | * Don't call this if you don't want to support adding images. |
122 | */ |
123 | void enableImageActions(); |
124 | /** |
125 | * Calling this allows createActions() to create the add emoticons actions. |
126 | * Call this method before calling createActions(), otherwise the action |
127 | * will not be added. |
128 | * Don't call this if you don't want to support emoticons actions. |
129 | */ |
130 | void enableEmoticonActions(); |
131 | |
132 | void enableInsertHtmlActions(); |
133 | |
134 | void enableInsertTableActions(); |
135 | /** |
136 | * Destructor |
137 | */ |
138 | ~TextEdit(); |
139 | |
140 | /** |
141 | * Reimplemented from KMEditor, to support more actions. |
142 | * |
143 | * @param actionCollection the collection to put the new actions into |
144 | * The additional action XML names are: |
145 | * - add_image |
146 | * - delete_line |
147 | * |
148 | * The add_image actions is only added if enableImageActions() is called before. |
149 | */ |
150 | virtual void createActions( KActionCollection *actionCollection ); |
151 | |
152 | /** |
153 | * Adds an image. The image is loaded from file and then pasted to the current |
154 | * cursor position. |
155 | * |
156 | * @param url The URL of the file which contains the image |
157 | */ |
158 | void addImage( const KUrl &url ); |
159 | |
160 | /** |
161 | * Adds an image. The image is loaded from file and then pasted to the current |
162 | * cursor position with the given @p width and @p height. |
163 | * |
164 | * @param url The URL of the file which contains the image |
165 | * @param width The width the inserted image will have. |
166 | * @param height The height the inserted image will have. |
167 | * |
168 | * @since 4.10 |
169 | */ |
170 | void addImage( const KUrl &url, int width, int height ); |
171 | |
172 | /** |
173 | * Loads an image into the textedit. The difference to addImage() is that this |
174 | * function expects that the image tag is already present in the HTML source. |
175 | * |
176 | * @param image the image to load |
177 | * @param matchName the name of tags to match image |
178 | * @param resourceName the resource name of image |
179 | * So what this message does is that it scans the HTML source for the image |
180 | * tag that matches the @p matchName, and then inserts the @p image as a |
181 | * resource, giving that resource the name @p resourceName. |
182 | * |
183 | * @since 4.4 |
184 | */ |
185 | void loadImage( const QImage &image, const QString &matchName, const QString &resourceName ); |
186 | |
187 | /** |
188 | * Deletes the line at the current cursor position. |
189 | * @since 4.4 |
190 | */ |
191 | void deleteCurrentLine(); |
192 | |
193 | /** |
194 | * Get a list with all embedded HTML images. |
195 | * If the same image is contained twice or more in the editor, it will have only |
196 | * one entry in this list. |
197 | * |
198 | * @return a list of embedded HTML images of the editor. |
199 | */ |
200 | ImageList embeddedImages() const; |
201 | |
202 | /** |
203 | * Same as embeddedImages(), only that this returns a list of general purpose information, |
204 | * whereas the embeddedImages() function returns a list with mail-specific information. |
205 | * |
206 | * @since 4.4 |
207 | */ |
208 | ImageWithNameList imagesWithName() const; |
209 | |
210 | /** |
211 | * Returns the text of the editor as plain text, with linebreaks inserted |
212 | * where word-wrapping occurred. |
213 | */ |
214 | QString toWrappedPlainText() const; |
215 | |
216 | /** |
217 | * @since 5.0 |
218 | */ |
219 | QString toWrappedPlainText( QTextDocument *document ) const; |
220 | |
221 | /** |
222 | * @since 4.10 |
223 | */ |
224 | //TODO 5.0 merge it |
225 | QString toCleanPlainText( const QString &plainText ) const; |
226 | |
227 | /** |
228 | * Same as toPlainText() from QTextEdit, only that it removes embedded |
229 | * images and converts non-breaking space characters to normal spaces. |
230 | */ |
231 | QString toCleanPlainText() const; |
232 | |
233 | /** |
234 | * This method is called after the highlighter is created. |
235 | * If you use custom colors for highlighting, override this method and |
236 | * set the colors to the highlighter in it. |
237 | * |
238 | * The default implementation does nothing, therefore the default colors of |
239 | * the EMailQuoteHighlighter class will be used. |
240 | * |
241 | * @param highlighter the highlighter that was just created. You need to |
242 | * set the colors of this highlighter. |
243 | */ |
244 | virtual void setHighlighterColors( EMailQuoteHighlighter *highlighter ); |
245 | |
246 | /** |
247 | * Convenience method for qouteLength( line ) > 0 |
248 | */ |
249 | bool isLineQuoted( const QString &line ) const; |
250 | |
251 | /** |
252 | * This is called whenever the editor needs to find out the length of the quote, |
253 | * i.e. the length of the quote prefix before the real text starts. |
254 | * The default implementation counts the number of spaces, '>' and '|' chars in |
255 | * front of the line. |
256 | * |
257 | * @param line the line of which the length of the quote prefix should be returned |
258 | * @return 0 if the line is not quoted, the length of the quote prefix otherwise |
259 | * FIXME: Not yet used in all places, e.g. keypressEvent() or the quote highlighter |
260 | */ |
261 | virtual int quoteLength( const QString &line ) const; |
262 | |
263 | /** |
264 | * Returns the prefix that is added to a line that is quoted. |
265 | * By default, this is "> ". |
266 | */ |
267 | virtual const QString defaultQuoteSign() const; |
268 | |
269 | /** |
270 | * For all given embedded images, this function replace the image name |
271 | * in the <img> tag of the HTML body with cid:content-id, so that the |
272 | * HTML references the image body parts, see RFC 2557. |
273 | * |
274 | * This is useful when building a MIME message with inline images. |
275 | * |
276 | * Note that this function works on encoded content already. |
277 | * |
278 | * @param htmlBody the HTML code in which the <img> tag will be modified. |
279 | * The HTML code here could come from toHtml(), for example. |
280 | * |
281 | * @param imageList the list of images of which the <img> tag will be modified. |
282 | * You can get such a list from the embeddedImages() function. |
283 | * |
284 | * @return a modified HTML code, where the <img> tags got replaced |
285 | */ |
286 | static QByteArray imageNamesToContentIds( const QByteArray &htmlBody, |
287 | const ImageList &imageList ); |
288 | |
289 | /** |
290 | * Checks if rich text formatting is used anywhere. |
291 | * This is not the same as checking whether textMode() returns "Rich", |
292 | * since that only tells that rich text mode is enabled, but not if any |
293 | * special formatting is actually used. |
294 | * |
295 | * @return true if formatting is used anywhere |
296 | */ |
297 | bool isFormattingUsed() const; |
298 | |
299 | /** |
300 | * Return config file. |
301 | * @since 4.5 |
302 | */ |
303 | QString configFile() const; |
304 | |
305 | /** Return true if richtext mode support image |
306 | * @since 4.6 |
307 | */ |
308 | bool isEnableImageActions() const; |
309 | |
310 | /** Return true if emoticons actions supported |
311 | * @since 4.9 |
312 | */ |
313 | bool isEnableEmoticonActions() const; |
314 | |
315 | /** |
316 | * @param image the image to insert |
317 | * @param info the info to supply with image |
318 | * @since 4.6 |
319 | */ |
320 | void insertImage( const QImage &image, const QFileInfo &info ); |
321 | |
322 | /** |
323 | * @since 4.10 |
324 | */ |
325 | bool isEnableInsertHtmlActions() const; |
326 | |
327 | /** |
328 | * @since 4.10 |
329 | */ |
330 | bool isEnableInsertTableActions() const; |
331 | |
332 | protected: |
333 | |
334 | /** |
335 | * Reimplemented for inline image support |
336 | */ |
337 | virtual bool canInsertFromMimeData( const QMimeData *source ) const; |
338 | |
339 | /** |
340 | * Reimplemented for inline image support |
341 | */ |
342 | virtual void insertFromMimeData( const QMimeData *source ); |
343 | |
344 | /** |
345 | * Reimplemented from KRichTextWidget to hide the mouse cursor when there |
346 | * was no mouse movement for some time, using KCursor |
347 | */ |
348 | virtual bool eventFilter( QObject *o, QEvent *e ); |
349 | |
350 | /** |
351 | * Reimplemented to add qoute signs when the user presses enter |
352 | * on a quoted line. |
353 | */ |
354 | virtual void keyPressEvent ( QKeyEvent *e ); |
355 | |
356 | // For the explaination for these four methods, see the comment at the |
357 | // spellCheckingEnabled variable of the private class. |
358 | |
359 | /** |
360 | * Reimplemented from KTextEditSpellInterface |
361 | */ |
362 | virtual bool isSpellCheckingEnabled() const; |
363 | |
364 | /** |
365 | * Reimplemented from KTextEditSpellInterface |
366 | */ |
367 | virtual void setSpellCheckingEnabled( bool enable ); |
368 | |
369 | /** |
370 | * Reimplemented from KTextEditSpellInterface, to avoid spellchecking |
371 | * quoted text. |
372 | */ |
373 | virtual bool shouldBlockBeSpellChecked( const QString &block ) const; |
374 | |
375 | /** |
376 | * Reimplemented to create our own highlighter which does quote and |
377 | * spellcheck highlighting |
378 | */ |
379 | virtual void createHighlighter(); |
380 | |
381 | private: |
382 | void addImageHelper( const KUrl &url, int width = -1, int height = -1 ); |
383 | std::auto_ptr<TextEditPrivate> const d; |
384 | friend class TextEditPrivate; |
385 | Q_PRIVATE_SLOT( d, void _k_slotAddImage() ) |
386 | Q_PRIVATE_SLOT( d, void _k_slotDeleteLine() ) |
387 | Q_PRIVATE_SLOT( d, void _k_slotAddEmoticon( const QString & ) ) |
388 | Q_PRIVATE_SLOT( d, void _k_slotInsertHtml() ) |
389 | Q_PRIVATE_SLOT( d, void _k_slotFormatReset() ) |
390 | Q_PRIVATE_SLOT( d, void _k_slotTextModeChanged( KRichTextEdit::Mode ) ) |
391 | }; |
392 | |
393 | } // namespace |
394 | |
395 | #endif |
396 | |