File indexing completed on 2024-04-21 03:58:28
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2008 Stephen Kelly <steveire@gmail.com> 0004 SPDX-FileCopyrightText: 2008 Thomas McGuire <thomas.mcguire@gmx.net> 0005 0006 SPDX-License-Identifier: LGPL-2.0-only 0007 */ 0008 0009 #include "krichtextwidget.h" 0010 0011 #include "krichtextedit_p.h" 0012 0013 // KDE includes 0014 #include <KColorScheme> 0015 #include <KFontAction> 0016 #include <KFontSizeAction> 0017 #include <KLocalizedString> 0018 #include <ktoggleaction.h> 0019 0020 // Qt includes 0021 #include <QAction> 0022 #include <QActionGroup> 0023 #include <QColorDialog> 0024 #include <QTextList> 0025 0026 #include "klinkdialog_p.h" 0027 0028 // TODO: Add i18n context 0029 0030 /** 0031 Private class that helps to provide binary compatibility between releases. 0032 @internal 0033 */ 0034 //@cond PRIVATE 0035 class KRichTextWidgetPrivate : public KRichTextEditPrivate 0036 { 0037 Q_DECLARE_PUBLIC(KRichTextWidget) 0038 0039 public: 0040 KRichTextWidgetPrivate(KRichTextWidget *qq) 0041 : KRichTextEditPrivate(qq) 0042 { 0043 } 0044 0045 QList<QAction *> richTextActionList; 0046 QTextCharFormat painterFormat; 0047 0048 KRichTextWidget::RichTextSupport richTextSupport; 0049 0050 bool painterActive = false; 0051 0052 bool richTextEnabled = false; 0053 KToggleAction *enableRichText = nullptr; 0054 0055 QAction *action_text_foreground_color = nullptr; 0056 QAction *action_text_background_color = nullptr; 0057 0058 KToggleAction *action_text_bold = nullptr; 0059 KToggleAction *action_text_italic = nullptr; 0060 KToggleAction *action_text_underline = nullptr; 0061 KToggleAction *action_text_strikeout = nullptr; 0062 0063 KFontAction *action_font_family = nullptr; 0064 KFontSizeAction *action_font_size = nullptr; 0065 0066 KSelectAction *action_list_style = nullptr; 0067 QAction *action_list_indent = nullptr; 0068 QAction *action_list_dedent = nullptr; 0069 0070 QAction *action_manage_link = nullptr; 0071 QAction *action_insert_horizontal_rule = nullptr; 0072 QAction *action_format_painter = nullptr; 0073 QAction *action_to_plain_text = nullptr; 0074 0075 KToggleAction *action_align_left = nullptr; 0076 KToggleAction *action_align_right = nullptr; 0077 KToggleAction *action_align_center = nullptr; 0078 KToggleAction *action_align_justify = nullptr; 0079 0080 KToggleAction *action_direction_ltr = nullptr; 0081 KToggleAction *action_direction_rtl = nullptr; 0082 0083 KToggleAction *action_text_superscript = nullptr; 0084 KToggleAction *action_text_subscript = nullptr; 0085 0086 KSelectAction *action_heading_level = nullptr; 0087 0088 // 0089 // Normal functions 0090 // 0091 void init(); 0092 0093 // 0094 // Slots 0095 // 0096 0097 /** 0098 * @brief Opens a dialog to allow the user to select a foreground color. 0099 */ 0100 void _k_setTextForegroundColor(); 0101 0102 /** 0103 * @brief Opens a dialog to allow the user to select a background color. 0104 */ 0105 void _k_setTextBackgroundColor(); 0106 0107 /** 0108 * Opens a dialog which lets the user turn the currently selected text into 0109 * a link. 0110 * If no text is selected, the word under the cursor will be taken. 0111 * If the cursor is already over a link, the user can edit that link. 0112 * 0113 */ 0114 void _k_manageLink(); 0115 0116 /** 0117 * Activates a format painter to allow the user to copy font/text formatting 0118 * to different parts of the document. 0119 * 0120 */ 0121 void _k_formatPainter(bool active); 0122 0123 /** 0124 * @brief Update actions relating to text format (bold, size etc.). 0125 */ 0126 void updateCharFormatActions(const QTextCharFormat &format); 0127 0128 /** 0129 * Update actions not covered by text formatting, such as alignment, 0130 * list style and level. 0131 */ 0132 void updateMiscActions(); 0133 0134 /** 0135 * Change the style of the current list or create a new list with the style given by @a index. 0136 */ 0137 void _k_setListStyle(int index); 0138 0139 /** 0140 * Change the heading level of a current line to a level given by @a level 0141 */ 0142 void _k_setHeadingLevel(int level); 0143 }; 0144 //@endcond 0145 0146 void KRichTextWidgetPrivate::init() 0147 { 0148 Q_Q(KRichTextWidget); 0149 0150 q->setRichTextSupport(KRichTextWidget::FullSupport); 0151 } 0152 0153 KRichTextWidget::KRichTextWidget(QWidget *parent) 0154 : KRichTextEdit(*new KRichTextWidgetPrivate(this), parent) 0155 { 0156 Q_D(KRichTextWidget); 0157 0158 d->init(); 0159 } 0160 0161 KRichTextWidget::KRichTextWidget(const QString &text, QWidget *parent) 0162 : KRichTextEdit(*new KRichTextWidgetPrivate(this), text, parent) 0163 { 0164 Q_D(KRichTextWidget); 0165 0166 d->init(); 0167 } 0168 0169 KRichTextWidget::~KRichTextWidget() = default; 0170 0171 KRichTextWidget::RichTextSupport KRichTextWidget::richTextSupport() const 0172 { 0173 Q_D(const KRichTextWidget); 0174 0175 return d->richTextSupport; 0176 } 0177 0178 void KRichTextWidget::setRichTextSupport(const KRichTextWidget::RichTextSupport &support) 0179 { 0180 Q_D(KRichTextWidget); 0181 0182 d->richTextSupport = support; 0183 } 0184 0185 QList<QAction *> KRichTextWidget::createActions() 0186 { 0187 Q_D(KRichTextWidget); 0188 0189 // Note to maintainers: If adding new functionality here, make sure to disconnect 0190 // and delete actions which should not be supported. 0191 // 0192 // New Actions need to be added to the following places: 0193 // - possibly the RichTextSupportValues enum 0194 // - the API documentation for createActions() 0195 // - this function 0196 // - the action needs to be added to the private class as a member 0197 // - the constructor of the private class 0198 // - depending on the action, some slot that changes the toggle state when 0199 // appropriate, such as updateCharFormatActions or updateMiscActions. 0200 0201 // The list of actions currently supported is also stored internally. 0202 // This is used to disable all actions at once in setActionsEnabled. 0203 d->richTextActionList.clear(); 0204 0205 if (d->richTextSupport & SupportTextForegroundColor) { 0206 // Foreground Color 0207 d->action_text_foreground_color = new QAction(QIcon::fromTheme(QStringLiteral("format-stroke-color")), i18nc("@action", "Text &Color..."), this); 0208 d->action_text_foreground_color->setIconText(i18nc("@label stroke color", "Color")); 0209 d->richTextActionList.append((d->action_text_foreground_color)); 0210 d->action_text_foreground_color->setObjectName(QStringLiteral("format_text_foreground_color")); 0211 connect(d->action_text_foreground_color, &QAction::triggered, this, [this]() { 0212 Q_D(KRichTextWidget); 0213 d->_k_setTextForegroundColor(); 0214 }); 0215 } else { 0216 d->action_text_foreground_color = nullptr; 0217 } 0218 0219 if (d->richTextSupport & SupportTextBackgroundColor) { 0220 // Background Color 0221 d->action_text_background_color = new QAction(QIcon::fromTheme(QStringLiteral("format-fill-color")), i18nc("@action", "Text &Highlight..."), this); 0222 d->richTextActionList.append((d->action_text_background_color)); 0223 d->action_text_background_color->setObjectName(QStringLiteral("format_text_background_color")); 0224 connect(d->action_text_background_color, &QAction::triggered, this, [this]() { 0225 Q_D(KRichTextWidget); 0226 d->_k_setTextBackgroundColor(); 0227 }); 0228 } else { 0229 d->action_text_background_color = nullptr; 0230 } 0231 0232 if (d->richTextSupport & SupportFontFamily) { 0233 // Font Family 0234 d->action_font_family = new KFontAction(i18nc("@action", "&Font"), this); 0235 d->richTextActionList.append((d->action_font_family)); 0236 d->action_font_family->setObjectName(QStringLiteral("format_font_family")); 0237 connect(d->action_font_family, &KSelectAction::textTriggered, this, &KRichTextWidget::setFontFamily); 0238 } else { 0239 d->action_font_family = nullptr; 0240 } 0241 0242 if (d->richTextSupport & SupportFontSize) { 0243 // Font Size 0244 d->action_font_size = new KFontSizeAction(i18nc("@action", "Font &Size"), this); 0245 d->richTextActionList.append((d->action_font_size)); 0246 d->action_font_size->setObjectName(QStringLiteral("format_font_size")); 0247 connect(d->action_font_size, &KFontSizeAction::fontSizeChanged, this, &KRichTextEdit::setFontSize); 0248 } else { 0249 d->action_font_size = nullptr; 0250 } 0251 0252 if (d->richTextSupport & SupportBold) { 0253 d->action_text_bold = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-bold")), i18nc("@action boldify selected text", "&Bold"), this); 0254 QFont bold; 0255 bold.setBold(true); 0256 d->action_text_bold->setFont(bold); 0257 d->richTextActionList.append((d->action_text_bold)); 0258 d->action_text_bold->setObjectName(QStringLiteral("format_text_bold")); 0259 d->action_text_bold->setShortcut(Qt::CTRL | Qt::Key_B); 0260 connect(d->action_text_bold, &QAction::triggered, this, &KRichTextEdit::setTextBold); 0261 } else { 0262 d->action_text_bold = nullptr; 0263 } 0264 0265 if (d->richTextSupport & SupportItalic) { 0266 d->action_text_italic = 0267 new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-italic")), i18nc("@action italicize selected text", "&Italic"), this); 0268 QFont italic; 0269 italic.setItalic(true); 0270 d->action_text_italic->setFont(italic); 0271 d->richTextActionList.append((d->action_text_italic)); 0272 d->action_text_italic->setObjectName(QStringLiteral("format_text_italic")); 0273 d->action_text_italic->setShortcut(Qt::CTRL | Qt::Key_I); 0274 connect(d->action_text_italic, &QAction::triggered, this, &KRichTextEdit::setTextItalic); 0275 } else { 0276 d->action_text_italic = nullptr; 0277 } 0278 0279 if (d->richTextSupport & SupportUnderline) { 0280 d->action_text_underline = 0281 new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-underline")), i18nc("@action underline selected text", "&Underline"), this); 0282 QFont underline; 0283 underline.setUnderline(true); 0284 d->action_text_underline->setFont(underline); 0285 d->richTextActionList.append((d->action_text_underline)); 0286 d->action_text_underline->setObjectName(QStringLiteral("format_text_underline")); 0287 d->action_text_underline->setShortcut(Qt::CTRL | Qt::Key_U); 0288 connect(d->action_text_underline, &QAction::triggered, this, &KRichTextEdit::setTextUnderline); 0289 } else { 0290 d->action_text_underline = nullptr; 0291 } 0292 0293 if (d->richTextSupport & SupportStrikeOut) { 0294 d->action_text_strikeout = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-strikethrough")), i18nc("@action", "&Strike Out"), this); 0295 QFont strikeout; 0296 strikeout.setStrikeOut(true); 0297 d->action_text_strikeout->setFont(strikeout); 0298 d->richTextActionList.append((d->action_text_strikeout)); 0299 d->action_text_strikeout->setObjectName(QStringLiteral("format_text_strikeout")); 0300 d->action_text_strikeout->setShortcut(Qt::CTRL | Qt::Key_L); 0301 connect(d->action_text_strikeout, &QAction::triggered, this, &KRichTextEdit::setTextStrikeOut); 0302 } else { 0303 d->action_text_strikeout = nullptr; 0304 } 0305 0306 if (d->richTextSupport & SupportAlignment) { 0307 // Alignment 0308 d->action_align_left = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-left")), i18nc("@action", "Align &Left"), this); 0309 d->action_align_left->setIconText(i18nc("@label left justify", "Left")); 0310 d->richTextActionList.append((d->action_align_left)); 0311 d->action_align_left->setObjectName(QStringLiteral("format_align_left")); 0312 connect(d->action_align_left, &QAction::triggered, this, &KRichTextEdit::alignLeft); 0313 0314 d->action_align_center = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-center")), i18nc("@action", "Align &Center"), this); 0315 d->action_align_center->setIconText(i18nc("@label center justify", "Center")); 0316 d->richTextActionList.append((d->action_align_center)); 0317 d->action_align_center->setObjectName(QStringLiteral("format_align_center")); 0318 connect(d->action_align_center, &QAction::triggered, this, &KRichTextEdit::alignCenter); 0319 0320 d->action_align_right = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-right")), i18nc("@action", "Align &Right"), this); 0321 d->action_align_right->setIconText(i18nc("@label right justify", "Right")); 0322 d->richTextActionList.append((d->action_align_right)); 0323 d->action_align_right->setObjectName(QStringLiteral("format_align_right")); 0324 connect(d->action_align_right, &QAction::triggered, this, &KRichTextEdit::alignRight); 0325 0326 d->action_align_justify = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-fill")), i18nc("@action", "&Justify"), this); 0327 d->action_align_justify->setIconText(i18nc("@label justify fill", "Justify")); 0328 d->richTextActionList.append((d->action_align_justify)); 0329 d->action_align_justify->setObjectName(QStringLiteral("format_align_justify")); 0330 connect(d->action_align_justify, &QAction::triggered, this, &KRichTextEdit::alignJustify); 0331 0332 QActionGroup *alignmentGroup = new QActionGroup(this); 0333 alignmentGroup->addAction(d->action_align_left); 0334 alignmentGroup->addAction(d->action_align_center); 0335 alignmentGroup->addAction(d->action_align_right); 0336 alignmentGroup->addAction(d->action_align_justify); 0337 } else { 0338 d->action_align_left = nullptr; 0339 d->action_align_center = nullptr; 0340 d->action_align_right = nullptr; 0341 d->action_align_justify = nullptr; 0342 } 0343 0344 if (d->richTextSupport & SupportDirection) { 0345 d->action_direction_ltr = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-direction-ltr")), i18nc("@action", "Left-to-Right"), this); 0346 d->action_direction_ltr->setIconText(i18nc("@label left-to-right", "Left-to-Right")); 0347 d->richTextActionList.append(d->action_direction_ltr); 0348 d->action_direction_ltr->setObjectName(QStringLiteral("direction_ltr")); 0349 connect(d->action_direction_ltr, &QAction::triggered, this, &KRichTextEdit::makeLeftToRight); 0350 0351 d->action_direction_rtl = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-direction-rtl")), i18nc("@action", "Right-to-Left"), this); 0352 d->action_direction_rtl->setIconText(i18nc("@label right-to-left", "Right-to-Left")); 0353 d->richTextActionList.append(d->action_direction_rtl); 0354 d->action_direction_rtl->setObjectName(QStringLiteral("direction_rtl")); 0355 connect(d->action_direction_rtl, &QAction::triggered, this, &KRichTextEdit::makeRightToLeft); 0356 0357 QActionGroup *directionGroup = new QActionGroup(this); 0358 directionGroup->addAction(d->action_direction_ltr); 0359 directionGroup->addAction(d->action_direction_rtl); 0360 } else { 0361 d->action_direction_ltr = nullptr; 0362 d->action_direction_rtl = nullptr; 0363 } 0364 0365 if (d->richTextSupport & SupportChangeListStyle) { 0366 d->action_list_style = new KSelectAction(QIcon::fromTheme(QStringLiteral("format-list-unordered")), i18nc("@title:menu", "List Style"), this); 0367 QStringList listStyles; 0368 /* clang-format off */ 0369 listStyles << i18nc("@item:inmenu no list style", "None") 0370 << i18nc("@item:inmenu disc list style", "Disc") 0371 << i18nc("@item:inmenu circle list style", "Circle") 0372 << i18nc("@item:inmenu square list style", "Square") 0373 << i18nc("@item:inmenu numbered lists", "123") 0374 << i18nc("@item:inmenu lowercase abc lists", "abc") 0375 << i18nc("@item:inmenu uppercase abc lists", "ABC") 0376 << i18nc("@item:inmenu lower case roman numerals", "i ii iii") 0377 << i18nc("@item:inmenu upper case roman numerals", "I II III"); 0378 /* clang-format on */ 0379 0380 d->action_list_style->setItems(listStyles); 0381 d->action_list_style->setCurrentItem(0); 0382 d->richTextActionList.append((d->action_list_style)); 0383 d->action_list_style->setObjectName(QStringLiteral("format_list_style")); 0384 0385 connect(d->action_list_style, &KSelectAction::indexTriggered, this, [this](int style) { 0386 Q_D(KRichTextWidget); 0387 d->_k_setListStyle(style); 0388 }); 0389 connect(d->action_list_style, &QAction::triggered, this, [d]() { 0390 d->updateMiscActions(); 0391 }); 0392 } else { 0393 d->action_list_style = nullptr; 0394 } 0395 0396 if (d->richTextSupport & SupportIndentLists) { 0397 d->action_list_indent = new QAction(QIcon::fromTheme(QStringLiteral("format-indent-more")), i18nc("@action", "Increase Indent"), this); 0398 d->richTextActionList.append((d->action_list_indent)); 0399 d->action_list_indent->setObjectName(QStringLiteral("format_list_indent_more")); 0400 connect(d->action_list_indent, &QAction::triggered, this, &KRichTextEdit::indentListMore); 0401 connect(d->action_list_indent, &QAction::triggered, this, [d]() { 0402 d->updateMiscActions(); 0403 }); 0404 } else { 0405 d->action_list_indent = nullptr; 0406 } 0407 0408 if (d->richTextSupport & SupportDedentLists) { 0409 d->action_list_dedent = new QAction(QIcon::fromTheme(QStringLiteral("format-indent-less")), i18nc("@action", "Decrease Indent"), this); 0410 d->richTextActionList.append((d->action_list_dedent)); 0411 d->action_list_dedent->setObjectName(QStringLiteral("format_list_indent_less")); 0412 connect(d->action_list_dedent, &QAction::triggered, this, &KRichTextEdit::indentListLess); 0413 connect(d->action_list_dedent, &QAction::triggered, this, [d]() { 0414 d->updateMiscActions(); 0415 }); 0416 } else { 0417 d->action_list_dedent = nullptr; 0418 } 0419 0420 if (d->richTextSupport & SupportRuleLine) { 0421 d->action_insert_horizontal_rule = new QAction(QIcon::fromTheme(QStringLiteral("insert-horizontal-rule")), i18nc("@action", "Insert Rule Line"), this); 0422 d->richTextActionList.append((d->action_insert_horizontal_rule)); 0423 d->action_insert_horizontal_rule->setObjectName(QStringLiteral("insert_horizontal_rule")); 0424 connect(d->action_insert_horizontal_rule, &QAction::triggered, this, &KRichTextEdit::insertHorizontalRule); 0425 } else { 0426 d->action_insert_horizontal_rule = nullptr; 0427 } 0428 0429 if (d->richTextSupport & SupportHyperlinks) { 0430 d->action_manage_link = new QAction(QIcon::fromTheme(QStringLiteral("insert-link")), i18nc("@action", "Link"), this); 0431 d->richTextActionList.append((d->action_manage_link)); 0432 d->action_manage_link->setObjectName(QStringLiteral("manage_link")); 0433 connect(d->action_manage_link, &QAction::triggered, this, [this]() { 0434 Q_D(KRichTextWidget); 0435 d->_k_manageLink(); 0436 }); 0437 } else { 0438 d->action_manage_link = nullptr; 0439 } 0440 0441 if (d->richTextSupport & SupportFormatPainting) { 0442 d->action_format_painter = new KToggleAction(QIcon::fromTheme(QStringLiteral("draw-brush")), i18nc("@action", "Format Painter"), this); 0443 d->richTextActionList.append((d->action_format_painter)); 0444 d->action_format_painter->setObjectName(QStringLiteral("format_painter")); 0445 connect(d->action_format_painter, &QAction::toggled, this, [this](bool state) { 0446 Q_D(KRichTextWidget); 0447 d->_k_formatPainter(state); 0448 }); 0449 } else { 0450 d->action_format_painter = nullptr; 0451 } 0452 0453 if (d->richTextSupport & SupportToPlainText) { 0454 d->action_to_plain_text = new KToggleAction(i18nc("@action", "To Plain Text"), this); 0455 d->richTextActionList.append((d->action_to_plain_text)); 0456 d->action_to_plain_text->setObjectName(QStringLiteral("action_to_plain_text")); 0457 connect(d->action_to_plain_text, &QAction::triggered, this, &KRichTextEdit::switchToPlainText); 0458 } else { 0459 d->action_to_plain_text = nullptr; 0460 } 0461 0462 if (d->richTextSupport & SupportSuperScriptAndSubScript) { 0463 d->action_text_subscript = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-subscript")), i18nc("@action", "Subscript"), this); 0464 d->richTextActionList.append((d->action_text_subscript)); 0465 d->action_text_subscript->setObjectName(QStringLiteral("format_text_subscript")); 0466 connect(d->action_text_subscript, &QAction::triggered, this, &KRichTextEdit::setTextSubScript); 0467 0468 d->action_text_superscript = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-superscript")), i18nc("@action", "Superscript"), this); 0469 d->richTextActionList.append((d->action_text_superscript)); 0470 d->action_text_superscript->setObjectName(QStringLiteral("format_text_superscript")); 0471 connect(d->action_text_superscript, &QAction::triggered, this, &KRichTextEdit::setTextSuperScript); 0472 } else { 0473 d->action_text_subscript = nullptr; 0474 0475 d->action_text_superscript = nullptr; 0476 } 0477 0478 if (d->richTextSupport & SupportHeading) { 0479 // TODO: an icon maybe? 0480 d->action_heading_level = new KSelectAction(i18nc("@title:menu", "Heading Level"), this); 0481 const QStringList headingLevels = {i18nc("@item:inmenu no heading", "Basic text"), 0482 i18nc("@item:inmenu heading level 1 (largest)", "Title"), 0483 i18nc("@item:inmenu heading level 2", "Subtitle"), 0484 i18nc("@item:inmenu heading level 3", "Section"), 0485 i18nc("@item:inmenu heading level 4", "Subsection"), 0486 i18nc("@item:inmenu heading level 5", "Paragraph"), 0487 i18nc("@item:inmenu heading level 6 (smallest)", "Subparagraph")}; 0488 0489 d->action_heading_level->setItems(headingLevels); 0490 d->action_heading_level->setCurrentItem(0); 0491 d->richTextActionList.append(d->action_heading_level); 0492 d->action_heading_level->setObjectName(QStringLiteral("format_heading_level")); 0493 connect(d->action_heading_level, &KSelectAction::indexTriggered, this, [this](int level) { 0494 Q_D(KRichTextWidget); 0495 d->_k_setHeadingLevel(level); 0496 }); 0497 } else { 0498 d->action_heading_level = nullptr; 0499 } 0500 0501 disconnect(this, &QTextEdit::currentCharFormatChanged, this, nullptr); 0502 disconnect(this, &QTextEdit::cursorPositionChanged, this, nullptr); 0503 connect(this, &QTextEdit::currentCharFormatChanged, this, [d](const QTextCharFormat &format) { 0504 d->updateCharFormatActions(format); 0505 }); 0506 connect(this, &QTextEdit::cursorPositionChanged, this, [d]() { 0507 d->updateMiscActions(); 0508 }); 0509 0510 d->updateMiscActions(); 0511 d->updateCharFormatActions(currentCharFormat()); 0512 0513 return d->richTextActionList; 0514 } 0515 0516 void KRichTextWidget::setActionsEnabled(bool enabled) 0517 { 0518 Q_D(KRichTextWidget); 0519 0520 for (QAction *action : std::as_const(d->richTextActionList)) { 0521 action->setEnabled(enabled); 0522 } 0523 d->richTextEnabled = enabled; 0524 } 0525 0526 void KRichTextWidgetPrivate::_k_setListStyle(int index) 0527 { 0528 Q_Q(KRichTextWidget); 0529 0530 q->setListStyle(index); 0531 updateMiscActions(); 0532 } 0533 0534 void KRichTextWidgetPrivate::_k_setHeadingLevel(int level) 0535 { 0536 Q_Q(KRichTextWidget); 0537 0538 q->setHeadingLevel(level); 0539 updateMiscActions(); 0540 } 0541 0542 void KRichTextWidgetPrivate::updateCharFormatActions(const QTextCharFormat &format) 0543 { 0544 Q_Q(KRichTextWidget); 0545 0546 QFont f = format.font(); 0547 0548 if (richTextSupport & KRichTextWidget::SupportFontFamily) { 0549 action_font_family->setFont(f.family()); 0550 } 0551 if (richTextSupport & KRichTextWidget::SupportFontSize) { 0552 if (f.pointSize() > 0) { 0553 action_font_size->setFontSize(f.pointSize()); 0554 } 0555 } 0556 0557 if (richTextSupport & KRichTextWidget::SupportBold) { 0558 action_text_bold->setChecked(f.bold()); 0559 } 0560 0561 if (richTextSupport & KRichTextWidget::SupportItalic) { 0562 action_text_italic->setChecked(f.italic()); 0563 } 0564 0565 if (richTextSupport & KRichTextWidget::SupportUnderline) { 0566 action_text_underline->setChecked(f.underline()); 0567 } 0568 0569 if (richTextSupport & KRichTextWidget::SupportStrikeOut) { 0570 action_text_strikeout->setChecked(f.strikeOut()); 0571 } 0572 0573 if (richTextSupport & KRichTextWidget::SupportSuperScriptAndSubScript) { 0574 QTextCharFormat::VerticalAlignment vAlign = format.verticalAlignment(); 0575 action_text_superscript->setChecked(vAlign == QTextCharFormat::AlignSuperScript); 0576 action_text_subscript->setChecked(vAlign == QTextCharFormat::AlignSubScript); 0577 } 0578 } 0579 0580 void KRichTextWidgetPrivate::updateMiscActions() 0581 { 0582 Q_Q(KRichTextWidget); 0583 0584 if (richTextSupport & KRichTextWidget::SupportAlignment) { 0585 Qt::Alignment a = q->alignment(); 0586 if (a & Qt::AlignLeft) { 0587 action_align_left->setChecked(true); 0588 } else if (a & Qt::AlignHCenter) { 0589 action_align_center->setChecked(true); 0590 } else if (a & Qt::AlignRight) { 0591 action_align_right->setChecked(true); 0592 } else if (a & Qt::AlignJustify) { 0593 action_align_justify->setChecked(true); 0594 } 0595 } 0596 0597 if (richTextSupport & KRichTextWidget::SupportChangeListStyle) { 0598 if (q->textCursor().currentList()) { 0599 action_list_style->setCurrentItem(-q->textCursor().currentList()->format().style()); 0600 } else { 0601 action_list_style->setCurrentItem(0); 0602 } 0603 } 0604 0605 if (richTextSupport & KRichTextWidget::SupportIndentLists) { 0606 if (richTextEnabled) { 0607 action_list_indent->setEnabled(q->canIndentList()); 0608 } else { 0609 action_list_indent->setEnabled(false); 0610 } 0611 } 0612 0613 if (richTextSupport & KRichTextWidget::SupportDedentLists) { 0614 if (richTextEnabled) { 0615 action_list_dedent->setEnabled(q->canDedentList()); 0616 } else { 0617 action_list_dedent->setEnabled(false); 0618 } 0619 } 0620 0621 if (richTextSupport & KRichTextWidget::SupportDirection) { 0622 const Qt::LayoutDirection direction = q->textCursor().blockFormat().layoutDirection(); 0623 action_direction_ltr->setChecked(direction == Qt::LeftToRight); 0624 action_direction_rtl->setChecked(direction == Qt::RightToLeft); 0625 } 0626 0627 if (richTextSupport & KRichTextWidget::SupportHeading) { 0628 action_heading_level->setCurrentItem(q->textCursor().blockFormat().headingLevel()); 0629 } 0630 } 0631 0632 void KRichTextWidgetPrivate::_k_setTextForegroundColor() 0633 { 0634 Q_Q(KRichTextWidget); 0635 0636 const QColor currentColor = q->textColor(); 0637 const QColor defaultColor = KColorScheme(QPalette::Active, KColorScheme::View).foreground().color(); 0638 0639 const QColor selectedColor = QColorDialog::getColor(currentColor.isValid() ? currentColor : defaultColor, q); 0640 0641 if (!selectedColor.isValid() && !currentColor.isValid()) { 0642 q->setTextForegroundColor(defaultColor); 0643 } else if (selectedColor.isValid()) { 0644 q->setTextForegroundColor(selectedColor); 0645 } 0646 } 0647 0648 void KRichTextWidgetPrivate::_k_setTextBackgroundColor() 0649 { 0650 Q_Q(KRichTextWidget); 0651 0652 QTextCharFormat fmt = q->textCursor().charFormat(); 0653 const QColor currentColor = fmt.background().color(); 0654 const QColor defaultColor = KColorScheme(QPalette::Active, KColorScheme::View).foreground().color(); 0655 0656 const QColor selectedColor = QColorDialog::getColor(currentColor.isValid() ? currentColor : defaultColor, q); 0657 0658 if (!selectedColor.isValid() && !currentColor.isValid()) { 0659 q->setTextBackgroundColor(defaultColor); 0660 } else if (selectedColor.isValid()) { 0661 q->setTextBackgroundColor(selectedColor); 0662 } 0663 } 0664 0665 void KRichTextWidgetPrivate::_k_manageLink() 0666 { 0667 Q_Q(KRichTextWidget); 0668 0669 q->selectLinkText(); 0670 KLinkDialog *linkDialog = new KLinkDialog(q); 0671 linkDialog->setLinkText(q->currentLinkText()); 0672 linkDialog->setLinkUrl(q->currentLinkUrl()); 0673 linkDialog->setAttribute(Qt::WA_DeleteOnClose); 0674 0675 QObject::connect(linkDialog, &QDialog::accepted, linkDialog, [linkDialog, this]() { 0676 Q_Q(KRichTextWidget); 0677 q->updateLink(linkDialog->linkUrl(), linkDialog->linkText()); 0678 }); 0679 0680 linkDialog->show(); 0681 } 0682 0683 void KRichTextWidget::mouseReleaseEvent(QMouseEvent *event) 0684 { 0685 Q_D(KRichTextWidget); 0686 0687 if (d->painterActive) { 0688 // If the painter is active, paint the selection with the 0689 // correct format. 0690 if (textCursor().hasSelection()) { 0691 QTextCursor c = textCursor(); 0692 c.setCharFormat(d->painterFormat); 0693 setTextCursor(c); 0694 } 0695 d->painterActive = false; 0696 d->action_format_painter->setChecked(false); 0697 } 0698 KRichTextEdit::mouseReleaseEvent(event); 0699 } 0700 0701 void KRichTextWidgetPrivate::_k_formatPainter(bool active) 0702 { 0703 Q_Q(KRichTextWidget); 0704 0705 if (active) { 0706 painterFormat = q->currentCharFormat(); 0707 painterActive = true; 0708 q->viewport()->setCursor(QCursor(QIcon::fromTheme(QStringLiteral("draw-brush")).pixmap(32, 32), 0, 32)); 0709 } else { 0710 painterFormat = QTextCharFormat(); 0711 painterActive = false; 0712 q->viewport()->setCursor(Qt::IBeamCursor); 0713 } 0714 } 0715 0716 void KRichTextWidget::updateActionStates() 0717 { 0718 Q_D(KRichTextWidget); 0719 0720 d->updateMiscActions(); 0721 d->updateCharFormatActions(currentCharFormat()); 0722 } 0723 0724 #include "moc_krichtextwidget.cpp"