File indexing completed on 2024-05-19 05:21:43

0001 /*
0002    SPDX-FileCopyrightText: 2015-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "richtextcomposeractions.h"
0008 #include "richtextcomposercontroler.h"
0009 #include "tableactionmenu.h"
0010 #include <KActionCollection>
0011 #include <KFontAction>
0012 #include <KFontSizeAction>
0013 #include <KLocalizedString>
0014 #include <KToggleAction>
0015 #include <QActionGroup>
0016 #include <QTextCharFormat>
0017 #include <QTextList>
0018 #include <TextEmoticonsWidgets/EmoticonTextEditAction>
0019 
0020 using namespace KPIMTextEdit;
0021 
0022 class Q_DECL_HIDDEN RichTextComposerActions::RichTextComposerActionsPrivate
0023 {
0024 public:
0025     RichTextComposerActionsPrivate(KPIMTextEdit::RichTextComposerControler *controller)
0026         : composerControler(controller)
0027     {
0028     }
0029 
0030     QList<QAction *> richTextActionList;
0031 
0032     KPIMTextEdit::RichTextComposerControler *const composerControler;
0033     KToggleAction *action_align_left = nullptr;
0034     KToggleAction *action_align_right = nullptr;
0035     KToggleAction *action_align_center = nullptr;
0036     KToggleAction *action_align_justify = nullptr;
0037 
0038     KToggleAction *action_direction_ltr = nullptr;
0039     KToggleAction *action_direction_rtl = nullptr;
0040 
0041     KToggleAction *action_text_superscript = nullptr;
0042     KToggleAction *action_text_subscript = nullptr;
0043 
0044     KToggleAction *action_text_bold = nullptr;
0045     KToggleAction *action_text_italic = nullptr;
0046     KToggleAction *action_text_underline = nullptr;
0047     KToggleAction *action_text_strikeout = nullptr;
0048 
0049     KFontAction *action_font_family = nullptr;
0050     KFontSizeAction *action_font_size = nullptr;
0051 
0052     QAction *action_insert_horizontal_rule = nullptr;
0053     QAction *action_text_foreground_color = nullptr;
0054     QAction *action_text_background_color = nullptr;
0055     QAction *action_manage_link = nullptr;
0056 
0057     QAction *action_list_indent = nullptr;
0058     QAction *action_list_dedent = nullptr;
0059 
0060     KSelectAction *action_list_style = nullptr;
0061 
0062     QAction *action_paste_quotation = nullptr;
0063     QAction *action_add_quote_chars = nullptr;
0064     QAction *action_remove_quote_chars = nullptr;
0065     QAction *action_paste_without_formatting = nullptr;
0066 
0067     QAction *action_add_image = nullptr;
0068     TextEmoticonsWidgets::EmoticonTextEditAction *action_add_emoticon = nullptr;
0069     QAction *action_insert_html = nullptr;
0070     KPIMTextEdit::TableActionMenu *action_add_table = nullptr;
0071     QAction *action_format_reset = nullptr;
0072 
0073     KToggleAction *action_format_painter = nullptr;
0074     KSelectAction *action_heading_level = nullptr;
0075     KToggleAction *action_list_checkbox = nullptr;
0076 
0077     bool richTextEnabled = false;
0078 };
0079 
0080 RichTextComposerActions::RichTextComposerActions(KPIMTextEdit::RichTextComposerControler *controller, QObject *parent)
0081     : QObject(parent)
0082     , d(new RichTextComposerActions::RichTextComposerActionsPrivate(controller))
0083 {
0084 }
0085 
0086 RichTextComposerActions::~RichTextComposerActions() = default;
0087 
0088 QList<QAction *> RichTextComposerActions::richTextActionList() const
0089 {
0090     return d->richTextActionList;
0091 }
0092 
0093 int RichTextComposerActions::numberOfActions() const
0094 {
0095     return d->richTextActionList.count();
0096 }
0097 
0098 void RichTextComposerActions::createActions(KActionCollection *ac)
0099 {
0100     // Alignment
0101     d->action_align_left = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-left")), i18nc("@action", "Align &Left"), this);
0102     d->action_align_left->setIconText(i18nc("@label left justify", "Left"));
0103     d->richTextActionList.append((d->action_align_left));
0104     d->action_align_left->setObjectName(QLatin1StringView("format_align_left"));
0105     connect(d->action_align_left, &KToggleAction::triggered, d->composerControler, &RichTextComposerControler::alignLeft);
0106     if (ac) {
0107         ac->addAction(QStringLiteral("format_align_left"), d->action_align_left);
0108     }
0109 
0110     d->action_align_center = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-center")), i18nc("@action", "Align &Center"), this);
0111     d->action_align_center->setIconText(i18nc("@label center justify", "Center"));
0112     d->richTextActionList.append((d->action_align_center));
0113     d->action_align_center->setObjectName(QLatin1StringView("format_align_center"));
0114     connect(d->action_align_center, &KToggleAction::triggered, d->composerControler, &RichTextComposerControler::alignCenter);
0115     if (ac) {
0116         ac->addAction(QStringLiteral("format_align_center"), d->action_align_center);
0117     }
0118 
0119     d->action_align_right = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-right")), i18nc("@action", "Align &Right"), this);
0120     d->action_align_right->setIconText(i18nc("@label right justify", "Right"));
0121     d->richTextActionList.append((d->action_align_right));
0122     d->action_align_right->setObjectName(QLatin1StringView("format_align_right"));
0123     connect(d->action_align_right, &KToggleAction::triggered, d->composerControler, &RichTextComposerControler::alignRight);
0124     if (ac) {
0125         ac->addAction(QStringLiteral("format_align_right"), d->action_align_right);
0126     }
0127 
0128     d->action_align_justify = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-fill")), i18nc("@action", "&Justify"), this);
0129     d->action_align_justify->setIconText(i18nc("@label justify fill", "Justify"));
0130     d->richTextActionList.append((d->action_align_justify));
0131     d->action_align_justify->setObjectName(QLatin1StringView("format_align_justify"));
0132     connect(d->action_align_justify, &KToggleAction::triggered, d->composerControler, &RichTextComposerControler::alignJustify);
0133     if (ac) {
0134         ac->addAction(QStringLiteral("format_align_justify"), d->action_align_justify);
0135     }
0136 
0137     auto alignmentGroup = new QActionGroup(this);
0138     alignmentGroup->addAction(d->action_align_left);
0139     alignmentGroup->addAction(d->action_align_center);
0140     alignmentGroup->addAction(d->action_align_right);
0141     alignmentGroup->addAction(d->action_align_justify);
0142 
0143     // Align text
0144     d->action_direction_ltr = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-direction-ltr")), i18nc("@action", "Left-to-Right"), this);
0145     d->action_direction_ltr->setIconText(i18nc("@label left-to-right", "Left-to-Right"));
0146     d->richTextActionList.append(d->action_direction_ltr);
0147     d->action_direction_ltr->setObjectName(QLatin1StringView("direction_ltr"));
0148     connect(d->action_direction_ltr, &KToggleAction::triggered, d->composerControler, &RichTextComposerControler::makeLeftToRight);
0149     if (ac) {
0150         ac->addAction(QStringLiteral("direction_ltr"), d->action_direction_ltr);
0151     }
0152 
0153     d->action_direction_rtl = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-direction-rtl")), i18nc("@action", "Right-to-Left"), this);
0154     d->action_direction_rtl->setIconText(i18nc("@label right-to-left", "Right-to-Left"));
0155     d->richTextActionList.append(d->action_direction_rtl);
0156     d->action_direction_rtl->setObjectName(QLatin1StringView("direction_rtl"));
0157     connect(d->action_direction_rtl, &KToggleAction::triggered, d->composerControler, &RichTextComposerControler::makeRightToLeft);
0158     if (ac) {
0159         ac->addAction(QStringLiteral("direction_rtl"), d->action_direction_rtl);
0160     }
0161 
0162     auto directionGroup = new QActionGroup(this);
0163     directionGroup->addAction(d->action_direction_ltr);
0164     directionGroup->addAction(d->action_direction_rtl);
0165 
0166     // Sub/Super script
0167     d->action_text_subscript = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-subscript")), i18nc("@action", "Subscript"), this);
0168     d->richTextActionList.append((d->action_text_subscript));
0169     d->action_text_subscript->setObjectName(QLatin1StringView("format_text_subscript"));
0170     connect(d->action_text_subscript, &KToggleAction::triggered, d->composerControler, &RichTextComposerControler::setTextSubScript);
0171     if (ac) {
0172         ac->addAction(QStringLiteral("format_text_subscript"), d->action_text_subscript);
0173     }
0174 
0175     d->action_text_superscript = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-superscript")), i18nc("@action", "Superscript"), this);
0176     d->richTextActionList.append((d->action_text_superscript));
0177     d->action_text_superscript->setObjectName(QLatin1StringView("format_text_superscript"));
0178     connect(d->action_text_superscript, &KToggleAction::triggered, d->composerControler, &RichTextComposerControler::setTextSuperScript);
0179     if (ac) {
0180         ac->addAction(QStringLiteral("format_text_superscript"), d->action_text_superscript);
0181     }
0182 
0183     d->action_text_bold = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-bold")), i18nc("@action boldify selected text", "&Bold"), this);
0184     QFont bold;
0185     bold.setBold(true);
0186     d->action_text_bold->setFont(bold);
0187     d->richTextActionList.append((d->action_text_bold));
0188     d->action_text_bold->setObjectName(QLatin1StringView("format_text_bold"));
0189     if (ac) {
0190         ac->addAction(QStringLiteral("format_text_bold"), d->action_text_bold);
0191         ac->setDefaultShortcut(d->action_text_bold, Qt::CTRL | Qt::Key_B);
0192     }
0193     connect(d->action_text_bold, &KToggleAction::triggered, d->composerControler, &RichTextComposerControler::setTextBold);
0194 
0195     d->action_text_italic =
0196         new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-italic")), i18nc("@action italicize selected text", "&Italic"), this);
0197     QFont italic;
0198     italic.setItalic(true);
0199     d->action_text_italic->setFont(italic);
0200     d->richTextActionList.append((d->action_text_italic));
0201     d->action_text_italic->setObjectName(QLatin1StringView("format_text_italic"));
0202     if (ac) {
0203         ac->addAction(QStringLiteral("format_text_italic"), d->action_text_italic);
0204         ac->setDefaultShortcut(d->action_text_italic, Qt::CTRL | Qt::Key_I);
0205     }
0206     connect(d->action_text_italic, &KToggleAction::triggered, d->composerControler, &RichTextComposerControler::setTextItalic);
0207 
0208     d->action_text_underline =
0209         new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-underline")), i18nc("@action underline selected text", "&Underline"), this);
0210     QFont underline;
0211     underline.setUnderline(true);
0212     d->action_text_underline->setFont(underline);
0213     d->richTextActionList.append((d->action_text_underline));
0214     d->action_text_underline->setObjectName(QLatin1StringView("format_text_underline"));
0215     if (ac) {
0216         ac->addAction(QStringLiteral("format_text_underline"), d->action_text_underline);
0217         ac->setDefaultShortcut(d->action_text_underline, Qt::CTRL | Qt::Key_U);
0218     }
0219     connect(d->action_text_underline, &KToggleAction::triggered, d->composerControler, &RichTextComposerControler::setTextUnderline);
0220 
0221     d->action_text_strikeout = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-strikethrough")), i18nc("@action", "&Strike Out"), this);
0222     QFont strikeout;
0223     strikeout.setStrikeOut(true);
0224     d->action_text_strikeout->setFont(strikeout);
0225     d->richTextActionList.append((d->action_text_strikeout));
0226     if (ac) {
0227         ac->addAction(QStringLiteral("format_text_strikeout"), d->action_text_strikeout);
0228     }
0229     d->action_text_strikeout->setObjectName(QLatin1StringView("format_text_strikeout"));
0230     if (ac) {
0231         ac->setDefaultShortcut(d->action_text_strikeout, Qt::CTRL | Qt::Key_L);
0232     }
0233     connect(d->action_text_strikeout, &KToggleAction::triggered, d->composerControler, &RichTextComposerControler::setTextStrikeOut);
0234 
0235     // Font Family
0236     d->action_font_family = new KFontAction(i18nc("@action", "&Font"), this);
0237     d->richTextActionList.append((d->action_font_family));
0238     d->action_font_family->setObjectName(QLatin1StringView("format_font_family"));
0239     if (ac) {
0240         ac->addAction(QStringLiteral("format_font_family"), d->action_font_family);
0241     }
0242     connect(d->action_font_family, &KFontAction::textTriggered, d->composerControler, &RichTextComposerControler::setFontFamily);
0243 
0244     // Font Size
0245     d->action_font_size = new KFontSizeAction(i18nc("@action", "Font &Size"), this);
0246     d->richTextActionList.append((d->action_font_size));
0247     d->action_font_size->setObjectName(QLatin1StringView("format_font_size"));
0248     if (ac) {
0249         ac->addAction(QStringLiteral("format_font_size"), d->action_font_size);
0250     }
0251     connect(d->action_font_size, &KFontSizeAction::fontSizeChanged, d->composerControler, &RichTextComposerControler::setFontSize);
0252 
0253     d->action_insert_horizontal_rule = new QAction(QIcon::fromTheme(QStringLiteral("insert-horizontal-rule")), i18nc("@action", "Insert Rule Line"), this);
0254     d->richTextActionList.append((d->action_insert_horizontal_rule));
0255     d->action_insert_horizontal_rule->setObjectName(QLatin1StringView("insert_horizontal_rule"));
0256     if (ac) {
0257         ac->addAction(QStringLiteral("insert_horizontal_rule"), d->action_insert_horizontal_rule);
0258     }
0259     connect(d->action_insert_horizontal_rule, &QAction::triggered, d->composerControler, &RichTextComposerControler::insertHorizontalRule);
0260 
0261     // Foreground Color
0262     d->action_text_foreground_color = new QAction(QIcon::fromTheme(QStringLiteral("format-stroke-color")), i18nc("@action", "Text &Color..."), this);
0263     d->action_text_foreground_color->setIconText(i18nc("@label stroke color", "Color"));
0264     d->richTextActionList.append((d->action_text_foreground_color));
0265     d->action_text_foreground_color->setObjectName(QLatin1StringView("format_text_foreground_color"));
0266     if (ac) {
0267         ac->addAction(QStringLiteral("format_text_foreground_color"), d->action_text_foreground_color);
0268     }
0269     connect(d->action_text_foreground_color, &QAction::triggered, d->composerControler, &RichTextComposerControler::setChangeTextForegroundColor);
0270     // Background Color
0271     d->action_text_background_color = new QAction(QIcon::fromTheme(QStringLiteral("format-fill-color")), i18nc("@action", "Text &Highlight..."), this);
0272     d->richTextActionList.append((d->action_text_background_color));
0273     if (ac) {
0274         ac->addAction(QStringLiteral("format_text_background_color"), d->action_text_background_color);
0275     }
0276     d->action_text_background_color->setObjectName(QLatin1StringView("format_text_background_color"));
0277     connect(d->action_text_background_color, &QAction::triggered, d->composerControler, &RichTextComposerControler::setChangeTextBackgroundColor);
0278 
0279     d->action_manage_link = new QAction(QIcon::fromTheme(QStringLiteral("insert-link")), i18nc("@action", "Link"), this);
0280     d->richTextActionList.append((d->action_manage_link));
0281     d->action_manage_link->setObjectName(QLatin1StringView("manage_link"));
0282     if (ac) {
0283         ac->addAction(QStringLiteral("manage_link"), d->action_manage_link);
0284     }
0285     connect(d->action_manage_link, &QAction::triggered, d->composerControler, &RichTextComposerControler::manageLink);
0286 
0287     d->action_list_indent = new QAction(QIcon::fromTheme(QStringLiteral("format-indent-more")), i18nc("@action", "Increase List Level"), this);
0288     d->richTextActionList.append((d->action_list_indent));
0289     d->action_list_indent->setObjectName(QLatin1StringView("format_list_indent_more"));
0290     if (ac) {
0291         ac->addAction(QStringLiteral("format_list_indent_more"), d->action_list_indent);
0292     }
0293     connect(d->action_list_indent, &QAction::triggered, d->composerControler, &RichTextComposerControler::indentListMore);
0294     connect(d->action_list_indent, &QAction::triggered, this, &RichTextComposerActions::slotUpdateMiscActions);
0295     d->action_list_dedent = new QAction(QIcon::fromTheme(QStringLiteral("format-indent-less")), i18nc("@action", "Decrease List Level"), this);
0296     d->richTextActionList.append((d->action_list_dedent));
0297     d->action_list_dedent->setObjectName(QLatin1StringView("format_list_indent_less"));
0298     if (ac) {
0299         ac->addAction(QStringLiteral("format_list_indent_less"), d->action_list_dedent);
0300     }
0301     connect(d->action_list_dedent, &QAction::triggered, d->composerControler, &RichTextComposerControler::indentListLess);
0302     connect(d->action_list_dedent, &QAction::triggered, this, &RichTextComposerActions::slotUpdateMiscActions);
0303 
0304     d->action_list_style = new KSelectAction(QIcon::fromTheme(QStringLiteral("format-list-unordered")), i18nc("@title:menu", "List Style"), this);
0305     QStringList listStyles;
0306     listStyles << i18nc("@item:inmenu no list style", "None") << i18nc("@item:inmenu disc list style", "Disc")
0307                << i18nc("@item:inmenu circle list style", "Circle") << i18nc("@item:inmenu square list style", "Square")
0308                << i18nc("@item:inmenu numbered lists", "123") << i18nc("@item:inmenu lowercase abc lists", "abc")
0309                << i18nc("@item:inmenu uppercase abc lists", "ABC") << i18nc("@item:inmenu lower case roman numerals", "i ii iii")
0310                << i18nc("@item:inmenu upper case roman numerals", "I II III");
0311 
0312     d->action_list_style->setItems(listStyles);
0313     d->action_list_style->setCurrentItem(0);
0314     d->richTextActionList.append((d->action_list_style));
0315     d->action_list_style->setObjectName(QLatin1StringView("format_list_style"));
0316     if (ac) {
0317         ac->addAction(QStringLiteral("format_list_style"), d->action_list_style);
0318     }
0319     connect(d->action_list_style, &KSelectAction::indexTriggered, this, &RichTextComposerActions::setListStyle);
0320     connect(d->action_list_style, &QAction::triggered, this, &RichTextComposerActions::slotUpdateMiscActions);
0321     d->action_paste_quotation = new QAction(i18n("Pa&ste as Quotation"), this);
0322     d->action_paste_quotation->setObjectName(QLatin1StringView("paste_quoted"));
0323     if (ac) {
0324         ac->addAction(QStringLiteral("paste_quoted"), d->action_paste_quotation);
0325         ac->setDefaultShortcut(d->action_paste_quotation, QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_O));
0326     }
0327     connect(d->action_paste_quotation, &QAction::triggered, d->composerControler, &RichTextComposerControler::slotPasteAsQuotation);
0328 
0329     d->action_add_quote_chars = new QAction(i18n("Add &Quote Characters"), this);
0330     d->action_add_quote_chars->setObjectName(QLatin1StringView("tools_quote"));
0331     if (ac) {
0332         ac->addAction(QStringLiteral("tools_quote"), d->action_add_quote_chars);
0333     }
0334     connect(d->action_add_quote_chars, &QAction::triggered, d->composerControler, &RichTextComposerControler::slotAddQuotes);
0335 
0336     d->action_remove_quote_chars = new QAction(i18n("Re&move Quote Characters"), this);
0337     d->action_remove_quote_chars->setObjectName(QLatin1StringView("tools_unquote"));
0338     connect(d->action_remove_quote_chars, &QAction::triggered, d->composerControler, &RichTextComposerControler::slotRemoveQuotes);
0339     if (ac) {
0340         ac->addAction(QStringLiteral("tools_unquote"), d->action_remove_quote_chars);
0341     }
0342 
0343     d->action_paste_without_formatting = new QAction(i18n("Paste Without Formatting"), this);
0344     d->action_paste_without_formatting->setObjectName(QLatin1StringView("paste_without_formatting"));
0345     if (ac) {
0346         ac->addAction(QStringLiteral("paste_without_formatting"), d->action_paste_without_formatting);
0347         ac->setDefaultShortcut(d->action_paste_without_formatting, QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_V));
0348     }
0349     connect(d->action_paste_without_formatting, &QAction::triggered, d->composerControler, &RichTextComposerControler::slotPasteWithoutFormatting);
0350 
0351     d->action_add_image = new QAction(QIcon::fromTheme(QStringLiteral("insert-image")), i18n("Add Image"), this);
0352     d->action_add_image->setObjectName(QLatin1StringView("add_image"));
0353     if (ac) {
0354         ac->addAction(QStringLiteral("add_image"), d->action_add_image);
0355     }
0356     connect(d->action_add_image, &QAction::triggered, d->composerControler, &RichTextComposerControler::slotAddImage);
0357     d->richTextActionList.append(d->action_add_image);
0358 
0359     d->action_add_emoticon = new TextEmoticonsWidgets::EmoticonTextEditAction(this);
0360     d->action_add_emoticon->setObjectName(QLatin1StringView("add_emoticon"));
0361     if (ac) {
0362         ac->addAction(QStringLiteral("add_emoticon"), d->action_add_emoticon);
0363     }
0364     // Don't add to d->richTextActionList as we want to use it when we use plain text email too
0365     connect(d->action_add_emoticon,
0366             &TextEmoticonsWidgets::EmoticonTextEditAction::insertEmoticon,
0367             d->composerControler->richTextComposer(),
0368             &RichTextComposer::insertEmoticon);
0369 
0370     d->action_insert_html = new QAction(i18n("Insert HTML"), this);
0371     d->action_insert_html->setObjectName(QLatin1StringView("insert_html"));
0372     if (ac) {
0373         ac->addAction(QStringLiteral("insert_html"), d->action_insert_html);
0374     }
0375     connect(d->action_insert_html, &QAction::triggered, d->composerControler, &RichTextComposerControler::slotInsertHtml);
0376     d->richTextActionList.append(d->action_insert_html);
0377 
0378     d->action_add_table = new KPIMTextEdit::TableActionMenu(d->composerControler->richTextComposer());
0379     d->action_add_table->setIcon(QIcon::fromTheme(QStringLiteral("insert-table")));
0380     d->action_add_table->setText(i18n("Table"));
0381     d->action_add_table->setPopupMode(QToolButton::InstantPopup);
0382 
0383     d->action_add_table->setObjectName(QLatin1StringView("insert_table"));
0384     d->richTextActionList.append(d->action_add_table);
0385     if (ac) {
0386         ac->addAction(QStringLiteral("insert_table"), d->action_add_table);
0387     }
0388 
0389     d->action_format_reset = new QAction(QIcon::fromTheme(QStringLiteral("draw-eraser")), i18n("Reset Font Settings"), this);
0390     d->action_format_reset->setIconText(i18n("Reset Font"));
0391     d->action_format_reset->setObjectName(QLatin1StringView("format_reset"));
0392     connect(d->action_format_reset, &QAction::triggered, d->composerControler, &RichTextComposerControler::slotFormatReset);
0393     if (ac) {
0394         ac->addAction(QStringLiteral("format_reset"), d->action_format_reset);
0395     }
0396     d->richTextActionList.append(d->action_format_reset);
0397 
0398     d->action_format_painter = new KToggleAction(QIcon::fromTheme(QStringLiteral("draw-brush")), i18nc("@action", "Format Painter"), this);
0399     d->richTextActionList.append(d->action_format_painter);
0400     d->action_format_painter->setObjectName(QLatin1StringView("format_painter"));
0401     if (ac) {
0402         ac->addAction(QStringLiteral("format_painter"), d->action_format_painter);
0403     }
0404     connect(d->action_format_painter, &QAction::toggled, d->composerControler, &RichTextComposerControler::slotFormatPainter);
0405 
0406     d->action_heading_level = new KSelectAction(i18nc("@title:menu", "Heading Level"), this);
0407     const QStringList headingLevels = {i18nc("@item:inmenu no heading", "Basic text"),
0408                                        i18nc("@item:inmenu heading level 1 (largest)", "Title"),
0409                                        i18nc("@item:inmenu heading level 2", "Subtitle"),
0410                                        i18nc("@item:inmenu heading level 3", "Section"),
0411                                        i18nc("@item:inmenu heading level 4", "Subsection"),
0412                                        i18nc("@item:inmenu heading level 5", "Paragraph"),
0413                                        i18nc("@item:inmenu heading level 6 (smallest)", "Subparagraph")};
0414 
0415     d->action_heading_level->setItems(headingLevels);
0416     d->action_heading_level->setCurrentItem(0);
0417     d->richTextActionList.append(d->action_heading_level);
0418     d->action_heading_level->setObjectName(QLatin1StringView("format_heading_level"));
0419     connect(d->action_heading_level, &KSelectAction::indexTriggered, this, &RichTextComposerActions::setHeadingLevel);
0420     if (ac) {
0421         ac->addAction(QStringLiteral("format_heading_level"), d->action_heading_level);
0422     }
0423 
0424     d->action_list_checkbox = new KToggleAction(QIcon::fromTheme(QStringLiteral("checkbox")), i18nc("@action", "Checkbox"), this);
0425     d->richTextActionList.append(d->action_list_checkbox);
0426     d->action_list_checkbox->setObjectName(QLatin1StringView("format_list_checkbox"));
0427     connect(d->action_list_checkbox, &KToggleAction::toggled, d->composerControler, &RichTextComposerControler::addCheckbox);
0428     if (ac) {
0429         ac->addAction(QStringLiteral("format_list_checkbox"), d->action_list_checkbox);
0430     }
0431 
0432     disconnect(d->composerControler->richTextComposer(), &QTextEdit::currentCharFormatChanged, this, &RichTextComposerActions::slotUpdateCharFormatActions);
0433     disconnect(d->composerControler->richTextComposer(), &QTextEdit::cursorPositionChanged, this, &RichTextComposerActions::slotUpdateMiscActions);
0434 
0435     connect(d->composerControler->richTextComposer(), &QTextEdit::currentCharFormatChanged, this, &RichTextComposerActions::slotUpdateCharFormatActions);
0436     connect(d->composerControler->richTextComposer(), &QTextEdit::cursorPositionChanged, this, &RichTextComposerActions::slotUpdateMiscActions);
0437 
0438     updateActionStates();
0439 }
0440 
0441 void RichTextComposerActions::updateActionStates()
0442 {
0443     slotUpdateMiscActions();
0444     slotUpdateCharFormatActions(d->composerControler->richTextComposer()->currentCharFormat());
0445 }
0446 
0447 void RichTextComposerActions::setHeadingLevel(int level)
0448 {
0449     d->composerControler->setHeadingLevel(level);
0450     slotUpdateMiscActions();
0451 }
0452 
0453 void RichTextComposerActions::setListStyle(int _styleindex)
0454 {
0455     d->composerControler->setListStyle(_styleindex);
0456     slotUpdateMiscActions();
0457 }
0458 
0459 void RichTextComposerActions::setActionsEnabled(bool enabled)
0460 {
0461     for (QAction *action : std::as_const(d->richTextActionList)) {
0462         action->setEnabled(enabled);
0463     }
0464     d->richTextEnabled = enabled;
0465 }
0466 
0467 void RichTextComposerActions::slotUpdateCharFormatActions(const QTextCharFormat &format)
0468 {
0469     QFont f = format.font();
0470 
0471     d->action_font_family->setFont(f.family());
0472     if (f.pointSize() > 0) {
0473         d->action_font_size->setFontSize(f.pointSize());
0474     }
0475     d->action_text_bold->setChecked(f.bold());
0476     d->action_text_italic->setChecked(f.italic());
0477     d->action_text_underline->setChecked(f.underline());
0478     d->action_text_strikeout->setChecked(f.strikeOut());
0479     const QTextCharFormat::VerticalAlignment vAlign = format.verticalAlignment();
0480     d->action_text_superscript->setChecked(vAlign == QTextCharFormat::AlignSuperScript);
0481     d->action_text_subscript->setChecked(vAlign == QTextCharFormat::AlignSubScript);
0482 }
0483 
0484 void RichTextComposerActions::slotUpdateMiscActions()
0485 {
0486     const RichTextComposer *richTextComposer = d->composerControler->richTextComposer();
0487     const Qt::Alignment a = richTextComposer->alignment();
0488     if (a & Qt::AlignLeft) {
0489         d->action_align_left->setChecked(true);
0490     } else if (a & Qt::AlignHCenter) {
0491         d->action_align_center->setChecked(true);
0492     } else if (a & Qt::AlignRight) {
0493         d->action_align_right->setChecked(true);
0494     } else if (a & Qt::AlignJustify) {
0495         d->action_align_justify->setChecked(true);
0496     }
0497     if (richTextComposer->textCursor().currentList()) {
0498         d->action_list_style->setCurrentItem(-richTextComposer->textCursor().currentList()->format().style());
0499     } else {
0500         d->action_list_style->setCurrentItem(0);
0501     }
0502     if (d->richTextEnabled) {
0503         d->action_list_indent->setEnabled(d->composerControler->canIndentList());
0504     } else {
0505         d->action_list_indent->setEnabled(false);
0506     }
0507     if (d->richTextEnabled) {
0508         d->action_list_dedent->setEnabled(d->composerControler->canDedentList());
0509     } else {
0510         d->action_list_dedent->setEnabled(false);
0511     }
0512 
0513     const Qt::LayoutDirection direction = richTextComposer->textCursor().blockFormat().layoutDirection();
0514     d->action_direction_ltr->setChecked(direction == Qt::LeftToRight);
0515     d->action_direction_rtl->setChecked(direction == Qt::RightToLeft);
0516     d->action_heading_level->setCurrentItem(richTextComposer->textCursor().blockFormat().headingLevel());
0517     d->action_list_checkbox->setChecked(richTextComposer->textCursor().blockFormat().marker() != QTextBlockFormat::MarkerType::NoMarker);
0518 }
0519 
0520 void RichTextComposerActions::uncheckActionFormatPainter()
0521 {
0522     d->action_format_painter->setChecked(false);
0523 }
0524 
0525 void RichTextComposerActions::textModeChanged(KPIMTextEdit::RichTextComposer::Mode mode)
0526 {
0527     if (d->action_add_table) {
0528         d->action_add_table->setRichTextMode(mode == KPIMTextEdit::RichTextComposer::Rich);
0529     }
0530 }
0531 
0532 #include "moc_richtextcomposeractions.cpp"