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 QFont f = format.font();
545
546 if (richTextSupport & KRichTextWidget::SupportFontFamily) {
547 action_font_family->setFont(f.family());
548 }
549 if (richTextSupport & KRichTextWidget::SupportFontSize) {
550 if (f.pointSize() > 0) {
551 action_font_size->setFontSize(f.pointSize());
552 }
553 }
554
555 if (richTextSupport & KRichTextWidget::SupportBold) {
556 action_text_bold->setChecked(f.bold());
557 }
558
559 if (richTextSupport & KRichTextWidget::SupportItalic) {
560 action_text_italic->setChecked(f.italic());
561 }
562
563 if (richTextSupport & KRichTextWidget::SupportUnderline) {
564 action_text_underline->setChecked(f.underline());
565 }
566
567 if (richTextSupport & KRichTextWidget::SupportStrikeOut) {
568 action_text_strikeout->setChecked(f.strikeOut());
569 }
570
573 action_text_superscript->setChecked(vAlign == QTextCharFormat::AlignSuperScript);
574 action_text_subscript->setChecked(vAlign == QTextCharFormat::AlignSubScript);
575 }
576}
577
578void KRichTextWidgetPrivate::updateMiscActions()
579{
580 Q_Q(KRichTextWidget);
581
582 if (richTextSupport & KRichTextWidget::SupportAlignment) {
583 Qt::Alignment a = q->alignment();
584 if (a & Qt::AlignLeft) {
585 action_align_left->setChecked(true);
586 } else if (a & Qt::AlignHCenter) {
587 action_align_center->setChecked(true);
588 } else if (a & Qt::AlignRight) {
589 action_align_right->setChecked(true);
590 } else if (a & Qt::AlignJustify) {
591 action_align_justify->setChecked(true);
592 }
593 }
594
595 if (richTextSupport & KRichTextWidget::SupportChangeListStyle) {
596 if (q->textCursor().currentList()) {
597 action_list_style->setCurrentItem(-q->textCursor().currentList()->format().style());
598 } else {
599 action_list_style->setCurrentItem(0);
600 }
601 }
602
603 if (richTextSupport & KRichTextWidget::SupportIndentLists) {
604 if (richTextEnabled) {
605 action_list_indent->setEnabled(q->canIndentList());
606 } else {
607 action_list_indent->setEnabled(false);
608 }
609 }
610
611 if (richTextSupport & KRichTextWidget::SupportDedentLists) {
612 if (richTextEnabled) {
613 action_list_dedent->setEnabled(q->canDedentList());
614 } else {
615 action_list_dedent->setEnabled(false);
616 }
617 }
618
619 if (richTextSupport & KRichTextWidget::SupportDirection) {
620 const Qt::LayoutDirection direction = q->textCursor().blockFormat().layoutDirection();
621 action_direction_ltr->setChecked(direction == Qt::LeftToRight);
622 action_direction_rtl->setChecked(direction == Qt::RightToLeft);
623 }
624
625 if (richTextSupport & KRichTextWidget::SupportHeading) {
626 action_heading_level->setCurrentItem(q->textCursor().blockFormat().headingLevel());
627 }
628}
629
630void KRichTextWidgetPrivate::_k_setTextForegroundColor()
631{
632 Q_Q(KRichTextWidget);
633
634 const QColor currentColor = q->textColor();
636
637 const QColor selectedColor = QColorDialog::getColor(currentColor.isValid() ? currentColor : defaultColor, q);
638
639 if (!selectedColor.isValid() && !currentColor.isValid()) {
640 q->setTextForegroundColor(defaultColor);
641 } else if (selectedColor.isValid()) {
642 q->setTextForegroundColor(selectedColor);
643 }
644}
645
646void KRichTextWidgetPrivate::_k_setTextBackgroundColor()
647{
648 Q_Q(KRichTextWidget);
649
650 QTextCharFormat fmt = q->textCursor().charFormat();
651 const QColor currentColor = fmt.background().color();
653
654 const QColor selectedColor = QColorDialog::getColor(currentColor.isValid() ? currentColor : defaultColor, q);
655
656 if (!selectedColor.isValid() && !currentColor.isValid()) {
657 q->setTextBackgroundColor(defaultColor);
658 } else if (selectedColor.isValid()) {
659 q->setTextBackgroundColor(selectedColor);
660 }
661}
662
663void KRichTextWidgetPrivate::_k_manageLink()
664{
665 Q_Q(KRichTextWidget);
666
667 q->selectLinkText();
668 KLinkDialog *linkDialog = new KLinkDialog(q);
669 linkDialog->setLinkText(q->currentLinkText());
670 linkDialog->setLinkUrl(q->currentLinkUrl());
671 linkDialog->setAttribute(Qt::WA_DeleteOnClose);
672
673 QObject::connect(linkDialog, &QDialog::accepted, linkDialog, [linkDialog, this]() {
674 Q_Q(KRichTextWidget);
675 q->updateLink(linkDialog->linkUrl(), linkDialog->linkText());
676 });
677
678 linkDialog->show();
679}
680
682{
684
685 if (d->painterActive) {
686 // If the painter is active, paint the selection with the
687 // correct format.
688 if (textCursor().hasSelection()) {
690 c.setCharFormat(d->painterFormat);
691 setTextCursor(c);
692 }
693 d->painterActive = false;
694 d->action_format_painter->setChecked(false);
695 }
697}
698
699void KRichTextWidgetPrivate::_k_formatPainter(bool active)
700{
701 Q_Q(KRichTextWidget);
702
703 if (active) {
704 painterFormat = q->currentCharFormat();
705 painterActive = true;
706 q->viewport()->setCursor(QCursor(QIcon::fromTheme(QStringLiteral("draw-brush")).pixmap(32, 32), 0, 32));
707 } else {
708 painterFormat = QTextCharFormat();
709 painterActive = false;
710 q->viewport()->setCursor(Qt::IBeamCursor);
711 }
712}
713
715{
717
718 d->updateMiscActions();
719 d->updateCharFormatActions(currentCharFormat());
720}
721
722#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)
void append(QList< T > &&value)
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-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:14:15 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.