KTextWidgets

krichtextwidget.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2008 Stephen Kelly <steveire@gmail.com>
4 SPDX-FileCopyrightText: 2008 Thomas McGuire <thomas.mcguire@gmx.net>
5
6 SPDX-License-Identifier: LGPL-2.0-only
7*/
8
9#include "krichtextwidget.h"
10
11#include "krichtextedit_p.h"
12
13// KDE includes
14#include <KColorScheme>
15#include <KFontAction>
16#include <KFontSizeAction>
17#include <KLocalizedString>
18#include <ktoggleaction.h>
19
20// Qt includes
21#include <QAction>
22#include <QActionGroup>
23#include <QColorDialog>
24#include <QTextList>
25
26#include "klinkdialog_p.h"
27
28// TODO: Add i18n context
29
30/**
31 Private class that helps to provide binary compatibility between releases.
32 @internal
33*/
34//@cond PRIVATE
35class KRichTextWidgetPrivate : public KRichTextEditPrivate
36{
37 Q_DECLARE_PUBLIC(KRichTextWidget)
38
39public:
40 KRichTextWidgetPrivate(KRichTextWidget *qq)
41 : KRichTextEditPrivate(qq)
42 {
43 }
44
45 QList<QAction *> richTextActionList;
46 QTextCharFormat painterFormat;
47
49
50 bool painterActive = false;
51
52 bool richTextEnabled = false;
53 KToggleAction *enableRichText = nullptr;
54
55 QAction *action_text_foreground_color = nullptr;
56 QAction *action_text_background_color = nullptr;
57
58 KToggleAction *action_text_bold = nullptr;
59 KToggleAction *action_text_italic = nullptr;
60 KToggleAction *action_text_underline = nullptr;
61 KToggleAction *action_text_strikeout = nullptr;
62
63 KFontAction *action_font_family = nullptr;
64 KFontSizeAction *action_font_size = nullptr;
65
66 KSelectAction *action_list_style = nullptr;
67 QAction *action_list_indent = nullptr;
68 QAction *action_list_dedent = nullptr;
69
70 QAction *action_manage_link = nullptr;
71 QAction *action_insert_horizontal_rule = nullptr;
72 QAction *action_format_painter = nullptr;
73 QAction *action_to_plain_text = nullptr;
74
75 KToggleAction *action_align_left = nullptr;
76 KToggleAction *action_align_right = nullptr;
77 KToggleAction *action_align_center = nullptr;
78 KToggleAction *action_align_justify = nullptr;
79
80 KToggleAction *action_direction_ltr = nullptr;
81 KToggleAction *action_direction_rtl = nullptr;
82
83 KToggleAction *action_text_superscript = nullptr;
84 KToggleAction *action_text_subscript = nullptr;
85
86 KSelectAction *action_heading_level = nullptr;
87
88 //
89 // Normal functions
90 //
91 void init();
92
93 //
94 // Slots
95 //
96
97 /**
98 * @brief Opens a dialog to allow the user to select a foreground color.
99 */
100 void _k_setTextForegroundColor();
101
102 /**
103 * @brief Opens a dialog to allow the user to select a background color.
104 */
105 void _k_setTextBackgroundColor();
106
107 /**
108 * Opens a dialog which lets the user turn the currently selected text into
109 * a link.
110 * If no text is selected, the word under the cursor will be taken.
111 * If the cursor is already over a link, the user can edit that link.
112 *
113 */
114 void _k_manageLink();
115
116 /**
117 * Activates a format painter to allow the user to copy font/text formatting
118 * to different parts of the document.
119 *
120 */
121 void _k_formatPainter(bool active);
122
123 /**
124 * @brief Update actions relating to text format (bold, size etc.).
125 */
126 void updateCharFormatActions(const QTextCharFormat &format);
127
128 /**
129 * Update actions not covered by text formatting, such as alignment,
130 * list style and level.
131 */
132 void updateMiscActions();
133
134 /**
135 * Change the style of the current list or create a new list with the style given by @a index.
136 */
137 void _k_setListStyle(int index);
138
139 /**
140 * Change the heading level of a current line to a level given by @a level
141 */
142 void _k_setHeadingLevel(int level);
143};
144//@endcond
145
146void KRichTextWidgetPrivate::init()
147{
148 Q_Q(KRichTextWidget);
149
150 q->setRichTextSupport(KRichTextWidget::FullSupport);
151}
152
154 : KRichTextEdit(*new KRichTextWidgetPrivate(this), parent)
155{
157
158 d->init();
159}
160
162 : KRichTextEdit(*new KRichTextWidgetPrivate(this), text, parent)
163{
165
166 d->init();
167}
168
170
171KRichTextWidget::RichTextSupport KRichTextWidget::richTextSupport() const
172{
173 Q_D(const KRichTextWidget);
174
175 return d->richTextSupport;
176}
177
179{
181
182 d->richTextSupport = support;
183}
184
186{
188
189 // Note to maintainers: If adding new functionality here, make sure to disconnect
190 // and delete actions which should not be supported.
191 //
192 // New Actions need to be added to the following places:
193 // - possibly the RichTextSupportValues enum
194 // - the API documentation for createActions()
195 // - this function
196 // - the action needs to be added to the private class as a member
197 // - the constructor of the private class
198 // - depending on the action, some slot that changes the toggle state when
199 // appropriate, such as updateCharFormatActions or updateMiscActions.
200
201 // The list of actions currently supported is also stored internally.
202 // This is used to disable all actions at once in setActionsEnabled.
203 d->richTextActionList.clear();
204
205 if (d->richTextSupport & SupportTextForegroundColor) {
206 // Foreground Color
207 d->action_text_foreground_color = new QAction(QIcon::fromTheme(QStringLiteral("format-stroke-color")), i18nc("@action", "Text &Color..."), this);
208 d->action_text_foreground_color->setIconText(i18nc("@label stroke color", "Color"));
209 d->richTextActionList.append((d->action_text_foreground_color));
210 d->action_text_foreground_color->setObjectName(QStringLiteral("format_text_foreground_color"));
211 connect(d->action_text_foreground_color, &QAction::triggered, this, [this]() {
212 Q_D(KRichTextWidget);
213 d->_k_setTextForegroundColor();
214 });
215 } else {
216 d->action_text_foreground_color = nullptr;
217 }
218
219 if (d->richTextSupport & SupportTextBackgroundColor) {
220 // Background Color
221 d->action_text_background_color = new QAction(QIcon::fromTheme(QStringLiteral("format-fill-color")), i18nc("@action", "Text &Highlight..."), this);
222 d->richTextActionList.append((d->action_text_background_color));
223 d->action_text_background_color->setObjectName(QStringLiteral("format_text_background_color"));
224 connect(d->action_text_background_color, &QAction::triggered, this, [this]() {
225 Q_D(KRichTextWidget);
226 d->_k_setTextBackgroundColor();
227 });
228 } else {
229 d->action_text_background_color = nullptr;
230 }
231
232 if (d->richTextSupport & SupportFontFamily) {
233 // Font Family
234 d->action_font_family = new KFontAction(i18nc("@action", "&Font"), this);
235 d->richTextActionList.append((d->action_font_family));
236 d->action_font_family->setObjectName(QStringLiteral("format_font_family"));
238 } else {
239 d->action_font_family = nullptr;
240 }
241
242 if (d->richTextSupport & SupportFontSize) {
243 // Font Size
244 d->action_font_size = new KFontSizeAction(i18nc("@action", "Font &Size"), this);
245 d->richTextActionList.append((d->action_font_size));
246 d->action_font_size->setObjectName(QStringLiteral("format_font_size"));
247 connect(d->action_font_size, &KFontSizeAction::fontSizeChanged, this, &KRichTextEdit::setFontSize);
248 } else {
249 d->action_font_size = nullptr;
250 }
251
252 if (d->richTextSupport & SupportBold) {
253 d->action_text_bold = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-bold")), i18nc("@action boldify selected text", "&Bold"), this);
254 QFont bold;
255 bold.setBold(true);
256 d->action_text_bold->setFont(bold);
257 d->richTextActionList.append((d->action_text_bold));
258 d->action_text_bold->setObjectName(QStringLiteral("format_text_bold"));
259 d->action_text_bold->setShortcut(Qt::CTRL | Qt::Key_B);
260 connect(d->action_text_bold, &QAction::triggered, this, &KRichTextEdit::setTextBold);
261 } else {
262 d->action_text_bold = nullptr;
263 }
264
265 if (d->richTextSupport & SupportItalic) {
266 d->action_text_italic =
267 new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-italic")), i18nc("@action italicize selected text", "&Italic"), this);
268 QFont italic;
269 italic.setItalic(true);
270 d->action_text_italic->setFont(italic);
271 d->richTextActionList.append((d->action_text_italic));
272 d->action_text_italic->setObjectName(QStringLiteral("format_text_italic"));
273 d->action_text_italic->setShortcut(Qt::CTRL | Qt::Key_I);
274 connect(d->action_text_italic, &QAction::triggered, this, &KRichTextEdit::setTextItalic);
275 } else {
276 d->action_text_italic = nullptr;
277 }
278
279 if (d->richTextSupport & SupportUnderline) {
280 d->action_text_underline =
281 new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-underline")), i18nc("@action underline selected text", "&Underline"), this);
282 QFont underline;
283 underline.setUnderline(true);
284 d->action_text_underline->setFont(underline);
285 d->richTextActionList.append((d->action_text_underline));
286 d->action_text_underline->setObjectName(QStringLiteral("format_text_underline"));
287 d->action_text_underline->setShortcut(Qt::CTRL | Qt::Key_U);
288 connect(d->action_text_underline, &QAction::triggered, this, &KRichTextEdit::setTextUnderline);
289 } else {
290 d->action_text_underline = nullptr;
291 }
292
293 if (d->richTextSupport & SupportStrikeOut) {
294 d->action_text_strikeout = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-strikethrough")), i18nc("@action", "&Strike Out"), this);
295 QFont strikeout;
296 strikeout.setStrikeOut(true);
297 d->action_text_strikeout->setFont(strikeout);
298 d->richTextActionList.append((d->action_text_strikeout));
299 d->action_text_strikeout->setObjectName(QStringLiteral("format_text_strikeout"));
300 d->action_text_strikeout->setShortcut(Qt::CTRL | Qt::Key_L);
301 connect(d->action_text_strikeout, &QAction::triggered, this, &KRichTextEdit::setTextStrikeOut);
302 } else {
303 d->action_text_strikeout = nullptr;
304 }
305
306 if (d->richTextSupport & SupportAlignment) {
307 // Alignment
308 d->action_align_left = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-left")), i18nc("@action", "Align &Left"), this);
309 d->action_align_left->setIconText(i18nc("@label left justify", "Left"));
310 d->richTextActionList.append((d->action_align_left));
311 d->action_align_left->setObjectName(QStringLiteral("format_align_left"));
312 connect(d->action_align_left, &QAction::triggered, this, &KRichTextEdit::alignLeft);
313
314 d->action_align_center = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-center")), i18nc("@action", "Align &Center"), this);
315 d->action_align_center->setIconText(i18nc("@label center justify", "Center"));
316 d->richTextActionList.append((d->action_align_center));
317 d->action_align_center->setObjectName(QStringLiteral("format_align_center"));
318 connect(d->action_align_center, &QAction::triggered, this, &KRichTextEdit::alignCenter);
319
320 d->action_align_right = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-right")), i18nc("@action", "Align &Right"), this);
321 d->action_align_right->setIconText(i18nc("@label right justify", "Right"));
322 d->richTextActionList.append((d->action_align_right));
323 d->action_align_right->setObjectName(QStringLiteral("format_align_right"));
324 connect(d->action_align_right, &QAction::triggered, this, &KRichTextEdit::alignRight);
325
326 d->action_align_justify = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-fill")), i18nc("@action", "&Justify"), this);
327 d->action_align_justify->setIconText(i18nc("@label justify fill", "Justify"));
328 d->richTextActionList.append((d->action_align_justify));
329 d->action_align_justify->setObjectName(QStringLiteral("format_align_justify"));
330 connect(d->action_align_justify, &QAction::triggered, this, &KRichTextEdit::alignJustify);
331
332 QActionGroup *alignmentGroup = new QActionGroup(this);
333 alignmentGroup->addAction(d->action_align_left);
334 alignmentGroup->addAction(d->action_align_center);
335 alignmentGroup->addAction(d->action_align_right);
336 alignmentGroup->addAction(d->action_align_justify);
337 } else {
338 d->action_align_left = nullptr;
339 d->action_align_center = nullptr;
340 d->action_align_right = nullptr;
341 d->action_align_justify = nullptr;
342 }
343
344 if (d->richTextSupport & SupportDirection) {
345 d->action_direction_ltr = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-direction-ltr")), i18nc("@action", "Left-to-Right"), this);
346 d->action_direction_ltr->setIconText(i18nc("@label left-to-right", "Left-to-Right"));
347 d->richTextActionList.append(d->action_direction_ltr);
348 d->action_direction_ltr->setObjectName(QStringLiteral("direction_ltr"));
349 connect(d->action_direction_ltr, &QAction::triggered, this, &KRichTextEdit::makeLeftToRight);
350
351 d->action_direction_rtl = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-direction-rtl")), i18nc("@action", "Right-to-Left"), this);
352 d->action_direction_rtl->setIconText(i18nc("@label right-to-left", "Right-to-Left"));
353 d->richTextActionList.append(d->action_direction_rtl);
354 d->action_direction_rtl->setObjectName(QStringLiteral("direction_rtl"));
355 connect(d->action_direction_rtl, &QAction::triggered, this, &KRichTextEdit::makeRightToLeft);
356
357 QActionGroup *directionGroup = new QActionGroup(this);
358 directionGroup->addAction(d->action_direction_ltr);
359 directionGroup->addAction(d->action_direction_rtl);
360 } else {
361 d->action_direction_ltr = nullptr;
362 d->action_direction_rtl = nullptr;
363 }
364
365 if (d->richTextSupport & SupportChangeListStyle) {
366 d->action_list_style = new KSelectAction(QIcon::fromTheme(QStringLiteral("format-list-unordered")), i18nc("@title:menu", "List Style"), this);
367 QStringList listStyles;
368 /* clang-format off */
369 listStyles << i18nc("@item:inmenu no list style", "None")
370 << i18nc("@item:inmenu disc list style", "Disc")
371 << i18nc("@item:inmenu circle list style", "Circle")
372 << i18nc("@item:inmenu square list style", "Square")
373 << i18nc("@item:inmenu numbered lists", "123")
374 << i18nc("@item:inmenu lowercase abc lists", "abc")
375 << i18nc("@item:inmenu uppercase abc lists", "ABC")
376 << i18nc("@item:inmenu lower case roman numerals", "i ii iii")
377 << i18nc("@item:inmenu upper case roman numerals", "I II III");
378 /* clang-format on */
379
380 d->action_list_style->setItems(listStyles);
381 d->action_list_style->setCurrentItem(0);
382 d->richTextActionList.append((d->action_list_style));
383 d->action_list_style->setObjectName(QStringLiteral("format_list_style"));
384
385 connect(d->action_list_style, &KSelectAction::indexTriggered, this, [this](int style) {
386 Q_D(KRichTextWidget);
387 d->_k_setListStyle(style);
388 });
389 connect(d->action_list_style, &QAction::triggered, this, [d]() {
390 d->updateMiscActions();
391 });
392 } else {
393 d->action_list_style = nullptr;
394 }
395
396 if (d->richTextSupport & SupportIndentLists) {
397 d->action_list_indent = new QAction(QIcon::fromTheme(QStringLiteral("format-indent-more")), i18nc("@action", "Increase Indent"), this);
398 d->richTextActionList.append((d->action_list_indent));
399 d->action_list_indent->setObjectName(QStringLiteral("format_list_indent_more"));
400 connect(d->action_list_indent, &QAction::triggered, this, &KRichTextEdit::indentListMore);
401 connect(d->action_list_indent, &QAction::triggered, this, [d]() {
402 d->updateMiscActions();
403 });
404 } else {
405 d->action_list_indent = nullptr;
406 }
407
408 if (d->richTextSupport & SupportDedentLists) {
409 d->action_list_dedent = new QAction(QIcon::fromTheme(QStringLiteral("format-indent-less")), i18nc("@action", "Decrease Indent"), this);
410 d->richTextActionList.append((d->action_list_dedent));
411 d->action_list_dedent->setObjectName(QStringLiteral("format_list_indent_less"));
412 connect(d->action_list_dedent, &QAction::triggered, this, &KRichTextEdit::indentListLess);
413 connect(d->action_list_dedent, &QAction::triggered, this, [d]() {
414 d->updateMiscActions();
415 });
416 } else {
417 d->action_list_dedent = nullptr;
418 }
419
420 if (d->richTextSupport & SupportRuleLine) {
421 d->action_insert_horizontal_rule = new QAction(QIcon::fromTheme(QStringLiteral("insert-horizontal-rule")), i18nc("@action", "Insert Rule Line"), this);
422 d->richTextActionList.append((d->action_insert_horizontal_rule));
423 d->action_insert_horizontal_rule->setObjectName(QStringLiteral("insert_horizontal_rule"));
424 connect(d->action_insert_horizontal_rule, &QAction::triggered, this, &KRichTextEdit::insertHorizontalRule);
425 } else {
426 d->action_insert_horizontal_rule = nullptr;
427 }
428
429 if (d->richTextSupport & SupportHyperlinks) {
430 d->action_manage_link = new QAction(QIcon::fromTheme(QStringLiteral("insert-link")), i18nc("@action", "Link"), this);
431 d->richTextActionList.append((d->action_manage_link));
432 d->action_manage_link->setObjectName(QStringLiteral("manage_link"));
433 connect(d->action_manage_link, &QAction::triggered, this, [this]() {
434 Q_D(KRichTextWidget);
435 d->_k_manageLink();
436 });
437 } else {
438 d->action_manage_link = nullptr;
439 }
440
441 if (d->richTextSupport & SupportFormatPainting) {
442 d->action_format_painter = new KToggleAction(QIcon::fromTheme(QStringLiteral("draw-brush")), i18nc("@action", "Format Painter"), this);
443 d->richTextActionList.append((d->action_format_painter));
444 d->action_format_painter->setObjectName(QStringLiteral("format_painter"));
445 connect(d->action_format_painter, &QAction::toggled, this, [this](bool state) {
446 Q_D(KRichTextWidget);
447 d->_k_formatPainter(state);
448 });
449 } else {
450 d->action_format_painter = nullptr;
451 }
452
453 if (d->richTextSupport & SupportToPlainText) {
454 d->action_to_plain_text = new KToggleAction(i18nc("@action", "To Plain Text"), this);
455 d->richTextActionList.append((d->action_to_plain_text));
456 d->action_to_plain_text->setObjectName(QStringLiteral("action_to_plain_text"));
457 connect(d->action_to_plain_text, &QAction::triggered, this, &KRichTextEdit::switchToPlainText);
458 } else {
459 d->action_to_plain_text = nullptr;
460 }
461
462 if (d->richTextSupport & SupportSuperScriptAndSubScript) {
463 d->action_text_subscript = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-subscript")), i18nc("@action", "Subscript"), this);
464 d->richTextActionList.append((d->action_text_subscript));
465 d->action_text_subscript->setObjectName(QStringLiteral("format_text_subscript"));
466 connect(d->action_text_subscript, &QAction::triggered, this, &KRichTextEdit::setTextSubScript);
467
468 d->action_text_superscript = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-superscript")), i18nc("@action", "Superscript"), this);
469 d->richTextActionList.append((d->action_text_superscript));
470 d->action_text_superscript->setObjectName(QStringLiteral("format_text_superscript"));
471 connect(d->action_text_superscript, &QAction::triggered, this, &KRichTextEdit::setTextSuperScript);
472 } else {
473 d->action_text_subscript = nullptr;
474
475 d->action_text_superscript = nullptr;
476 }
477
478 if (d->richTextSupport & SupportHeading) {
479 // TODO: an icon maybe?
480 d->action_heading_level = new KSelectAction(i18nc("@title:menu", "Heading Level"), this);
481 const QStringList headingLevels = {i18nc("@item:inmenu no heading", "Basic text"),
482 i18nc("@item:inmenu heading level 1 (largest)", "Title"),
483 i18nc("@item:inmenu heading level 2", "Subtitle"),
484 i18nc("@item:inmenu heading level 3", "Section"),
485 i18nc("@item:inmenu heading level 4", "Subsection"),
486 i18nc("@item:inmenu heading level 5", "Paragraph"),
487 i18nc("@item:inmenu heading level 6 (smallest)", "Subparagraph")};
488
489 d->action_heading_level->setItems(headingLevels);
490 d->action_heading_level->setCurrentItem(0);
491 d->richTextActionList.append(d->action_heading_level);
492 d->action_heading_level->setObjectName(QStringLiteral("format_heading_level"));
493 connect(d->action_heading_level, &KSelectAction::indexTriggered, this, [this](int level) {
494 Q_D(KRichTextWidget);
495 d->_k_setHeadingLevel(level);
496 });
497 } else {
498 d->action_heading_level = nullptr;
499 }
500
501 disconnect(this, &QTextEdit::currentCharFormatChanged, this, nullptr);
502 disconnect(this, &QTextEdit::cursorPositionChanged, this, nullptr);
503 connect(this, &QTextEdit::currentCharFormatChanged, this, [d](const QTextCharFormat &format) {
504 d->updateCharFormatActions(format);
505 });
506 connect(this, &QTextEdit::cursorPositionChanged, this, [d]() {
507 d->updateMiscActions();
508 });
509
510 d->updateMiscActions();
511 d->updateCharFormatActions(currentCharFormat());
512
513 return d->richTextActionList;
514}
515
517{
519
520 for (QAction *action : std::as_const(d->richTextActionList)) {
521 action->setEnabled(enabled);
522 }
523 d->richTextEnabled = enabled;
524}
525
526void KRichTextWidgetPrivate::_k_setListStyle(int index)
527{
528 Q_Q(KRichTextWidget);
529
530 q->setListStyle(index);
531 updateMiscActions();
532}
533
534void KRichTextWidgetPrivate::_k_setHeadingLevel(int level)
535{
536 Q_Q(KRichTextWidget);
537
538 q->setHeadingLevel(level);
539 updateMiscActions();
540}
541
542void KRichTextWidgetPrivate::updateCharFormatActions(const QTextCharFormat &format)
543{
544 Q_Q(KRichTextWidget);
545
546 QFont f = format.font();
547
548 if (richTextSupport & KRichTextWidget::SupportFontFamily) {
549 action_font_family->setFont(f.family());
550 }
551 if (richTextSupport & KRichTextWidget::SupportFontSize) {
552 if (f.pointSize() > 0) {
553 action_font_size->setFontSize(f.pointSize());
554 }
555 }
556
557 if (richTextSupport & KRichTextWidget::SupportBold) {
558 action_text_bold->setChecked(f.bold());
559 }
560
561 if (richTextSupport & KRichTextWidget::SupportItalic) {
562 action_text_italic->setChecked(f.italic());
563 }
564
565 if (richTextSupport & KRichTextWidget::SupportUnderline) {
566 action_text_underline->setChecked(f.underline());
567 }
568
569 if (richTextSupport & KRichTextWidget::SupportStrikeOut) {
570 action_text_strikeout->setChecked(f.strikeOut());
571 }
572
575 action_text_superscript->setChecked(vAlign == QTextCharFormat::AlignSuperScript);
576 action_text_subscript->setChecked(vAlign == QTextCharFormat::AlignSubScript);
577 }
578}
579
580void KRichTextWidgetPrivate::updateMiscActions()
581{
582 Q_Q(KRichTextWidget);
583
584 if (richTextSupport & KRichTextWidget::SupportAlignment) {
585 Qt::Alignment a = q->alignment();
586 if (a & Qt::AlignLeft) {
587 action_align_left->setChecked(true);
588 } else if (a & Qt::AlignHCenter) {
589 action_align_center->setChecked(true);
590 } else if (a & Qt::AlignRight) {
591 action_align_right->setChecked(true);
592 } else if (a & Qt::AlignJustify) {
593 action_align_justify->setChecked(true);
594 }
595 }
596
597 if (richTextSupport & KRichTextWidget::SupportChangeListStyle) {
598 if (q->textCursor().currentList()) {
599 action_list_style->setCurrentItem(-q->textCursor().currentList()->format().style());
600 } else {
601 action_list_style->setCurrentItem(0);
602 }
603 }
604
605 if (richTextSupport & KRichTextWidget::SupportIndentLists) {
606 if (richTextEnabled) {
607 action_list_indent->setEnabled(q->canIndentList());
608 } else {
609 action_list_indent->setEnabled(false);
610 }
611 }
612
613 if (richTextSupport & KRichTextWidget::SupportDedentLists) {
614 if (richTextEnabled) {
615 action_list_dedent->setEnabled(q->canDedentList());
616 } else {
617 action_list_dedent->setEnabled(false);
618 }
619 }
620
621 if (richTextSupport & KRichTextWidget::SupportDirection) {
622 const Qt::LayoutDirection direction = q->textCursor().blockFormat().layoutDirection();
623 action_direction_ltr->setChecked(direction == Qt::LeftToRight);
624 action_direction_rtl->setChecked(direction == Qt::RightToLeft);
625 }
626
627 if (richTextSupport & KRichTextWidget::SupportHeading) {
628 action_heading_level->setCurrentItem(q->textCursor().blockFormat().headingLevel());
629 }
630}
631
632void KRichTextWidgetPrivate::_k_setTextForegroundColor()
633{
634 Q_Q(KRichTextWidget);
635
636 const QColor currentColor = q->textColor();
638
639 const QColor selectedColor = QColorDialog::getColor(currentColor.isValid() ? currentColor : defaultColor, q);
640
641 if (!selectedColor.isValid() && !currentColor.isValid()) {
642 q->setTextForegroundColor(defaultColor);
643 } else if (selectedColor.isValid()) {
644 q->setTextForegroundColor(selectedColor);
645 }
646}
647
648void KRichTextWidgetPrivate::_k_setTextBackgroundColor()
649{
650 Q_Q(KRichTextWidget);
651
652 QTextCharFormat fmt = q->textCursor().charFormat();
653 const QColor currentColor = fmt.background().color();
655
656 const QColor selectedColor = QColorDialog::getColor(currentColor.isValid() ? currentColor : defaultColor, q);
657
658 if (!selectedColor.isValid() && !currentColor.isValid()) {
659 q->setTextBackgroundColor(defaultColor);
660 } else if (selectedColor.isValid()) {
661 q->setTextBackgroundColor(selectedColor);
662 }
663}
664
665void KRichTextWidgetPrivate::_k_manageLink()
666{
667 Q_Q(KRichTextWidget);
668
669 q->selectLinkText();
670 KLinkDialog *linkDialog = new KLinkDialog(q);
671 linkDialog->setLinkText(q->currentLinkText());
672 linkDialog->setLinkUrl(q->currentLinkUrl());
673 linkDialog->setAttribute(Qt::WA_DeleteOnClose);
674
675 QObject::connect(linkDialog, &QDialog::accepted, linkDialog, [linkDialog, this]() {
676 Q_Q(KRichTextWidget);
677 q->updateLink(linkDialog->linkUrl(), linkDialog->linkText());
678 });
679
680 linkDialog->show();
681}
682
684{
686
687 if (d->painterActive) {
688 // If the painter is active, paint the selection with the
689 // correct format.
690 if (textCursor().hasSelection()) {
692 c.setCharFormat(d->painterFormat);
693 setTextCursor(c);
694 }
695 d->painterActive = false;
696 d->action_format_painter->setChecked(false);
697 }
699}
700
701void KRichTextWidgetPrivate::_k_formatPainter(bool active)
702{
703 Q_Q(KRichTextWidget);
704
705 if (active) {
706 painterFormat = q->currentCharFormat();
707 painterActive = true;
708 q->viewport()->setCursor(QCursor(QIcon::fromTheme(QStringLiteral("draw-brush")).pixmap(32, 32), 0, 32));
709 } else {
710 painterFormat = QTextCharFormat();
711 painterActive = false;
712 q->viewport()->setCursor(Qt::IBeamCursor);
713 }
714}
715
717{
719
720 d->updateMiscActions();
721 d->updateCharFormatActions(currentCharFormat());
722}
723
724#include "moc_krichtextwidget.cpp"
QBrush foreground(ForegroundRole=NormalText) const
The KRichTextEdit class provides a widget to edit and display rich text.
void setTextStrikeOut(bool strikeOut)
Toggles the strikeout formatting of the current word or selection at the current cursor position.
void setTextSubScript(bool subscript)
Toggles the subscript formatting of the current word or selection at the current cursor position.
void alignRight()
Sets the alignment of the current block to Right Aligned.
void insertHorizontalRule()
Inserts a horizontal rule below the current block.
void alignJustify()
Sets the alignment of the current block to Justified.
void switchToPlainText()
This will switch the editor to plain text mode.
void setTextUnderline(bool underline)
Toggles the underline formatting of the current word or selection at the current cursor position.
void setFontSize(int size)
Sets the current word or selection to the font size size.
void indentListLess()
Decreases the nesting level of the current block or selected blocks.
void makeLeftToRight()
Sets the direction of the current block to Left-To-Right.
void indentListMore()
Increases the nesting level of the current block or selected blocks.
void alignLeft()
Sets the alignment of the current block to Left Aligned.
void setTextSuperScript(bool superscript)
Toggles the superscript formatting of the current word or selection at the current cursor position.
void setTextBold(bool bold)
Toggles the bold formatting of the current word or selection at the current cursor position.
void setTextItalic(bool italic)
Toggles the italic formatting of the current word or selection at the current cursor position.
void makeRightToLeft()
Sets the direction of the current block to Right-To-Left.
void alignCenter()
Sets the alignment of the current block to Centered.
A KRichTextEdit with common actions.
KRichTextWidget(QWidget *parent)
Constructor.
void setActionsEnabled(bool enabled)
Disables or enables all of the actions created by createActions().
~KRichTextWidget() override
Destructor.
void mouseReleaseEvent(QMouseEvent *event) override
Reimplemented.
void updateActionStates()
Tells KRichTextWidget to update the state of the actions created by createActions().
void setRichTextSupport(const KRichTextWidget::RichTextSupport &support)
Sets the supported rich text subset available.
@ SupportTextBackgroundColor
Action to change the background color of the currently selected text.
@ SupportFontFamily
Action to change the font family of the currently selected text.
@ SupportDirection
Action to change direction of text to Right-To-Left or Left-To-Right.
@ SupportItalic
Action to format the selected text as italic.
@ SupportUnderline
Action to underline the selected text.
@ SupportHeading
Action to make the current line a heading (up to six levels, corresponding to HTML h1....
@ SupportBold
Action to format the selected text as bold.
@ SupportStrikeOut
Action to strike out the selected text.
@ SupportDedentLists
Action to decrease the current list nesting level.
@ SupportHyperlinks
Action to convert the current text to a hyperlink.
@ SupportChangeListStyle
Action to make the current line a list element, change the list style or remove list formatting.
@ SupportRuleLine
Action to insert a horizontal line.
@ FullSupport
Includes all above actions for full rich text support.
@ SupportToPlainText
Action to change the text of the whole text edit to plain text.
@ SupportFontSize
Action to change the font size of the currently selected text.
@ SupportTextForegroundColor
Action to change the text color of the currently selected text.
@ SupportFormatPainting
Action to make the mouse cursor a format painter.
@ SupportAlignment
Actions to align the current paragraph left, righ, center or justify.
@ SupportSuperScriptAndSubScript
Actions to format text as superscript or subscript.
@ SupportIndentLists
Action to increase the current list nesting level.
virtual QList< QAction * > createActions()
Creates the actions and adds them to the given action collection.
void indexTriggered(int index)
void textTriggered(const QString &text)
bool event(QEvent *) override
Reimplemented to catch "delete word" shortcut events.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QCA_EXPORT void init()
virtual void mouseReleaseEvent(QMouseEvent *e) override
void toggled(bool checked)
void triggered(bool checked)
QAction * addAction(QAction *action)
const QColor & color() const const
bool isValid() const const
QColor getColor(const QColor &initial, QWidget *parent, const QString &title, ColorDialogOptions options)
void accepted()
bool bold() const const
QString family() const const
bool italic() const const
int pointSize() const const
void setBold(bool enable)
void setItalic(bool enable)
void setStrikeOut(bool enable)
void setUnderline(bool enable)
bool strikeOut() const const
bool underline() const const
QIcon fromTheme(const QString &name)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
QString & append(QChar ch)
typedef Alignment
IBeamCursor
LayoutDirection
WA_DeleteOnClose
QFont font() const const
VerticalAlignment verticalAlignment() const const
void setCharFormat(const QTextCharFormat &format)
QTextCharFormat currentCharFormat() const const
void currentCharFormatChanged(const QTextCharFormat &f)
void cursorPositionChanged()
void setFontFamily(const QString &fontFamily)
void setTextCursor(const QTextCursor &cursor)
QTextCursor textCursor() const const
QBrush background() const const
QStyle * style() const const
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:17:07 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.