KDEUI
krichtextedit.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "krichtextedit.h"
00025
00026
00027 #include "nestedlisthelper.h"
00028 #include "klinkdialog.h"
00029
00030
00031 #include <kcursor.h>
00032
00033
00034 #include <QtGui/QTextDocumentFragment>
00035 #include <QtGui/QMouseEvent>
00036
00041
00042 class KRichTextEditPrivate : public QObject
00043 {
00044 public:
00045 KRichTextEditPrivate(KRichTextEdit *parent)
00046 : q(parent),
00047 mMode(KRichTextEdit::Plain) {
00048 nestedListHelper = new NestedListHelper(q);
00049 }
00050
00051 ~KRichTextEditPrivate() {
00052 delete nestedListHelper;
00053 }
00054
00055
00056
00057
00058
00059
00060
00061
00062 void selectLinkText() const;
00063
00064 void init();
00065
00066
00067
00068 void activateRichText();
00069
00070
00071 void mergeFormatOnWordOrSelection(const QTextCharFormat &format);
00072
00073 void setTextCursor(QTextCursor &cursor);
00074
00075
00076
00077
00078 KRichTextEdit *q;
00079 KRichTextEdit::Mode mMode;
00080
00081 NestedListHelper *nestedListHelper;
00082
00083 };
00084
00085 void KRichTextEditPrivate::activateRichText()
00086 {
00087 if (mMode == KRichTextEdit::Plain) {
00088 q->setAcceptRichText(true);
00089 mMode = KRichTextEdit::Rich;
00090 emit q->textModeChanged(mMode);
00091 }
00092 }
00093
00094 void KRichTextEditPrivate::setTextCursor(QTextCursor &cursor)
00095 {
00096 q->setTextCursor(cursor);
00097 }
00098
00099 void KRichTextEditPrivate::mergeFormatOnWordOrSelection(const QTextCharFormat &format)
00100 {
00101 QTextCursor cursor = q->textCursor();
00102 QTextCursor wordStart(cursor);
00103 QTextCursor wordEnd(cursor);
00104
00105 wordStart.movePosition(QTextCursor::StartOfWord);
00106 wordEnd.movePosition(QTextCursor::EndOfWord);
00107
00108 cursor.beginEditBlock();
00109 if (!cursor.hasSelection() && cursor.position() != wordStart.position() && cursor.position() != wordEnd.position())
00110 cursor.select(QTextCursor::WordUnderCursor);
00111 cursor.mergeCharFormat(format);
00112 q->mergeCurrentCharFormat(format);
00113 cursor.endEditBlock();
00114 }
00115
00116
00117 KRichTextEdit::KRichTextEdit(const QString& text, QWidget *parent)
00118 : KTextEdit(text, parent), d(new KRichTextEditPrivate(this))
00119 {
00120 d->init();
00121 }
00122
00123 KRichTextEdit::KRichTextEdit(QWidget *parent)
00124 : KTextEdit(parent), d(new KRichTextEditPrivate(this))
00125 {
00126 d->init();
00127 }
00128
00129 KRichTextEdit::~KRichTextEdit()
00130 {
00131 delete d;
00132 }
00133
00134
00135 void KRichTextEditPrivate::init()
00136 {
00137 q->setAcceptRichText(false);
00138 KCursor::setAutoHideCursor(q, true, true);
00139 }
00140
00141
00142 void KRichTextEdit::setListStyle(int _styleIndex)
00143 {
00144 d->nestedListHelper->handleOnBulletType(-_styleIndex);
00145 setFocus();
00146 d->activateRichText();
00147 }
00148
00149 void KRichTextEdit::indentListMore()
00150 {
00151 d->nestedListHelper->handleOnIndentMore();
00152 d->activateRichText();
00153 }
00154
00155 void KRichTextEdit::indentListLess()
00156 {
00157 d->nestedListHelper->handleOnIndentLess();
00158 }
00159
00160 void KRichTextEdit::insertHorizontalRule()
00161 {
00162 QTextCursor cursor = textCursor();
00163 QTextBlockFormat bf = cursor.blockFormat();
00164 QTextCharFormat cf = cursor.charFormat();
00165
00166 cursor.beginEditBlock();
00167 cursor.insertHtml("<hr>");
00168 cursor.insertBlock(bf, cf);
00169 setTextCursor(cursor);
00170 d->activateRichText();
00171 cursor.endEditBlock();
00172 }
00173
00174 void KRichTextEdit::alignLeft()
00175 {
00176 setAlignment(Qt::AlignLeft);
00177 setFocus();
00178 d->activateRichText();
00179 }
00180
00181 void KRichTextEdit::alignCenter()
00182 {
00183 setAlignment(Qt::AlignHCenter);
00184 setFocus();
00185 d->activateRichText();
00186 }
00187
00188 void KRichTextEdit::alignRight()
00189 {
00190 setAlignment(Qt::AlignRight);
00191 setFocus();
00192 d->activateRichText();
00193 }
00194
00195 void KRichTextEdit::alignJustify()
00196 {
00197 setAlignment(Qt::AlignJustify);
00198 setFocus();
00199 d->activateRichText();
00200 }
00201
00202 void KRichTextEdit::setTextBold(bool bold)
00203 {
00204 QTextCharFormat fmt;
00205 fmt.setFontWeight(bold ? QFont::Bold : QFont::Normal);
00206 d->mergeFormatOnWordOrSelection(fmt);
00207 setFocus();
00208 d->activateRichText();
00209 }
00210
00211 void KRichTextEdit::setTextItalic(bool italic)
00212 {
00213 QTextCharFormat fmt;
00214 fmt.setFontItalic(italic);
00215 d->mergeFormatOnWordOrSelection(fmt);
00216 setFocus();
00217 d->activateRichText();
00218 }
00219
00220 void KRichTextEdit::setTextUnderline(bool underline)
00221 {
00222 QTextCharFormat fmt;
00223 fmt.setFontUnderline(underline);
00224 d->mergeFormatOnWordOrSelection(fmt);
00225 setFocus();
00226 d->activateRichText();
00227 }
00228
00229 void KRichTextEdit::setTextStrikeOut(bool strikeOut)
00230 {
00231 QTextCharFormat fmt;
00232 fmt.setFontStrikeOut(strikeOut);
00233 d->mergeFormatOnWordOrSelection(fmt);
00234 setFocus();
00235 d->activateRichText();
00236 }
00237
00238 void KRichTextEdit::setTextForegroundColor(const QColor &color)
00239 {
00240 QTextCharFormat fmt;
00241 fmt.setForeground(color);
00242 d->mergeFormatOnWordOrSelection(fmt);
00243 setFocus();
00244 d->activateRichText();
00245 }
00246
00247 void KRichTextEdit::setTextBackgroundColor(const QColor &color)
00248 {
00249 QTextCharFormat fmt;
00250 fmt.setBackground(color);
00251 d->mergeFormatOnWordOrSelection(fmt);
00252 setFocus();
00253 d->activateRichText();
00254 }
00255
00256 void KRichTextEdit::setFontFamily(const QString &fontFamily)
00257 {
00258 QTextCharFormat fmt;
00259 fmt.setFontFamily(fontFamily);
00260 d->mergeFormatOnWordOrSelection(fmt);
00261 setFocus();
00262 d->activateRichText();
00263 }
00264
00265 void KRichTextEdit::setFontSize(int size)
00266 {
00267 QTextCharFormat fmt;
00268 fmt.setFontPointSize(size);
00269 d->mergeFormatOnWordOrSelection(fmt);
00270 setFocus();
00271 d->activateRichText();
00272 }
00273
00274 void KRichTextEdit::setFont(const QFont &font)
00275 {
00276 QTextCharFormat fmt;
00277 fmt.setFont(font);
00278 d->mergeFormatOnWordOrSelection(fmt);
00279 setFocus();
00280 d->activateRichText();
00281 }
00282
00283 void KRichTextEdit::switchToPlainText()
00284 {
00285 if (d->mMode == Rich) {
00286 d->mMode = Plain;
00287
00288 document()->setPlainText(document()->toPlainText());
00289 setAcceptRichText(false);
00290 emit textModeChanged(d->mMode);
00291 }
00292 }
00293
00294 void KRichTextEdit::setTextSuperScript(bool superscript)
00295 {
00296 QTextCharFormat fmt;
00297 fmt.setVerticalAlignment(superscript ? QTextCharFormat::AlignSuperScript : QTextCharFormat::AlignNormal);
00298 d->mergeFormatOnWordOrSelection(fmt);
00299 setFocus();
00300 d->activateRichText();
00301 }
00302
00303 void KRichTextEdit::setTextSubScript(bool subscript)
00304 {
00305 QTextCharFormat fmt;
00306 fmt.setVerticalAlignment(subscript ? QTextCharFormat::AlignSubScript : QTextCharFormat::AlignNormal);
00307 d->mergeFormatOnWordOrSelection(fmt);
00308 setFocus();
00309 d->activateRichText();
00310 }
00311
00312 void KRichTextEdit::enableRichTextMode()
00313 {
00314 d->activateRichText();
00315 }
00316
00317 KRichTextEdit::Mode KRichTextEdit::textMode() const
00318 {
00319 return d->mMode;
00320 }
00321
00322 QString KRichTextEdit::textOrHtml() const
00323 {
00324 if (textMode() == Rich)
00325 return toCleanHtml();
00326 else
00327 return toPlainText();
00328 }
00329
00330 void KRichTextEdit::setTextOrHtml(const QString &text)
00331 {
00332
00333 if (Qt::mightBeRichText(text)) {
00334 if (d->mMode == KRichTextEdit::Plain) {
00335 d->activateRichText();
00336 }
00337 setHtml(text);
00338 } else {
00339 setPlainText(text);
00340 }
00341 }
00342
00343 QString KRichTextEdit::currentLinkText() const
00344 {
00345 QTextCursor cursor = textCursor();
00346 selectLinkText(&cursor);
00347 return cursor.selectedText();
00348 }
00349
00350 void KRichTextEdit::selectLinkText() const
00351 {
00352 QTextCursor cursor = textCursor();
00353 selectLinkText(&cursor);
00354 d->setTextCursor(cursor);
00355 }
00356
00357 void KRichTextEdit::selectLinkText(QTextCursor *cursor) const
00358 {
00359
00360 if (cursor->charFormat().isAnchor()) {
00361 QString aHref = cursor->charFormat().anchorHref();
00362
00363
00364 while (cursor->charFormat().anchorHref() == aHref) {
00365 if (cursor->atStart())
00366 break;
00367 cursor->setPosition(cursor->position() - 1);
00368 }
00369 if (cursor->charFormat().anchorHref() != aHref)
00370 cursor->setPosition(cursor->position() + 1, QTextCursor::KeepAnchor);
00371
00372
00373 while (cursor->charFormat().anchorHref() == aHref) {
00374 if (cursor->atEnd())
00375 break;
00376 cursor->setPosition(cursor->position() + 1, QTextCursor::KeepAnchor);
00377 }
00378 if (cursor->charFormat().anchorHref() != aHref)
00379 cursor->setPosition(cursor->position() - 1, QTextCursor::KeepAnchor);
00380 } else if (cursor->hasSelection()) {
00381
00382 } else {
00383
00384
00385 cursor->movePosition(QTextCursor::StartOfWord);
00386 cursor->movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
00387 }
00388 }
00389
00390 QString KRichTextEdit::currentLinkUrl() const
00391 {
00392 return textCursor().charFormat().anchorHref();
00393 }
00394
00395 void KRichTextEdit::updateLink(const QString &linkUrl, const QString &linkText)
00396 {
00397 selectLinkText();
00398
00399 QTextCursor cursor = textCursor();
00400 cursor.beginEditBlock();
00401 if (!cursor.hasSelection()) {
00402 cursor.select(QTextCursor::WordUnderCursor);
00403 }
00404
00405 QTextCharFormat format = cursor.charFormat();
00406 if (!linkUrl.isEmpty()) {
00407 format.setAnchor(true);
00408 format.setAnchorHref(linkUrl);
00409 } else {
00410 format = cursor.block().charFormat();
00411 format.setAnchor(false);
00412 format.setAnchorHref(QString());
00413 }
00414
00415 QString _linkText;
00416
00417 int lowPos = qMin(cursor.selectionStart(), cursor.selectionEnd());
00418 if (!linkText.isEmpty()) {
00419 _linkText = linkText;
00420 } else {
00421 _linkText = linkUrl;
00422 }
00423
00424
00425
00426
00427 cursor.insertText(_linkText, format);
00428
00429
00430
00431
00432
00433
00434 if (!linkUrl.isEmpty()) {
00435 cursor.setPosition(lowPos);
00436 cursor.setPosition(lowPos + _linkText.length(), QTextCursor::KeepAnchor);
00437
00438 if (!cursor.currentList()) {
00439 cursor.insertHtml(cursor.selection().toHtml());
00440 } else {
00441
00442
00443
00444
00445
00446
00447 QString selectionHtml = cursor.selection().toHtml();
00448 QString style = selectionHtml.split("<li style=\"").takeAt(1).split('\"').first();
00449 QString linkTag = "<a" + selectionHtml.split("<a").takeAt(1).split('>').first() + '>'
00450 + "<span style=\"" + style + "\">" + _linkText + "</span></a>";
00451 cursor.insertHtml(linkTag);
00452 }
00453
00454
00455
00456 if (cursor.position() == cursor.block().position() + cursor.block().length() - 1) {
00457 cursor.setCharFormat(cursor.block().charFormat());
00458 cursor.insertText(QString(' '));
00459 }
00460
00461 d->activateRichText();
00462 } else {
00463
00464
00465 QTextCharFormat charFormat;
00466 cursor.setCharFormat(charFormat);
00467 }
00468
00469 cursor.endEditBlock();
00470 }
00471
00472 void KRichTextEdit::keyPressEvent(QKeyEvent *event)
00473 {
00474 bool handled = false;
00475 if (textCursor().currentList()) {
00476
00477
00478 handled = d->nestedListHelper->handleBeforeKeyPressEvent(event);
00479 }
00480
00481 if (!handled) {
00482 KTextEdit::keyPressEvent(event);
00483 }
00484
00485 if (textCursor().currentList()) {
00486 d->nestedListHelper->handleAfterKeyPressEvent(event);
00487 }
00488 emit cursorPositionChanged();
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 bool KRichTextEdit::canIndentList() const
00506 {
00507 return d->nestedListHelper->canIndent();
00508 }
00509
00510 bool KRichTextEdit::canDedentList() const
00511 {
00512 return d->nestedListHelper->canDedent();
00513 }
00514
00515 QString KRichTextEdit::toCleanHtml() const
00516 {
00517
00518
00519 return toHtml();
00520 }
00521
00522 #include "krichtextedit.moc"