1 /*******************************************************************
2  KNotes -- Notes for the KDE project
3 
4  SPDX-FileCopyrightText: 1997-2013 The KNotes Developers
5 
6  SPDX-License-Identifier: GPL-2.0-or-later
7 *******************************************************************/
8 
9 #include "knoteedit.h"
10 #include "editor/noteeditorutils.h"
11 #include "notes/knote.h"
12 
13 #include <KPIMTextEdit/EditorUtil>
14 
15 #include <PimCommon/KActionMenuChangeCase>
16 
17 #include <KActionCollection>
18 #include <KFontAction>
19 #include <KFontSizeAction>
20 #include <KLocalizedString>
21 #include <KToggleAction>
22 
23 #include <QColorDialog>
24 #include <QIcon>
25 #include <QMenu>
26 
27 static const short ICON_SIZE = 10;
28 
KNoteEdit(KActionCollection * actions,QWidget * parent)29 KNoteEdit::KNoteEdit(KActionCollection *actions, QWidget *parent)
30     : KTextEdit(parent)
31     , m_note(nullptr)
32     , m_actions(actions)
33 {
34     setAcceptDrops(true);
35     setWordWrapMode(QTextOption::WordWrap);
36     setLineWrapMode(WidgetWidth);
37     if (acceptRichText()) {
38         setAutoFormatting(AutoAll);
39     } else {
40         setAutoFormatting(AutoNone);
41     }
42 
43     // create the actions modifying the text format
44     m_textBold = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-bold")), i18n("Bold"), this);
45     actions->addAction(QStringLiteral("format_bold"), m_textBold);
46     actions->setDefaultShortcut(m_textBold, QKeySequence(Qt::CTRL | Qt::Key_B));
47     m_textItalic = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-italic")), i18n("Italic"), this);
48     actions->addAction(QStringLiteral("format_italic"), m_textItalic);
49     actions->setDefaultShortcut(m_textItalic, QKeySequence(Qt::CTRL | Qt::Key_I));
50     m_textUnderline = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-underline")), i18n("Underline"), this);
51     actions->addAction(QStringLiteral("format_underline"), m_textUnderline);
52     actions->setDefaultShortcut(m_textUnderline, QKeySequence(Qt::CTRL | Qt::Key_U));
53     m_textStrikeOut = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-strikethrough")), i18n("Strike Out"), this);
54     actions->addAction(QStringLiteral("format_strikeout"), m_textStrikeOut);
55     actions->setDefaultShortcut(m_textStrikeOut, QKeySequence(Qt::CTRL | Qt::Key_S));
56 
57     connect(m_textBold, &KToggleAction::toggled, this, &KNoteEdit::textBold);
58     connect(m_textItalic, &KToggleAction::toggled, this, &KNoteEdit::setFontItalic);
59     connect(m_textUnderline, &KToggleAction::toggled, this, &KNoteEdit::setFontUnderline);
60     connect(m_textStrikeOut, &KToggleAction::toggled, this, &KNoteEdit::textStrikeOut);
61 
62     m_textAlignLeft = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-left")), i18n("Align Left"), this);
63     actions->addAction(QStringLiteral("format_alignleft"), m_textAlignLeft);
64     connect(m_textAlignLeft, &KToggleAction::triggered, this, &KNoteEdit::textAlignLeft);
65     actions->setDefaultShortcut(m_textAlignLeft, QKeySequence(Qt::ALT | Qt::Key_L));
66     m_textAlignLeft->setChecked(true); // just a dummy, will be updated later
67     m_textAlignCenter = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-center")), i18n("Align Center"), this);
68     actions->addAction(QStringLiteral("format_aligncenter"), m_textAlignCenter);
69     connect(m_textAlignCenter, &KToggleAction::triggered, this, &KNoteEdit::textAlignCenter);
70     actions->setDefaultShortcut(m_textAlignCenter, QKeySequence(Qt::ALT | Qt::Key_C));
71     m_textAlignRight = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-right")), i18n("Align Right"), this);
72     actions->addAction(QStringLiteral("format_alignright"), m_textAlignRight);
73     connect(m_textAlignRight, &KToggleAction::triggered, this, &KNoteEdit::textAlignRight);
74     actions->setDefaultShortcut(m_textAlignRight, QKeySequence(Qt::ALT | Qt::Key_R));
75     m_textAlignBlock = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-fill")), i18n("Align Block"), this);
76     actions->addAction(QStringLiteral("format_alignblock"), m_textAlignBlock);
77     connect(m_textAlignBlock, &KToggleAction::triggered, this, &KNoteEdit::textAlignBlock);
78     actions->setDefaultShortcut(m_textAlignBlock, QKeySequence(Qt::ALT | Qt::Key_B));
79 
80     auto group = new QActionGroup(this);
81     group->addAction(m_textAlignLeft);
82     group->addAction(m_textAlignCenter);
83     group->addAction(m_textAlignRight);
84     group->addAction(m_textAlignBlock);
85 
86     m_textList = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-list-ordered")), i18n("List"), this);
87     actions->addAction(QStringLiteral("format_list"), m_textList);
88     connect(m_textList, &KToggleAction::triggered, this, &KNoteEdit::textList);
89 
90     m_textSuper = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-superscript")), i18n("Superscript"), this);
91     actions->addAction(QStringLiteral("format_super"), m_textSuper);
92     connect(m_textSuper, &KToggleAction::triggered, this, &KNoteEdit::textSuperScript);
93     m_textSub = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-subscript")), i18n("Subscript"), this);
94     actions->addAction(QStringLiteral("format_sub"), m_textSub);
95     connect(m_textSub, &KToggleAction::triggered, this, &KNoteEdit::textSubScript);
96 
97     m_textIncreaseIndent = new QAction(QIcon::fromTheme(QStringLiteral("format-indent-more")), i18n("Increase Indent"), this);
98     actions->addAction(QStringLiteral("format_increaseindent"), m_textIncreaseIndent);
99     actions->setDefaultShortcut(m_textIncreaseIndent, QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_I));
100     connect(m_textIncreaseIndent, &QAction::triggered, this, &KNoteEdit::textIncreaseIndent);
101 
102     m_textDecreaseIndent = new QAction(QIcon::fromTheme(QStringLiteral("format-indent-less")), i18n("Decrease Indent"), this);
103     actions->addAction(QStringLiteral("format_decreaseindent"), m_textDecreaseIndent);
104     actions->setDefaultShortcut(m_textDecreaseIndent, QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_D));
105     connect(m_textDecreaseIndent, &QAction::triggered, this, &KNoteEdit::textDecreaseIndent);
106 
107     group = new QActionGroup(this);
108     group->addAction(m_textIncreaseIndent);
109     group->addAction(m_textDecreaseIndent);
110 
111     QPixmap pix(ICON_SIZE, ICON_SIZE);
112     pix.fill(Qt::black); // just a dummy, gets updated before widget is shown
113     m_textColor = new QAction(i18n("Text Color..."), this);
114     actions->addAction(QStringLiteral("format_color"), m_textColor);
115     m_textColor->setIcon(pix);
116     connect(m_textColor, &QAction::triggered, this, &KNoteEdit::slotTextColor);
117 
118     auto act = new QAction(QIcon::fromTheme(QStringLiteral("format-fill-color")), i18n("Text Background Color..."), this);
119     actions->addAction(QStringLiteral("text_background_color"), act);
120     connect(act, &QAction::triggered, this, &KNoteEdit::slotTextBackgroundColor);
121 
122     m_textFont = new KFontAction(i18n("Text Font"), this);
123     actions->addAction(QStringLiteral("format_font"), m_textFont);
124     connect(m_textFont, &KFontAction::textTriggered, this, &KNoteEdit::setFontFamily);
125     m_textSize = new KFontSizeAction(i18n("Text Size"), this);
126     actions->addAction(QStringLiteral("format_size"), m_textSize);
127     connect(m_textSize, &KFontSizeAction::fontSizeChanged, this, &KNoteEdit::setTextFontSize);
128 
129     mChangeCaseActionMenu = new PimCommon::KActionMenuChangeCase(this);
130     mChangeCaseActionMenu->appendInActionCollection(actions);
131     connect(mChangeCaseActionMenu, &PimCommon::KActionMenuChangeCase::upperCase, this, &KNoteEdit::slotUpperCase);
132     connect(mChangeCaseActionMenu, &PimCommon::KActionMenuChangeCase::lowerCase, this, &KNoteEdit::slotLowerCase);
133     connect(mChangeCaseActionMenu, &PimCommon::KActionMenuChangeCase::sentenceCase, this, &KNoteEdit::slotSentenceCase);
134     connect(mChangeCaseActionMenu, &PimCommon::KActionMenuChangeCase::reverseCase, this, &KNoteEdit::slotReverseCase);
135 
136     auto action = new QAction(QIcon::fromTheme(QStringLiteral("knotes_date")), i18n("Insert Date"), this);
137     actions->addAction(QStringLiteral("insert_date"), action);
138     connect(action, &QAction::triggered, this, &KNoteEdit::slotInsertDate);
139 
140     action = new QAction(QIcon::fromTheme(QStringLiteral("checkmark")), i18n("Insert Checkmark"), this);
141     actions->addAction(QStringLiteral("insert_checkmark"), action);
142     connect(action, &QAction::triggered, this, &KNoteEdit::slotInsertCheckMark);
143 
144     // QTextEdit connections
145     connect(this, &KNoteEdit::currentCharFormatChanged, this, &KNoteEdit::slotCurrentCharFormatChanged);
146     connect(this, &KNoteEdit::cursorPositionChanged, this, &KNoteEdit::slotCursorPositionChanged);
147     slotCurrentCharFormatChanged(currentCharFormat());
148     slotCursorPositionChanged();
149 }
150 
~KNoteEdit()151 KNoteEdit::~KNoteEdit()
152 {
153 }
154 
setColor(const QColor & fg,const QColor & bg)155 void KNoteEdit::setColor(const QColor &fg, const QColor &bg)
156 {
157     mDefaultBackgroundColor = bg;
158     mDefaultForegroundColor = fg;
159 
160     QPalette p = palette();
161 
162     // better: from light(150) to light(100) to light(75)
163     // QLinearGradient g( width()/2, 0, width()/2, height() );
164     // g.setColorAt( 0, bg );
165     // g.setColorAt( 1, bg.darker(150) );
166 
167     p.setColor(QPalette::Window, bg);
168     // p.setBrush( QPalette::Window,     g );
169     p.setColor(QPalette::Base, bg);
170     // p.setBrush( QPalette::Base,       g );
171 
172     p.setColor(QPalette::WindowText, fg);
173     p.setColor(QPalette::Text, fg);
174 
175     p.setColor(QPalette::Button, bg.darker(116));
176     p.setColor(QPalette::ButtonText, fg);
177 
178     // p.setColor( QPalette::Highlight,  bg );
179     // p.setColor( QPalette::HighlightedText, fg );
180 
181     // order: Light, Midlight, Button, Mid, Dark, Shadow
182 
183     // the shadow
184     p.setColor(QPalette::Light, bg.lighter(180));
185     p.setColor(QPalette::Midlight, bg.lighter(150));
186     p.setColor(QPalette::Mid, bg.lighter(150));
187     p.setColor(QPalette::Dark, bg.darker(108));
188     p.setColor(QPalette::Shadow, bg.darker(116));
189 
190     setPalette(p);
191 
192     setTextColor(fg);
193 }
194 
setNote(KNote * _note)195 void KNoteEdit::setNote(KNote *_note)
196 {
197     m_note = _note;
198 }
199 
slotReverseCase()200 void KNoteEdit::slotReverseCase()
201 {
202     QTextCursor cursor = textCursor();
203     KPIMTextEdit::EditorUtil editorUtil;
204     editorUtil.reverseCase(cursor);
205 }
206 
slotSentenceCase()207 void KNoteEdit::slotSentenceCase()
208 {
209     QTextCursor cursor = textCursor();
210     KPIMTextEdit::EditorUtil editorUtil;
211     editorUtil.sentenceCase(cursor);
212 }
213 
slotUpperCase()214 void KNoteEdit::slotUpperCase()
215 {
216     QTextCursor cursor = textCursor();
217     KPIMTextEdit::EditorUtil editorUtil;
218     editorUtil.upperCase(cursor);
219 }
220 
slotLowerCase()221 void KNoteEdit::slotLowerCase()
222 {
223     QTextCursor cursor = textCursor();
224     KPIMTextEdit::EditorUtil editorUtil;
225     editorUtil.lowerCase(cursor);
226 }
227 
mousePopupMenu()228 QMenu *KNoteEdit::mousePopupMenu()
229 {
230     QMenu *popup = KTextEdit::mousePopupMenu();
231     if (popup) {
232         QTextCursor cursor = textCursor();
233         if (!isReadOnly()) {
234             if (cursor.hasSelection()) {
235                 popup->addSeparator();
236                 popup->addAction(mChangeCaseActionMenu);
237             }
238             popup->addSeparator();
239             QAction *act = m_actions->action(QStringLiteral("insert_date"));
240             popup->addAction(act);
241             popup->addSeparator();
242             act = m_actions->action(QStringLiteral("insert_checkmark"));
243             popup->addAction(act);
244         }
245     }
246     return popup;
247 }
248 
setText(const QString & text)249 void KNoteEdit::setText(const QString &text)
250 {
251     if (acceptRichText() && Qt::mightBeRichText(text)) {
252         setHtml(text);
253     } else {
254         setPlainText(text);
255     }
256 }
257 
text() const258 QString KNoteEdit::text() const
259 {
260     if (acceptRichText()) {
261         return toHtml();
262     } else {
263         return toPlainText();
264     }
265 }
266 
setTextFont(const QFont & font)267 void KNoteEdit::setTextFont(const QFont &font)
268 {
269     setCurrentFont(font);
270 
271     // make this font default so that if user deletes note content
272     // font is remembered
273     document()->setDefaultFont(font);
274 }
275 
setTextFontSize(int size)276 void KNoteEdit::setTextFontSize(int size)
277 {
278     setFontPointSize(size);
279 }
280 
setTabStop(int tabs)281 void KNoteEdit::setTabStop(int tabs)
282 {
283     QFontMetrics fm(font());
284     setTabStopDistance(fm.boundingRect(QLatin1Char('x')).width() * tabs);
285 }
286 
setAutoIndentMode(bool newmode)287 void KNoteEdit::setAutoIndentMode(bool newmode)
288 {
289     m_autoIndentMode = newmode;
290 }
291 
292 /** public slots **/
293 
setRichText(bool f)294 void KNoteEdit::setRichText(bool f)
295 {
296     if (f == acceptRichText()) {
297         return;
298     }
299 
300     setAcceptRichText(f);
301 
302     if (f) {
303         setAutoFormatting(AutoAll);
304     } else {
305         setAutoFormatting(AutoNone);
306     }
307 
308     const QString t = toPlainText();
309     if (f) {
310         // if the note contains html source try to render it
311         if (Qt::mightBeRichText(t)) {
312             setHtml(t);
313         } else {
314             setPlainText(t);
315         }
316 
317         enableRichTextActions(true);
318     } else {
319         setPlainText(t);
320         enableRichTextActions(false);
321     }
322 }
323 
textBold(bool b)324 void KNoteEdit::textBold(bool b)
325 {
326     if (!acceptRichText()) {
327         return;
328     }
329 
330     QTextCharFormat f;
331     f.setFontWeight(b ? QFont::Bold : QFont::Normal);
332     mergeCurrentCharFormat(f);
333 }
334 
textStrikeOut(bool s)335 void KNoteEdit::textStrikeOut(bool s)
336 {
337     if (!acceptRichText()) {
338         return;
339     }
340 
341     QTextCharFormat f;
342     f.setFontStrikeOut(s);
343     mergeCurrentCharFormat(f);
344 }
345 
slotTextColor()346 void KNoteEdit::slotTextColor()
347 {
348     if (!acceptRichText()) {
349         return;
350     }
351 
352     if (m_note) {
353         m_note->setBlockSave(true);
354     }
355     QColor c = QColorDialog::getColor(textColor(), this);
356     if (c.isValid()) {
357         setTextColor(c);
358     }
359     if (m_note) {
360         m_note->setBlockSave(false);
361     }
362 }
363 
slotTextBackgroundColor()364 void KNoteEdit::slotTextBackgroundColor()
365 {
366     if (!acceptRichText()) {
367         return;
368     }
369 
370     if (m_note) {
371         m_note->setBlockSave(true);
372     }
373     const QColor c = QColorDialog::getColor(textBackgroundColor(), this);
374     if (c.isValid()) {
375         setTextBackgroundColor(c);
376     }
377     if (m_note) {
378         m_note->setBlockSave(false);
379     }
380 }
381 
textAlignLeft()382 void KNoteEdit::textAlignLeft()
383 {
384     if (!acceptRichText()) {
385         return;
386     }
387     setAlignment(Qt::AlignLeft);
388     m_textAlignLeft->setChecked(true);
389 }
390 
textAlignCenter()391 void KNoteEdit::textAlignCenter()
392 {
393     if (!acceptRichText()) {
394         return;
395     }
396     setAlignment(Qt::AlignCenter);
397     m_textAlignCenter->setChecked(true);
398 }
399 
textAlignRight()400 void KNoteEdit::textAlignRight()
401 {
402     if (!acceptRichText()) {
403         return;
404     }
405     setAlignment(Qt::AlignRight);
406     m_textAlignRight->setChecked(true);
407 }
408 
textAlignBlock()409 void KNoteEdit::textAlignBlock()
410 {
411     if (!acceptRichText()) {
412         return;
413     }
414     setAlignment(Qt::AlignJustify);
415     m_textAlignBlock->setChecked(true);
416 }
417 
textList()418 void KNoteEdit::textList()
419 {
420     if (!acceptRichText()) {
421         return;
422     }
423     QTextCursor c = textCursor();
424     c.beginEditBlock();
425 
426     if (m_textList->isChecked()) {
427         QTextListFormat lf;
428         QTextBlockFormat bf = c.blockFormat();
429 
430         lf.setIndent(bf.indent() + 1);
431         bf.setIndent(0);
432 
433         lf.setStyle(QTextListFormat::ListDisc);
434 
435         c.setBlockFormat(bf);
436         c.createList(lf);
437     } else {
438         QTextBlockFormat bf;
439         bf.setObjectIndex(-1);
440         c.setBlockFormat(bf);
441     }
442 
443     c.endEditBlock();
444 }
445 
textSuperScript()446 void KNoteEdit::textSuperScript()
447 {
448     if (!acceptRichText()) {
449         return;
450     }
451     QTextCharFormat f;
452     if (m_textSuper->isChecked()) {
453         if (m_textSub->isChecked()) {
454             m_textSub->setChecked(false);
455         }
456         f.setVerticalAlignment(QTextCharFormat::AlignSuperScript);
457     } else {
458         f.setVerticalAlignment(QTextCharFormat::AlignNormal);
459     }
460     mergeCurrentCharFormat(f);
461 }
462 
textSubScript()463 void KNoteEdit::textSubScript()
464 {
465     if (!acceptRichText()) {
466         return;
467     }
468     QTextCharFormat f;
469     if (m_textSub->isChecked()) {
470         if (m_textSuper->isChecked()) {
471             m_textSuper->setChecked(false);
472         }
473         f.setVerticalAlignment(QTextCharFormat::AlignSubScript);
474     } else {
475         f.setVerticalAlignment(QTextCharFormat::AlignNormal);
476     }
477     mergeCurrentCharFormat(f);
478 }
479 
textIncreaseIndent()480 void KNoteEdit::textIncreaseIndent()
481 {
482     if (!acceptRichText()) {
483         return;
484     }
485     QTextBlockFormat f = textCursor().blockFormat();
486     f.setIndent(f.indent() + 1);
487     textCursor().setBlockFormat(f);
488 }
489 
textDecreaseIndent()490 void KNoteEdit::textDecreaseIndent()
491 {
492     if (!acceptRichText()) {
493         return;
494     }
495     QTextBlockFormat f = textCursor().blockFormat();
496     short int curIndent = f.indent();
497 
498     if (curIndent > 0) {
499         f.setIndent(curIndent - 1);
500     }
501     textCursor().setBlockFormat(f);
502 }
503 
504 /** protected methods **/
505 
keyPressEvent(QKeyEvent * e)506 void KNoteEdit::keyPressEvent(QKeyEvent *e)
507 {
508     KTextEdit::keyPressEvent(e);
509 
510     if (m_autoIndentMode && ((e->key() == Qt::Key_Return) || (e->key() == Qt::Key_Enter))) {
511         autoIndent();
512     }
513 }
514 
focusInEvent(QFocusEvent * e)515 void KNoteEdit::focusInEvent(QFocusEvent *e)
516 {
517     KTextEdit::focusInEvent(e);
518 
519     setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
520     setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
521 }
522 
focusOutEvent(QFocusEvent * e)523 void KNoteEdit::focusOutEvent(QFocusEvent *e)
524 {
525     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
526     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
527 
528     KTextEdit::focusOutEvent(e);
529 }
530 
531 /** private slots **/
532 
slotCurrentCharFormatChanged(const QTextCharFormat & f)533 void KNoteEdit::slotCurrentCharFormatChanged(const QTextCharFormat &f)
534 {
535     if (!acceptRichText()) {
536         return;
537     }
538 
539     // font changes
540     m_textFont->setFont(f.fontFamily());
541     m_textSize->setFontSize((f.fontPointSize() > 0) ? (int)f.fontPointSize() : 10);
542 
543     m_textBold->setChecked(f.font().bold());
544     m_textItalic->setChecked(f.fontItalic());
545     m_textUnderline->setChecked(f.fontUnderline());
546     m_textStrikeOut->setChecked(f.fontStrikeOut());
547 
548     // color changes
549     QPixmap pix(ICON_SIZE, ICON_SIZE);
550     pix.fill(f.foreground().color());
551     m_textColor->QAction::setIcon(pix);
552 
553     // vertical alignment changes
554     QTextCharFormat::VerticalAlignment va = f.verticalAlignment();
555     if (va == QTextCharFormat::AlignNormal) {
556         m_textSuper->setChecked(false);
557         m_textSub->setChecked(false);
558     } else if (va == QTextCharFormat::AlignSuperScript) {
559         m_textSuper->setChecked(true);
560     } else if (va == QTextCharFormat::AlignSubScript) {
561         m_textSub->setChecked(true);
562     }
563 }
564 
slotCursorPositionChanged()565 void KNoteEdit::slotCursorPositionChanged()
566 {
567     if (!acceptRichText()) {
568         return;
569     }
570     // alignment changes
571     const Qt::Alignment a = alignment();
572     if (a & Qt::AlignLeft) {
573         m_textAlignLeft->setChecked(true);
574     } else if (a & Qt::AlignHCenter) {
575         m_textAlignCenter->setChecked(true);
576     } else if (a & Qt::AlignRight) {
577         m_textAlignRight->setChecked(true);
578     } else if (a & Qt::AlignJustify) {
579         m_textAlignBlock->setChecked(true);
580     }
581 }
582 
583 /** private methods **/
584 
autoIndent()585 void KNoteEdit::autoIndent()
586 {
587     QTextCursor c = textCursor();
588     QTextBlock b = c.block();
589 
590     QString string;
591     while ((b.previous().length() > 0) && string.trimmed().isEmpty()) {
592         b = b.previous();
593         string = b.text();
594     }
595 
596     if (string.trimmed().isEmpty()) {
597         return;
598     }
599 
600     // This routine returns the whitespace before the first non white space
601     // character in string.
602     // It is assumed that string contains at least one non whitespace character
603     // ie \n \r \t \v \f and space
604     QString indentString;
605 
606     const int len = string.length();
607     int i = 0;
608     while (i < len && string.at(i).isSpace()) {
609         indentString += string.at(i++);
610     }
611 
612     if (!indentString.isEmpty()) {
613         c.insertText(indentString);
614     }
615 }
616 
enableRichTextActions(bool enabled)617 void KNoteEdit::enableRichTextActions(bool enabled)
618 {
619     m_textColor->setEnabled(enabled);
620     m_textFont->setEnabled(enabled);
621     m_textSize->setEnabled(enabled);
622 
623     m_textBold->setEnabled(enabled);
624     m_textItalic->setEnabled(enabled);
625     m_textUnderline->setEnabled(enabled);
626     m_textStrikeOut->setEnabled(enabled);
627 
628     m_textAlignLeft->setEnabled(enabled);
629     m_textAlignCenter->setEnabled(enabled);
630     m_textAlignRight->setEnabled(enabled);
631     m_textAlignBlock->setEnabled(enabled);
632 
633     m_textList->setEnabled(enabled);
634     m_textSuper->setEnabled(enabled);
635     m_textSub->setEnabled(enabled);
636 
637     m_textIncreaseIndent->setEnabled(enabled);
638     m_textDecreaseIndent->setEnabled(enabled);
639 }
640 
slotInsertDate()641 void KNoteEdit::slotInsertDate()
642 {
643     NoteShared::NoteEditorUtils noteEditorUtils;
644     noteEditorUtils.insertDate(this);
645 }
646 
slotInsertCheckMark()647 void KNoteEdit::slotInsertCheckMark()
648 {
649     QTextCursor cursor = textCursor();
650     NoteShared::NoteEditorUtils noteEditorUtils;
651     noteEditorUtils.addCheckmark(cursor);
652 }
653 
setCursorPositionFromStart(int pos)654 void KNoteEdit::setCursorPositionFromStart(int pos)
655 {
656     if (pos > 0) {
657         QTextCursor cursor = textCursor();
658         // Fix html pos cursor
659         cursor.setPosition(qMin(pos, cursor.document()->characterCount() - 1));
660         setTextCursor(cursor);
661         ensureCursorVisible();
662     }
663 }
664 
cursorPositionFromStart() const665 int KNoteEdit::cursorPositionFromStart() const
666 {
667     return textCursor().position();
668 }
669