00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "krichtextwidget.h"
00022
00023
00024 #include <kactioncollection.h>
00025 #include <kcolordialog.h>
00026 #include <kcolorscheme.h>
00027 #include <kfontaction.h>
00028 #include <kfontsizeaction.h>
00029 #include <klocale.h>
00030 #include <ktoggleaction.h>
00031
00032
00033 #include <QtGui/QTextList>
00034
00035 #include "klinkdialog.h"
00036
00037
00038
00043
00044 class KRichTextWidget::Private
00045 {
00046 public:
00047 Private(KRichTextWidget *parent)
00048 : q(parent),
00049 painterActive(false),
00050 enableRichText(0),
00051 action_text_foreground_color(0),
00052 action_text_background_color(0),
00053 action_text_bold(0),
00054 action_text_italic(0),
00055 action_text_underline(0),
00056 action_text_strikeout(0),
00057 action_font_family(0),
00058 action_font_size(0),
00059 action_list_style(0),
00060 action_list_indent(0),
00061 action_list_dedent(0),
00062 action_manage_link(0),
00063 action_insert_horizontal_rule(0),
00064 action_format_painter(0),
00065 action_to_plain_text(0),
00066 action_align_left(0),
00067 action_align_right(0),
00068 action_align_center(0),
00069 action_align_justify(0)
00070 {
00071 }
00072
00073 KRichTextWidget *q;
00074
00075 bool richTextEnabled;
00076 RichTextSupport richTextSupport;
00077
00078 QTextCharFormat painterFormat;
00079 bool painterActive;
00080
00081 QList<KAction*> richTextActionList;
00082
00083 KToggleAction *enableRichText;
00084
00085 KAction *action_text_foreground_color;
00086 KAction *action_text_background_color;
00087
00088 KToggleAction *action_text_bold;
00089 KToggleAction *action_text_italic;
00090 KToggleAction *action_text_underline;
00091 KToggleAction *action_text_strikeout;
00092
00093 KFontAction *action_font_family;
00094 KFontSizeAction *action_font_size;
00095
00096 KSelectAction *action_list_style;
00097 KAction *action_list_indent;
00098 KAction *action_list_dedent;
00099
00100 KAction *action_manage_link;
00101 KAction *action_insert_horizontal_rule;
00102 KAction *action_format_painter;
00103 KAction *action_to_plain_text;
00104
00105 KToggleAction *action_align_left;
00106 KToggleAction *action_align_right;
00107 KToggleAction *action_align_center;
00108 KToggleAction *action_align_justify;
00109
00110
00111
00112
00113 void init();
00114
00115
00116
00117
00118
00122 void _k_setTextForegroundColor();
00123
00127 void _k_setTextBackgroundColor();
00128
00136 void _k_manageLink();
00137
00143 void _k_formatPainter(bool active);
00144
00148 void _k_updateCharFormatActions(const QTextCharFormat &format);
00149
00154 void _k_updateMiscActions();
00155
00159 void _k_setListStyle(int index);
00160
00161 };
00162
00163
00164 void KRichTextWidget::Private::init()
00165 {
00166 q->setRichTextSupport(KRichTextWidget::FullSupport);
00167 }
00168
00169 KRichTextWidget::KRichTextWidget(QWidget* parent)
00170 : KRichTextEdit(parent),
00171 d(new Private(this))
00172 {
00173 d->init();
00174 }
00175
00176 KRichTextWidget::KRichTextWidget(const QString& text, QWidget *parent)
00177 : KRichTextEdit(text,parent),
00178 d(new Private(this))
00179 {
00180 d->init();
00181 }
00182
00183 KRichTextWidget::~KRichTextWidget()
00184 {
00185 delete d;
00186 }
00187
00188 KRichTextWidget::RichTextSupport KRichTextWidget::richTextSupport() const
00189 {
00190 return d->richTextSupport;
00191 }
00192
00193 void KRichTextWidget::setRichTextSupport(const KRichTextWidget::RichTextSupport &support)
00194 {
00195 d->richTextSupport = support;
00196 }
00197
00198 void KRichTextWidget::createActions(KActionCollection *actionCollection)
00199 {
00200 Q_ASSERT(actionCollection);
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 d->richTextActionList.clear();
00217
00218 if (d->richTextSupport & SupportTextForegroundColor) {
00219
00220 d->action_text_foreground_color = new KAction(KIcon("format-stroke-color"), i18nc("@action", "Text &Color..."), actionCollection);
00221 d->action_text_foreground_color->setIconText(i18nc("@label stroke color", "Color"));
00222 d->richTextActionList.append((d->action_text_foreground_color));
00223 actionCollection->addAction("format_text_foreground_color", d->action_text_foreground_color);
00224 connect(d->action_text_foreground_color, SIGNAL(triggered()), this, SLOT(_k_setTextForegroundColor()));
00225 } else {
00226 actionCollection->removeAction(d->action_text_foreground_color);
00227 d->action_text_foreground_color = 0;
00228 }
00229
00230 if (d->richTextSupport & SupportTextBackgroundColor) {
00231
00232 d->action_text_background_color = new KAction(KIcon("format-fill-color"), i18nc("@action", "Text &Highlight..."), actionCollection);
00233 d->richTextActionList.append((d->action_text_background_color));
00234 actionCollection->addAction("format_text_background_color", d->action_text_background_color);
00235 connect(d->action_text_background_color, SIGNAL(triggered()), this, SLOT(_k_setTextBackgroundColor()));
00236 } else {
00237 actionCollection->removeAction(d->action_text_background_color);
00238 d->action_text_background_color = 0;
00239 }
00240
00241 if (d->richTextSupport & SupportFontFamily) {
00242
00243 d->action_font_family = new KFontAction(i18nc("@action", "&Font"), actionCollection);
00244 d->richTextActionList.append((d->action_font_family));
00245 actionCollection->addAction("format_font_family", d->action_font_family);
00246 connect(d->action_font_family, SIGNAL(triggered(QString)), this, SLOT(setFontFamily(QString)));
00247 } else {
00248 actionCollection->removeAction(d->action_font_family);
00249 d->action_font_family = 0;
00250 }
00251
00252 if (d->richTextSupport & SupportFontSize) {
00253
00254 d->action_font_size = new KFontSizeAction(i18nc("@action", "Font &Size"), actionCollection);
00255 d->richTextActionList.append((d->action_font_size));
00256 actionCollection->addAction("format_font_size", d->action_font_size);
00257 connect(d->action_font_size, SIGNAL(fontSizeChanged(int)), this, SLOT(setFontSize(int)));
00258 } else {
00259 actionCollection->removeAction(d->action_font_size);
00260 d->action_font_size = 0;
00261 }
00262
00263 if (d->richTextSupport & SupportBold) {
00264 d->action_text_bold = new KToggleAction(KIcon("format-text-bold"), i18nc("@action boldify selected text", "&Bold"), actionCollection);
00265 QFont bold;
00266 bold.setBold(true);
00267 d->action_text_bold->setFont(bold);
00268 d->richTextActionList.append((d->action_text_bold));
00269 actionCollection->addAction("format_text_bold", d->action_text_bold);
00270 d->action_text_bold->setShortcut(KShortcut(Qt::CTRL + Qt::Key_B));
00271 connect(d->action_text_bold, SIGNAL(triggered(bool)), this, SLOT(setTextBold(bool)));
00272 } else {
00273 actionCollection->removeAction(d->action_text_bold);
00274 d->action_text_bold = 0;
00275 }
00276
00277 if (d->richTextSupport & SupportItalic) {
00278 d->action_text_italic = new KToggleAction(KIcon("format-text-italic"), i18nc("@action italicize selected text", "&Italic"), actionCollection);
00279 QFont italic;
00280 italic.setItalic(true);
00281 d->action_text_italic->setFont(italic);
00282 d->richTextActionList.append((d->action_text_italic));
00283 actionCollection->addAction("format_text_italic", d->action_text_italic);
00284 d->action_text_italic->setShortcut(KShortcut(Qt::CTRL + Qt::Key_I));
00285 connect(d->action_text_italic, SIGNAL(triggered(bool)),
00286 this, SLOT(setTextItalic(bool)));
00287 } else {
00288 actionCollection->removeAction(d->action_text_italic);
00289 d->action_text_italic = 0;
00290 }
00291
00292 if (d->richTextSupport & SupportUnderline) {
00293 d->action_text_underline = new KToggleAction(KIcon("format-text-underline"), i18nc("@action underline selected text", "&Underline"), actionCollection);
00294 QFont underline;
00295 underline.setUnderline(true);
00296 d->action_text_underline->setFont(underline);
00297 d->richTextActionList.append((d->action_text_underline));
00298 actionCollection->addAction("format_text_underline", d->action_text_underline);
00299 d->action_text_underline->setShortcut(KShortcut(Qt::CTRL + Qt::Key_U));
00300 connect(d->action_text_underline, SIGNAL(triggered(bool)),
00301 this, SLOT(setTextUnderline(bool)));
00302 } else {
00303 actionCollection->removeAction(d->action_text_underline);
00304 d->action_text_underline = 0;
00305 }
00306
00307 if (d->richTextSupport & SupportStrikeOut) {
00308 d->action_text_strikeout = new KToggleAction(KIcon("format-text-strikethrough"), i18nc("@action", "&Strike Out"), actionCollection);
00309 d->richTextActionList.append((d->action_text_strikeout));
00310 actionCollection->addAction("format_text_strikeout", d->action_text_strikeout);
00311 d->action_text_strikeout->setShortcut(KShortcut(Qt::CTRL + Qt::Key_L));
00312 connect(d->action_text_strikeout, SIGNAL(triggered(bool)),
00313 this, SLOT(setTextStrikeOut(bool)));
00314 } else {
00315 actionCollection->removeAction(d->action_text_strikeout);
00316 d->action_text_strikeout = 0;
00317 }
00318
00319 if (d->richTextSupport & SupportAlignment) {
00320
00321 d->action_align_left = new KToggleAction(KIcon("format-justify-left"), i18nc("@action", "Align &Left"), actionCollection);
00322 d->action_align_left->setIconText(i18nc("@label left justify", "Left"));
00323 d->richTextActionList.append((d->action_align_left));
00324 actionCollection->addAction("format_align_left", d->action_align_left);
00325 connect(d->action_align_left, SIGNAL(triggered()),
00326 this, SLOT(alignLeft()));
00327
00328 d->action_align_center = new KToggleAction(KIcon("format-justify-center"), i18nc("@action", "Align &Center"), actionCollection);
00329 d->action_align_center->setIconText(i18nc("@label center justify", "Center"));
00330 d->richTextActionList.append((d->action_align_center));
00331 actionCollection->addAction("format_align_center", d->action_align_center);
00332 connect(d->action_align_center, SIGNAL(triggered()),
00333 this, SLOT(alignCenter()));
00334
00335 d->action_align_right = new KToggleAction(KIcon("format-justify-right"), i18nc("@action", "Align &Right"), actionCollection);
00336 d->action_align_right->setIconText(i18nc("@label right justify", "Right"));
00337 d->richTextActionList.append((d->action_align_right));
00338 actionCollection->addAction("format_align_right", d->action_align_right);
00339 connect(d->action_align_right, SIGNAL(triggered()),
00340 this, SLOT(alignRight()));
00341
00342 d->action_align_justify = new KToggleAction(KIcon("format-justify-fill"), i18nc("@action", "&Justify"), actionCollection);
00343 d->action_align_justify->setIconText(i18nc("@label justify fill", "Justify"));
00344 d->richTextActionList.append((d->action_align_justify));
00345 actionCollection->addAction("format_align_justify", d->action_align_justify);
00346 connect(d->action_align_justify, SIGNAL(triggered()),
00347 this, SLOT(alignJustify()));
00348
00349 QActionGroup *alignmentGroup = new QActionGroup(this);
00350 alignmentGroup->addAction(d->action_align_left);
00351 alignmentGroup->addAction(d->action_align_center);
00352 alignmentGroup->addAction(d->action_align_right);
00353 alignmentGroup->addAction(d->action_align_justify);
00354 } else {
00355
00356 actionCollection->removeAction(d->action_align_left);
00357 actionCollection->removeAction(d->action_align_center);
00358 actionCollection->removeAction(d->action_align_right);
00359 actionCollection->removeAction(d->action_align_justify);
00360
00361 d->action_align_left = 0;
00362 d->action_align_center = 0;
00363 d->action_align_right = 0;
00364 d->action_align_justify = 0;
00365 }
00366
00367 if (d->richTextSupport & SupportChangeListStyle) {
00368 d->action_list_style = new KSelectAction(KIcon("format-list-unordered"), i18nc("@title:menu", "List Style"), actionCollection);
00369 QStringList listStyles;
00370 listStyles << i18nc("@item:inmenu no list style", "None")
00371 << i18nc("@item:inmenu disc list style", "Disc")
00372 << i18nc("@item:inmenu circle list style", "Circle")
00373 << i18nc("@item:inmenu square list style", "Square")
00374 << i18nc("@item:inmenu numbered lists", "123")
00375 << i18nc("@item:inmenu lowercase abc lists", "abc")
00376 << i18nc("@item:inmenu uppercase abc lists", "ABC");
00377 d->action_list_style->setItems(listStyles);
00378 d->action_list_style->setCurrentItem(0);
00379 d->richTextActionList.append((d->action_list_style));
00380 actionCollection->addAction("format_list_style", d->action_list_style);
00381 connect(d->action_list_style, SIGNAL(triggered(int)),
00382 this, SLOT(_k_setListStyle(int)));
00383 connect(d->action_list_style, SIGNAL(triggered()),
00384 this, SLOT(_k_updateMiscActions()));
00385
00386 } else {
00387 actionCollection->removeAction(d->action_list_style);
00388 d->action_list_style = 0;
00389 }
00390
00391 if (d->richTextSupport & SupportIndentLists) {
00392 d->action_list_indent = new KAction(KIcon("format-indent-more"), i18nc("@action", "Increase Indent"), actionCollection);
00393 d->richTextActionList.append((d->action_list_indent));
00394 actionCollection->addAction("format_list_indent_more", d->action_list_indent);
00395 connect(d->action_list_indent, SIGNAL(triggered()),
00396 this, SLOT(indentListMore()));
00397 connect(d->action_list_indent, SIGNAL(triggered()),
00398 this, SLOT(_k_updateMiscActions()));
00399 } else {
00400 actionCollection->removeAction(d->action_list_indent);
00401 d->action_list_indent = 0;
00402 }
00403
00404 if (d->richTextSupport & SupportDedentLists) {
00405 d->action_list_dedent = new KAction(KIcon("format-indent-less"), i18nc("@action", "Decrease Indent"), actionCollection);
00406 d->richTextActionList.append((d->action_list_dedent));
00407 actionCollection->addAction("format_list_indent_less", d->action_list_dedent);
00408 connect(d->action_list_dedent, SIGNAL(triggered()),
00409 this, SLOT(indentListLess()));
00410 connect(d->action_list_dedent, SIGNAL(triggered()),
00411 this, SLOT(_k_updateMiscActions()));
00412 } else {
00413 actionCollection->removeAction(d->action_list_dedent);
00414 d->action_list_dedent = 0;
00415 }
00416
00417 if (d->richTextSupport & SupportRuleLine) {
00418 d->action_insert_horizontal_rule = new KAction(KIcon("insert-horizontal-rule"), i18nc("@action", "Insert Rule Line"), actionCollection);
00419 d->richTextActionList.append((d->action_insert_horizontal_rule));
00420 actionCollection->addAction("insert_horizontal_rule", d->action_insert_horizontal_rule);
00421 connect(d->action_insert_horizontal_rule, SIGNAL(triggered()),
00422 this, SLOT(insertHorizontalRule()));
00423 } else {
00424 actionCollection->removeAction(d->action_insert_horizontal_rule);
00425 d->action_insert_horizontal_rule = 0;
00426 }
00427
00428 if (d->richTextSupport & SupportHyperlinks) {
00429 d->action_manage_link = new KAction(KIcon("insert-link"), i18nc("@action", "Link"), actionCollection);
00430 d->richTextActionList.append((d->action_manage_link));
00431 actionCollection->addAction("manage_link", d->action_manage_link);
00432 connect(d->action_manage_link, SIGNAL(triggered()),
00433 this, SLOT(_k_manageLink()));
00434 } else {
00435 actionCollection->removeAction(d->action_manage_link);
00436 d->action_manage_link = 0;
00437 }
00438
00439 if (d->richTextSupport & SupportFormatPainting) {
00440 d->action_format_painter = new KToggleAction(KIcon("draw-brush"), i18nc("@action", "Format Painter"), actionCollection);
00441 d->richTextActionList.append((d->action_format_painter));
00442 actionCollection->addAction("format_painter", d->action_format_painter);
00443 connect(d->action_format_painter, SIGNAL(toggled(bool)),
00444 this, SLOT(_k_formatPainter(bool)));
00445 } else {
00446 actionCollection->removeAction(d->action_format_painter);
00447 d->action_format_painter = 0;
00448 }
00449
00450 if (d->richTextSupport & SupportToPlainText) {
00451 d->action_to_plain_text = new KToggleAction(i18nc("@action", "To Plain Text"), actionCollection);
00452 d->richTextActionList.append((d->action_to_plain_text));
00453 actionCollection->addAction("action_to_plain_text", d->action_to_plain_text);
00454 connect(d->action_to_plain_text, SIGNAL(triggered()),
00455 this, SLOT(switchToPlainText()));
00456 } else {
00457 actionCollection->removeAction(d->action_to_plain_text);
00458 d->action_to_plain_text = 0;
00459 }
00460
00461 disconnect(this, SIGNAL(currentCharFormatChanged(const QTextCharFormat &)),
00462 this, SLOT(_k_updateCharFormatActions(const QTextCharFormat &)));
00463 disconnect(this, SIGNAL(cursorPositionChanged()),
00464 this, SLOT(_k_updateMiscActions()));
00465 connect(this, SIGNAL(currentCharFormatChanged(const QTextCharFormat &)),
00466 this, SLOT(_k_updateCharFormatActions(const QTextCharFormat &)));
00467 connect(this, SIGNAL(cursorPositionChanged()),
00468 this, SLOT(_k_updateMiscActions()));
00469
00470 d->_k_updateMiscActions();
00471 d->_k_updateCharFormatActions(currentCharFormat());
00472 }
00473
00474
00475 void KRichTextWidget::setActionsEnabled(bool enabled)
00476 {
00477 foreach(QAction* action, d->richTextActionList)
00478 {
00479 action->setEnabled(enabled);
00480 }
00481 d->richTextEnabled = enabled;
00482 }
00483
00484 void KRichTextWidget::Private::_k_setListStyle(int index)
00485 {
00486 q->setListStyle(index);
00487 _k_updateMiscActions();
00488 }
00489
00490 void KRichTextWidget::Private::_k_updateCharFormatActions(const QTextCharFormat &format)
00491 {
00492 QFont f = format.font();
00493
00494 if (richTextSupport & SupportFontFamily) {
00495 action_font_family->setFont(f.family());
00496 }
00497 if (richTextSupport & SupportFontSize) {
00498 if (f.pointSize() > 0)
00499 action_font_size->setFontSize((int)f.pointSize());
00500 }
00501
00502 if (richTextSupport & SupportBold) {
00503 action_text_bold->setChecked(f.bold());
00504 }
00505
00506 if (richTextSupport & SupportItalic) {
00507 action_text_italic->setChecked(f.italic());
00508 }
00509
00510 if (richTextSupport & SupportUnderline) {
00511 action_text_underline->setChecked(f.underline());
00512 }
00513
00514 if (richTextSupport & SupportStrikeOut) {
00515 action_text_strikeout->setChecked(f.strikeOut());
00516 }
00517 }
00518
00519 void KRichTextWidget::Private::_k_updateMiscActions()
00520 {
00521 if (richTextSupport & SupportAlignment) {
00522 Qt::Alignment a = q->alignment();
00523 if (a & Qt::AlignLeft) {
00524 action_align_left->setChecked(true);
00525 } else if (a & Qt::AlignHCenter) {
00526 action_align_center->setChecked(true);
00527 } else if (a & Qt::AlignRight) {
00528 action_align_right->setChecked(true);
00529 } else if (a & Qt::AlignJustify) {
00530 action_align_justify->setChecked(true);
00531 }
00532 }
00533
00534
00535 if (richTextSupport & SupportChangeListStyle) {
00536 if (q->textCursor().currentList()) {
00537 action_list_style->setCurrentItem(-q->textCursor().currentList()->format().style());
00538 } else {
00539 action_list_style->setCurrentItem(0);
00540 }
00541 }
00542
00543
00544 if ( richTextSupport & SupportIndentLists ) {
00545 if ( richTextEnabled ) {
00546 action_list_indent->setEnabled( q->canIndentList() );
00547 } else {
00548 action_list_indent->setEnabled( false );
00549 }
00550 }
00551
00552 if ( richTextSupport & SupportDedentLists ) {
00553 if ( richTextEnabled ) {
00554 action_list_dedent->setEnabled( q->canDedentList() );
00555 } else {
00556 action_list_dedent->setEnabled( false );
00557 }
00558 }
00559
00560 }
00561
00562 void KRichTextWidget::Private::_k_setTextForegroundColor()
00563 {
00564 QColor currentTextForegroundColor = q->textColor();
00565
00566 int result = KColorDialog::getColor(currentTextForegroundColor, KColorScheme(QPalette::Active, KColorScheme::View).foreground().color() , q);
00567 if (!currentTextForegroundColor.isValid())
00568 currentTextForegroundColor = KColorScheme(QPalette::Active, KColorScheme::View).foreground().color() ;
00569 if (result != QDialog::Accepted)
00570 return;
00571
00572 q->setTextForegroundColor(currentTextForegroundColor);
00573
00574 }
00575
00576 void KRichTextWidget::Private::_k_setTextBackgroundColor()
00577 {
00578 QTextCharFormat fmt = q->textCursor().charFormat();
00579 QColor currentTextBackgroundColor = fmt.background().color();
00580
00581 int result = KColorDialog::getColor(currentTextBackgroundColor, KColorScheme(QPalette::Active, KColorScheme::View).foreground().color() , q);
00582 if (!currentTextBackgroundColor.isValid())
00583 currentTextBackgroundColor = KColorScheme(QPalette::Active, KColorScheme::View).foreground().color() ;
00584 if (result != QDialog::Accepted)
00585 return;
00586
00587 q->setTextBackgroundColor(currentTextBackgroundColor);
00588
00589 }
00590
00591 void KRichTextWidget::Private::_k_manageLink()
00592 {
00593 q->selectLinkText();
00594 KLinkDialog *linkDialog = new KLinkDialog(q);
00595 linkDialog->setLinkText(q->currentLinkText());
00596 linkDialog->setLinkUrl(q->currentLinkUrl());
00597
00598 if (linkDialog->exec()) {
00599 q->updateLink(linkDialog->linkUrl(), linkDialog->linkText());
00600 }
00601
00602 delete linkDialog;
00603
00604 }
00605
00606 void KRichTextWidget::mouseReleaseEvent(QMouseEvent *event)
00607 {
00608 if (d->painterActive) {
00609
00610
00611 if (textCursor().hasSelection()) {
00612 textCursor().setCharFormat(d->painterFormat);
00613 }
00614 d->painterActive = false;
00615 d->action_format_painter->setChecked(false);
00616 }
00617 KRichTextEdit::mouseReleaseEvent(event);
00618 }
00619
00620 void KRichTextWidget::Private::_k_formatPainter(bool active)
00621 {
00622 if (active) {
00623 painterFormat = q->currentCharFormat();
00624 painterActive = true;
00625 q->viewport()->setCursor(QCursor(KIcon("draw-brush").pixmap(32, 32), 0, 32));
00626 } else {
00627 painterFormat = QTextCharFormat();
00628 painterActive = false;
00629 q->viewport()->setCursor(Qt::IBeamCursor);
00630 }
00631 }
00632
00633 void KRichTextWidget::updateActionStates()
00634 {
00635 d->_k_updateMiscActions();
00636 d->_k_updateCharFormatActions(currentCharFormat());
00637 }
00638
00639
00640 #include "krichtextwidget.moc"