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

KDE's Doxygen guidelines are available online.