Fix Bug 358840 - kmail composer: menu item "send" missing
[kdepim.git] / knotes / knoteedit.cpp
blob6dd195bfbd9657d9343c7cc509479098235c1ea8
1 /*******************************************************************
2 KNotes -- Notes for the KDE project
4 Copyright (c) 1997-2013, The KNotes Developers
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 *******************************************************************/
21 #include "knoteedit.h"
22 #include "notes/knote.h"
23 #include "NoteShared/NoteEditorUtils"
24 #include "KPIMTextEdit/EditorUtil"
25 #include "PimCommon/KActionMenuChangeCase"
26 #include "knotesglobalconfig.h"
28 #include <QAction>
30 #include <kactioncollection.h>
31 #include <QColorDialog>
32 #include "knotes_debug.h"
33 #include <kfontaction.h>
34 #include <kfontsizeaction.h>
35 #include <KLocalizedString>
36 #include <QMenu>
37 #include <kstandardaction.h>
38 #include <ktoggleaction.h>
40 #include <QFont>
41 #include <QPixmap>
42 #include <QKeyEvent>
44 static const short ICON_SIZE = 10;
46 KNoteEdit::KNoteEdit(KActionCollection *actions, QWidget *parent)
47 : KTextEdit(parent),
48 m_note(0),
49 m_actions(actions)
51 setAcceptDrops(true);
52 setWordWrapMode(QTextOption::WordWrap);
53 setLineWrapMode(WidgetWidth);
54 if (acceptRichText()) {
55 setAutoFormatting(AutoAll);
56 } else {
57 setAutoFormatting(AutoNone);
60 // create the actions modifying the text format
61 m_textBold = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-bold")), i18n("Bold"),
62 this);
63 actions->addAction(QStringLiteral("format_bold"), m_textBold);
64 actions->setDefaultShortcut(m_textBold, QKeySequence(Qt::CTRL + Qt::Key_B));
65 m_textItalic = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-italic")),
66 i18n("Italic"), this);
67 actions->addAction(QStringLiteral("format_italic"), m_textItalic);
68 actions->setDefaultShortcut(m_textItalic, QKeySequence(Qt::CTRL + Qt::Key_I));
69 m_textUnderline = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-underline")),
70 i18n("Underline"), this);
71 actions->addAction(QStringLiteral("format_underline"), m_textUnderline);
72 actions->setDefaultShortcut(m_textUnderline, QKeySequence(Qt::CTRL + Qt::Key_U));
73 m_textStrikeOut = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-strikethrough")),
74 i18n("Strike Out"), this);
75 actions->addAction(QStringLiteral("format_strikeout"), m_textStrikeOut);
76 actions->setDefaultShortcut(m_textStrikeOut, QKeySequence(Qt::CTRL + Qt::Key_S));
78 connect(m_textBold, &KToggleAction::toggled, this, &KNoteEdit::textBold);
79 connect(m_textItalic, &KToggleAction::toggled, this, &KNoteEdit::setFontItalic);
80 connect(m_textUnderline, &KToggleAction::toggled, this, &KNoteEdit::setFontUnderline);
81 connect(m_textStrikeOut, &KToggleAction::toggled, this, &KNoteEdit::textStrikeOut);
83 m_textAlignLeft = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-left")),
84 i18n("Align Left"), this);
85 actions->addAction(QStringLiteral("format_alignleft"), m_textAlignLeft);
86 connect(m_textAlignLeft, &KToggleAction::triggered, this, &KNoteEdit::textAlignLeft);
87 actions->setDefaultShortcut(m_textAlignLeft, QKeySequence(Qt::ALT + Qt::Key_L));
88 m_textAlignLeft->setChecked(true); // just a dummy, will be updated later
89 m_textAlignCenter = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-center")),
90 i18n("Align Center"), this);
91 actions->addAction(QStringLiteral("format_aligncenter"), m_textAlignCenter);
92 connect(m_textAlignCenter, &KToggleAction::triggered, this, &KNoteEdit::textAlignCenter);
93 actions->setDefaultShortcut(m_textAlignCenter, QKeySequence(Qt::ALT + Qt::Key_C));
94 m_textAlignRight = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-right")),
95 i18n("Align Right"), this);
96 actions->addAction(QStringLiteral("format_alignright"), m_textAlignRight);
97 connect(m_textAlignRight, &KToggleAction::triggered, this, &KNoteEdit::textAlignRight);
98 actions->setDefaultShortcut(m_textAlignRight, QKeySequence(Qt::ALT + Qt::Key_R));
99 m_textAlignBlock = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-justify-fill")),
100 i18n("Align Block"), this);
101 actions->addAction(QStringLiteral("format_alignblock"), m_textAlignBlock);
102 connect(m_textAlignBlock, &KToggleAction::triggered, this, &KNoteEdit::textAlignBlock);
103 actions->setDefaultShortcut(m_textAlignBlock, QKeySequence(Qt::ALT + Qt::Key_B));
105 QActionGroup *group = new QActionGroup(this);
106 group->addAction(m_textAlignLeft);
107 group->addAction(m_textAlignCenter);
108 group->addAction(m_textAlignRight);
109 group->addAction(m_textAlignBlock);
111 m_textList = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-list-ordered")), i18n("List"), this);
112 actions->addAction(QStringLiteral("format_list"), m_textList);
113 connect(m_textList, &KToggleAction::triggered, this, &KNoteEdit::textList);
115 m_textSuper = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-superscript")),
116 i18n("Superscript"), this);
117 actions->addAction(QStringLiteral("format_super"), m_textSuper);
118 connect(m_textSuper, &KToggleAction::triggered, this, &KNoteEdit::textSuperScript);
119 m_textSub = new KToggleAction(QIcon::fromTheme(QStringLiteral("format-text-subscript")), i18n("Subscript"),
120 this);
121 actions->addAction(QStringLiteral("format_sub"), m_textSub);
122 connect(m_textSub, &KToggleAction::triggered, this, &KNoteEdit::textSubScript);
124 m_textIncreaseIndent = new QAction(QIcon::fromTheme(QStringLiteral("format-indent-more")),
125 i18n("Increase Indent"), this);
126 actions->addAction(QStringLiteral("format_increaseindent"), m_textIncreaseIndent);
127 actions->setDefaultShortcut(m_textIncreaseIndent, QKeySequence(Qt::CTRL + Qt::ALT +
128 Qt::Key_I));
129 connect(m_textIncreaseIndent, &QAction::triggered, this, &KNoteEdit::textIncreaseIndent);
131 m_textDecreaseIndent = new QAction(QIcon::fromTheme(QStringLiteral("format-indent-less")),
132 i18n("Decrease Indent"), this);
133 actions->addAction(QStringLiteral("format_decreaseindent"), m_textDecreaseIndent);
134 actions->setDefaultShortcut(m_textDecreaseIndent, QKeySequence(Qt::CTRL + Qt::ALT +
135 Qt::Key_D));
136 connect(m_textDecreaseIndent, &QAction::triggered, this, &KNoteEdit::textDecreaseIndent);
138 group = new QActionGroup(this);
139 group->addAction(m_textIncreaseIndent);
140 group->addAction(m_textDecreaseIndent);
142 QPixmap pix(ICON_SIZE, ICON_SIZE);
143 pix.fill(Qt::black); // just a dummy, gets updated before widget is shown
144 m_textColor = new QAction(i18n("Text Color..."), this);
145 actions->addAction(QStringLiteral("format_color"), m_textColor);
146 m_textColor->setIcon(pix);
147 connect(m_textColor, &QAction::triggered, this, &KNoteEdit::slotTextColor);
149 QAction *act = new QAction(QIcon::fromTheme(QStringLiteral("format-fill-color")), i18n("Text Background Color..."), this);
150 actions->addAction(QStringLiteral("text_background_color"), act);
151 connect(act, &QAction::triggered, this, &KNoteEdit::slotTextBackgroundColor);
153 m_textFont = new KFontAction(i18n("Text Font"), this);
154 actions->addAction(QStringLiteral("format_font"), m_textFont);
155 connect(m_textFont, static_cast<void (KFontAction::*)(const QString &)>(&KFontAction::triggered), this, &KNoteEdit::setFontFamily);
157 m_textSize = new KFontSizeAction(i18n("Text Size"), this);
158 actions->addAction(QStringLiteral("format_size"), m_textSize);
159 connect(m_textSize, &KFontSizeAction::fontSizeChanged, this, &KNoteEdit::setTextFontSize);
161 mChangeCaseActionMenu = new PimCommon::KActionMenuChangeCase(this);
162 mChangeCaseActionMenu->appendInActionCollection(actions);
163 connect(mChangeCaseActionMenu, &PimCommon::KActionMenuChangeCase::upperCase, this, &KNoteEdit::slotUpperCase);
164 connect(mChangeCaseActionMenu, &PimCommon::KActionMenuChangeCase::lowerCase, this, &KNoteEdit::slotLowerCase);
165 connect(mChangeCaseActionMenu, &PimCommon::KActionMenuChangeCase::sentenceCase, this, &KNoteEdit::slotSentenceCase);
166 connect(mChangeCaseActionMenu, &PimCommon::KActionMenuChangeCase::reverseCase, this, &KNoteEdit::slotReverseCase);
168 QAction *action = new QAction(QIcon::fromTheme(QStringLiteral("knotes_date")), i18n("Insert Date"), this);
169 actions->addAction(QStringLiteral("insert_date"), action);
170 connect(action, &QAction::triggered, this, &KNoteEdit::slotInsertDate);
172 action = new QAction(QIcon::fromTheme(QStringLiteral("checkmark")), i18n("Insert Checkmark"), this);
173 actions->addAction(QStringLiteral("insert_checkmark"), action);
174 connect(action, &QAction::triggered, this, &KNoteEdit::slotInsertCheckMark);
176 // QTextEdit connections
177 connect(this, &KNoteEdit::currentCharFormatChanged, this, &KNoteEdit::slotCurrentCharFormatChanged);
178 connect(this, &KNoteEdit::cursorPositionChanged, this, &KNoteEdit::slotCursorPositionChanged);
179 slotCurrentCharFormatChanged(currentCharFormat());
180 slotCursorPositionChanged();
183 KNoteEdit::~KNoteEdit()
187 void KNoteEdit::setColor(const QColor &fg, const QColor &bg)
189 mDefaultBackgroundColor = bg;
190 mDefaultForegroundColor = fg;
192 QPalette p = palette();
194 // better: from light(150) to light(100) to light(75)
195 // QLinearGradient g( width()/2, 0, width()/2, height() );
196 // g.setColorAt( 0, bg );
197 // g.setColorAt( 1, bg.dark(150) );
199 p.setColor(QPalette::Window, bg);
200 // p.setBrush( QPalette::Window, g );
201 p.setColor(QPalette::Base, bg);
202 // p.setBrush( QPalette::Base, g );
204 p.setColor(QPalette::WindowText, fg);
205 p.setColor(QPalette::Text, fg);
207 p.setColor(QPalette::Button, bg.dark(116));
208 p.setColor(QPalette::ButtonText, fg);
210 //p.setColor( QPalette::Highlight, bg );
211 //p.setColor( QPalette::HighlightedText, fg );
213 // order: Light, Midlight, Button, Mid, Dark, Shadow
215 // the shadow
216 p.setColor(QPalette::Light, bg.light(180));
217 p.setColor(QPalette::Midlight, bg.light(150));
218 p.setColor(QPalette::Mid, bg.light(150));
219 p.setColor(QPalette::Dark, bg.dark(108));
220 p.setColor(QPalette::Shadow, bg.dark(116));
222 setPalette(p);
224 setTextColor(fg);
227 void KNoteEdit::setNote(KNote *_note)
229 m_note = _note;
232 void KNoteEdit::slotReverseCase()
234 QTextCursor cursor = textCursor();
235 KPIMTextEdit::EditorUtil editorUtil;
236 editorUtil.reverseCase(cursor);
239 void KNoteEdit::slotSentenceCase()
241 QTextCursor cursor = textCursor();
242 KPIMTextEdit::EditorUtil editorUtil;
243 editorUtil.sentenceCase(cursor);
246 void KNoteEdit::slotUpperCase()
248 QTextCursor cursor = textCursor();
249 KPIMTextEdit::EditorUtil editorUtil;
250 editorUtil.upperCase(cursor);
253 void KNoteEdit::slotLowerCase()
255 QTextCursor cursor = textCursor();
256 KPIMTextEdit::EditorUtil editorUtil;
257 editorUtil.lowerCase(cursor);
260 QMenu *KNoteEdit::mousePopupMenu()
262 QMenu *popup = KTextEdit::mousePopupMenu();
263 if (popup) {
264 QTextCursor cursor = textCursor();
265 if (!isReadOnly()) {
266 if (cursor.hasSelection()) {
267 popup->addSeparator();
268 popup->addAction(mChangeCaseActionMenu);
270 popup->addSeparator();
271 QAction *act = m_actions->action(QStringLiteral("insert_date"));
272 popup->addAction(act);
273 popup->addSeparator();
274 act = m_actions->action(QStringLiteral("insert_checkmark"));
275 popup->addAction(act);
278 return popup;
281 void KNoteEdit::setText(const QString &text)
283 if (acceptRichText() && Qt::mightBeRichText(text)) {
284 setHtml(text);
285 } else {
286 setPlainText(text);
290 QString KNoteEdit::text() const
292 if (acceptRichText()) {
293 return toHtml();
294 } else {
295 return toPlainText();
299 void KNoteEdit::setTextFont(const QFont &font)
301 setCurrentFont(font);
303 // make this font default so that if user deletes note content
304 // font is remembered
305 document()->setDefaultFont(font);
308 void KNoteEdit::setTextFontSize(int size)
310 setFontPointSize(size);
313 void KNoteEdit::setTabStop(int tabs)
315 QFontMetrics fm(font());
316 setTabStopWidth(fm.width(QLatin1Char('x')) * tabs);
319 void KNoteEdit::setAutoIndentMode(bool newmode)
321 m_autoIndentMode = newmode;
324 /** public slots **/
326 void KNoteEdit::setRichText(bool f)
328 if (f == acceptRichText()) {
329 return;
332 setAcceptRichText(f);
334 if (f) {
335 setAutoFormatting(AutoAll);
336 } else {
337 setAutoFormatting(AutoNone);
340 const QString t = toPlainText();
341 if (f) {
342 // if the note contains html source try to render it
343 if (Qt::mightBeRichText(t)) {
344 setHtml(t);
345 } else {
346 setPlainText(t);
349 enableRichTextActions(true);
350 } else {
351 setPlainText(t);
352 enableRichTextActions(false);
356 void KNoteEdit::textBold(bool b)
358 if (!acceptRichText()) {
359 return;
362 QTextCharFormat f;
363 f.setFontWeight(b ? QFont::Bold : QFont::Normal);
364 mergeCurrentCharFormat(f);
367 void KNoteEdit::textStrikeOut(bool s)
369 if (!acceptRichText()) {
370 return;
373 QTextCharFormat f;
374 f.setFontStrikeOut(s);
375 mergeCurrentCharFormat(f);
378 void KNoteEdit::slotTextColor()
380 if (!acceptRichText()) {
381 return;
384 if (m_note) {
385 m_note->setBlockSave(true);
387 QColor c = QColorDialog::getColor(textColor(), this);
388 if (c.isValid()) {
389 setTextColor(c);
391 if (m_note) {
392 m_note->setBlockSave(false);
396 void KNoteEdit::slotTextBackgroundColor()
398 if (!acceptRichText()) {
399 return;
402 if (m_note) {
403 m_note->setBlockSave(true);
405 QColor c = QColorDialog::getColor(textBackgroundColor(), this);
406 if (c.isValid()) {
407 setTextBackgroundColor(c);
409 if (m_note) {
410 m_note->setBlockSave(false);
414 void KNoteEdit::textAlignLeft()
416 if (!acceptRichText()) {
417 return;
419 setAlignment(Qt::AlignLeft);
420 m_textAlignLeft->setChecked(true);
423 void KNoteEdit::textAlignCenter()
425 if (!acceptRichText()) {
426 return;
428 setAlignment(Qt::AlignCenter);
429 m_textAlignCenter->setChecked(true);
432 void KNoteEdit::textAlignRight()
434 if (!acceptRichText()) {
435 return;
437 setAlignment(Qt::AlignRight);
438 m_textAlignRight->setChecked(true);
441 void KNoteEdit::textAlignBlock()
443 if (!acceptRichText()) {
444 return;
446 setAlignment(Qt::AlignJustify);
447 m_textAlignBlock->setChecked(true);
450 void KNoteEdit::textList()
452 if (!acceptRichText()) {
453 return;
455 QTextCursor c = textCursor();
456 c.beginEditBlock();
458 if (m_textList->isChecked()) {
459 QTextListFormat lf;
460 QTextBlockFormat bf = c.blockFormat();
462 lf.setIndent(bf.indent() + 1);
463 bf.setIndent(0);
465 lf.setStyle(QTextListFormat::ListDisc);
467 c.setBlockFormat(bf);
468 c.createList(lf);
469 } else {
470 QTextBlockFormat bf;
471 bf.setObjectIndex(-1);
472 c.setBlockFormat(bf);
476 c.endEditBlock();
479 void KNoteEdit::textSuperScript()
481 if (!acceptRichText()) {
482 return;
484 QTextCharFormat f;
485 if (m_textSuper->isChecked()) {
486 if (m_textSub->isChecked()) {
487 m_textSub->setChecked(false);
489 f.setVerticalAlignment(QTextCharFormat::AlignSuperScript);
490 } else {
491 f.setVerticalAlignment(QTextCharFormat::AlignNormal);
493 mergeCurrentCharFormat(f);
496 void KNoteEdit::textSubScript()
498 if (!acceptRichText()) {
499 return;
501 QTextCharFormat f;
502 if (m_textSub->isChecked()) {
503 if (m_textSuper->isChecked()) {
504 m_textSuper->setChecked(false);
506 f.setVerticalAlignment(QTextCharFormat::AlignSubScript);
507 } else {
508 f.setVerticalAlignment(QTextCharFormat::AlignNormal);
510 mergeCurrentCharFormat(f);
513 void KNoteEdit::textIncreaseIndent()
515 if (!acceptRichText()) {
516 return;
518 QTextBlockFormat f = textCursor().blockFormat();
519 f.setIndent(f.indent() + 1);
520 textCursor().setBlockFormat(f);
523 void KNoteEdit::textDecreaseIndent()
525 if (!acceptRichText()) {
526 return;
528 QTextBlockFormat f = textCursor().blockFormat();
529 short int curIndent = f.indent();
531 if (curIndent > 0) {
532 f.setIndent(curIndent - 1);
534 textCursor().setBlockFormat(f);
537 /** protected methods **/
539 void KNoteEdit::keyPressEvent(QKeyEvent *e)
541 KTextEdit::keyPressEvent(e);
543 if (m_autoIndentMode &&
544 ((e->key() == Qt::Key_Return) || (e->key() == Qt::Key_Enter))) {
545 autoIndent();
549 void KNoteEdit::focusInEvent(QFocusEvent *e)
551 KTextEdit::focusInEvent(e);
553 setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
554 setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
557 void KNoteEdit::focusOutEvent(QFocusEvent *e)
559 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
560 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
562 KTextEdit::focusOutEvent(e);
565 /** private slots **/
567 void KNoteEdit::slotCurrentCharFormatChanged(const QTextCharFormat &f)
569 if (!acceptRichText()) {
570 return;
573 // font changes
574 m_textFont->setFont(f.fontFamily());
575 m_textSize->setFontSize((f.fontPointSize() > 0) ? (int) f.fontPointSize() : 10);
577 m_textBold->setChecked(f.font().bold());
578 m_textItalic->setChecked(f.fontItalic());
579 m_textUnderline->setChecked(f.fontUnderline());
580 m_textStrikeOut->setChecked(f.fontStrikeOut());
582 // color changes
583 QPixmap pix(ICON_SIZE, ICON_SIZE);
584 pix.fill(f.foreground().color());
585 m_textColor->QAction::setIcon(pix);
587 // vertical alignment changes
588 QTextCharFormat::VerticalAlignment va = f.verticalAlignment();
589 if (va == QTextCharFormat::AlignNormal) {
590 m_textSuper->setChecked(false);
591 m_textSub->setChecked(false);
592 } else if (va == QTextCharFormat::AlignSuperScript) {
593 m_textSuper->setChecked(true);
594 } else if (va == QTextCharFormat::AlignSubScript) {
595 m_textSub->setChecked(true);
599 void KNoteEdit::slotCursorPositionChanged()
601 if (!acceptRichText()) {
602 return;
604 // alignment changes
605 const Qt::Alignment a = alignment();
606 if (a & Qt::AlignLeft) {
607 m_textAlignLeft->setChecked(true);
608 } else if (a & Qt::AlignHCenter) {
609 m_textAlignCenter->setChecked(true);
610 } else if (a & Qt::AlignRight) {
611 m_textAlignRight->setChecked(true);
612 } else if (a & Qt::AlignJustify) {
613 m_textAlignBlock->setChecked(true);
617 /** private methods **/
619 void KNoteEdit::autoIndent()
621 QTextCursor c = textCursor();
622 QTextBlock b = c.block();
624 QString string;
625 while ((b.previous().length() > 0) && string.trimmed().isEmpty()) {
626 b = b.previous();
627 string = b.text();
630 if (string.trimmed().isEmpty()) {
631 return;
634 // This routine returns the whitespace before the first non white space
635 // character in string.
636 // It is assumed that string contains at least one non whitespace character
637 // ie \n \r \t \v \f and space
638 QString indentString;
640 const int len = string.length();
641 int i = 0;
642 while (i < len && string.at(i).isSpace()) {
643 indentString += string.at(i++);
646 if (!indentString.isEmpty()) {
647 c.insertText(indentString);
651 void KNoteEdit::enableRichTextActions(bool enabled)
653 m_textColor->setEnabled(enabled);
654 m_textFont->setEnabled(enabled);
655 m_textSize->setEnabled(enabled);
657 m_textBold->setEnabled(enabled);
658 m_textItalic->setEnabled(enabled);
659 m_textUnderline->setEnabled(enabled);
660 m_textStrikeOut->setEnabled(enabled);
662 m_textAlignLeft->setEnabled(enabled);
663 m_textAlignCenter->setEnabled(enabled);
664 m_textAlignRight->setEnabled(enabled);
665 m_textAlignBlock->setEnabled(enabled);
667 m_textList->setEnabled(enabled);
668 m_textSuper->setEnabled(enabled);
669 m_textSub->setEnabled(enabled);
671 m_textIncreaseIndent->setEnabled(enabled);
672 m_textDecreaseIndent->setEnabled(enabled);
675 void KNoteEdit::slotInsertDate()
677 NoteShared::NoteEditorUtils noteEditorUtils;
678 noteEditorUtils.insertDate(this);
681 void KNoteEdit::slotInsertCheckMark()
683 QTextCursor cursor = textCursor();
684 NoteShared::NoteEditorUtils noteEditorUtils;
685 noteEditorUtils.addCheckmark(cursor);
688 void KNoteEdit::setCursorPositionFromStart(int pos)
690 if (pos > 0) {
691 QTextCursor cursor = textCursor();
692 //Fix html pos cursor
693 cursor.setPosition(qMin(pos, cursor.document()->characterCount() - 1));
694 setTextCursor(cursor);
695 ensureCursorVisible();
699 int KNoteEdit::cursorPositionFromStart() const
701 return textCursor().position();