34 #include <QtGui/QTextList>
45 class KRichTextWidget::Private
51 richTextEnabled(false),
53 action_text_foreground_color(0),
54 action_text_background_color(0),
56 action_text_italic(0),
57 action_text_underline(0),
58 action_text_strikeout(0),
59 action_font_family(0),
62 action_list_indent(0),
63 action_list_dedent(0),
64 action_manage_link(0),
65 action_insert_horizontal_rule(0),
66 action_format_painter(0),
67 action_to_plain_text(0),
69 action_align_right(0),
70 action_align_center(0),
71 action_align_justify(0),
72 action_direction_ltr(0),
73 action_direction_rtl(0),
74 action_text_superscript(0),
75 action_text_subscript(0)
83 QTextCharFormat painterFormat;
86 QList<KAction*> richTextActionList;
91 KAction *action_text_foreground_color;
92 KAction *action_text_background_color;
107 KAction *action_insert_horizontal_rule;
108 KAction *action_format_painter;
134 void _k_setTextForegroundColor();
139 void _k_setTextBackgroundColor();
148 void _k_manageLink();
155 void _k_formatPainter(
bool active);
160 void _k_updateCharFormatActions(
const QTextCharFormat &format);
166 void _k_updateMiscActions();
171 void _k_setListStyle(
int index);
176 void KRichTextWidget::Private::init()
202 return d->richTextSupport;
207 d->richTextSupport = support;
212 Q_ASSERT(actionCollection);
228 d->richTextActionList.clear();
232 d->action_text_foreground_color =
new KAction(
KIcon(
"format-stroke-color"),
i18nc(
"@action",
"Text &Color..."), actionCollection);
233 d->action_text_foreground_color->setIconText(
i18nc(
"@label stroke color",
"Color"));
234 d->richTextActionList.append((d->action_text_foreground_color));
235 actionCollection->
addAction(
"format_text_foreground_color", d->action_text_foreground_color);
236 connect(d->action_text_foreground_color, SIGNAL(triggered()),
this, SLOT(_k_setTextForegroundColor()));
238 actionCollection->
removeAction(d->action_text_foreground_color);
239 d->action_text_foreground_color = 0;
244 d->action_text_background_color =
new KAction(
KIcon(
"format-fill-color"),
i18nc(
"@action",
"Text &Highlight..."), actionCollection);
245 d->richTextActionList.append((d->action_text_background_color));
246 actionCollection->
addAction(
"format_text_background_color", d->action_text_background_color);
247 connect(d->action_text_background_color, SIGNAL(triggered()),
this, SLOT(_k_setTextBackgroundColor()));
249 actionCollection->
removeAction(d->action_text_background_color);
250 d->action_text_background_color = 0;
255 d->action_font_family =
new KFontAction(
i18nc(
"@action",
"&Font"), actionCollection);
256 d->richTextActionList.append((d->action_font_family));
257 actionCollection->
addAction(
"format_font_family", d->action_font_family);
261 d->action_font_family = 0;
267 d->richTextActionList.append((d->action_font_size));
268 actionCollection->
addAction(
"format_font_size", d->action_font_size);
269 connect(d->action_font_size, SIGNAL(fontSizeChanged(
int)),
this, SLOT(
setFontSize(
int)));
272 d->action_font_size = 0;
276 d->action_text_bold =
new KToggleAction(
KIcon(
"format-text-bold"),
i18nc(
"@action boldify selected text",
"&Bold"), actionCollection);
279 d->action_text_bold->setFont(bold);
280 d->richTextActionList.append((d->action_text_bold));
281 actionCollection->
addAction(
"format_text_bold", d->action_text_bold);
283 connect(d->action_text_bold, SIGNAL(triggered(
bool)),
this, SLOT(
setTextBold(
bool)));
286 d->action_text_bold = 0;
290 d->action_text_italic =
new KToggleAction(
KIcon(
"format-text-italic"),
i18nc(
"@action italicize selected text",
"&Italic"), actionCollection);
292 italic.setItalic(
true);
293 d->action_text_italic->setFont(italic);
294 d->richTextActionList.append((d->action_text_italic));
295 actionCollection->
addAction(
"format_text_italic", d->action_text_italic);
297 connect(d->action_text_italic, SIGNAL(triggered(
bool)),
301 d->action_text_italic = 0;
305 d->action_text_underline =
new KToggleAction(
KIcon(
"format-text-underline"),
i18nc(
"@action underline selected text",
"&Underline"), actionCollection);
307 underline.setUnderline(
true);
308 d->action_text_underline->setFont(underline);
309 d->richTextActionList.append((d->action_text_underline));
310 actionCollection->
addAction(
"format_text_underline", d->action_text_underline);
312 connect(d->action_text_underline, SIGNAL(triggered(
bool)),
315 actionCollection->
removeAction(d->action_text_underline);
316 d->action_text_underline = 0;
320 d->action_text_strikeout =
new KToggleAction(
KIcon(
"format-text-strikethrough"),
i18nc(
"@action",
"&Strike Out"), actionCollection);
321 d->richTextActionList.append((d->action_text_strikeout));
322 actionCollection->
addAction(
"format_text_strikeout", d->action_text_strikeout);
324 connect(d->action_text_strikeout, SIGNAL(triggered(
bool)),
327 actionCollection->
removeAction(d->action_text_strikeout);
328 d->action_text_strikeout = 0;
333 d->action_align_left =
new KToggleAction(
KIcon(
"format-justify-left"),
i18nc(
"@action",
"Align &Left"), actionCollection);
334 d->action_align_left->setIconText(
i18nc(
"@label left justify",
"Left"));
335 d->richTextActionList.append((d->action_align_left));
336 actionCollection->
addAction(
"format_align_left", d->action_align_left);
337 connect(d->action_align_left, SIGNAL(triggered()),
340 d->action_align_center =
new KToggleAction(
KIcon(
"format-justify-center"),
i18nc(
"@action",
"Align &Center"), actionCollection);
341 d->action_align_center->setIconText(
i18nc(
"@label center justify",
"Center"));
342 d->richTextActionList.append((d->action_align_center));
343 actionCollection->
addAction(
"format_align_center", d->action_align_center);
344 connect(d->action_align_center, SIGNAL(triggered()),
347 d->action_align_right =
new KToggleAction(
KIcon(
"format-justify-right"),
i18nc(
"@action",
"Align &Right"), actionCollection);
348 d->action_align_right->setIconText(
i18nc(
"@label right justify",
"Right"));
349 d->richTextActionList.append((d->action_align_right));
350 actionCollection->
addAction(
"format_align_right", d->action_align_right);
351 connect(d->action_align_right, SIGNAL(triggered()),
354 d->action_align_justify =
new KToggleAction(
KIcon(
"format-justify-fill"),
i18nc(
"@action",
"&Justify"), actionCollection);
355 d->action_align_justify->setIconText(
i18nc(
"@label justify fill",
"Justify"));
356 d->richTextActionList.append((d->action_align_justify));
357 actionCollection->
addAction(
"format_align_justify", d->action_align_justify);
358 connect(d->action_align_justify, SIGNAL(triggered()),
361 QActionGroup *alignmentGroup =
new QActionGroup(
this);
362 alignmentGroup->addAction(d->action_align_left);
363 alignmentGroup->addAction(d->action_align_center);
364 alignmentGroup->addAction(d->action_align_right);
365 alignmentGroup->addAction(d->action_align_justify);
371 actionCollection->
removeAction(d->action_align_justify);
373 d->action_align_left = 0;
374 d->action_align_center = 0;
375 d->action_align_right = 0;
376 d->action_align_justify = 0;
380 d->action_direction_ltr =
new KToggleAction(
KIcon(
"format-text-direction-ltr"),
i18nc(
"@action",
"Left-to-Right"), actionCollection);
381 d->action_direction_ltr->setIconText(
i18nc(
"@label left-to-right",
"Left-to-Right"));
382 d->richTextActionList.append(d->action_direction_ltr);
383 actionCollection->
addAction(
"direction_ltr", d->action_direction_ltr);
384 connect(d->action_direction_ltr, SIGNAL(triggered()),
387 d->action_direction_rtl =
new KToggleAction(
KIcon(
"format-text-direction-rtl"),
i18nc(
"@action",
"Right-to-Left"), actionCollection);
388 d->action_direction_rtl->setIconText(
i18nc(
"@label right-to-left",
"Right-to-Left"));
389 d->richTextActionList.append(d->action_direction_rtl);
390 actionCollection->
addAction(
"direction_rtl", d->action_direction_rtl);
391 connect(d->action_direction_rtl, SIGNAL(triggered()),
394 QActionGroup *directionGroup =
new QActionGroup(
this);
395 directionGroup->addAction(d->action_direction_ltr);
396 directionGroup->addAction(d->action_direction_rtl);
398 actionCollection->
removeAction(d->action_direction_ltr);
399 actionCollection->
removeAction(d->action_direction_rtl);
401 d->action_direction_ltr = 0;
402 d->action_direction_rtl = 0;
406 d->action_list_style =
new KSelectAction(
KIcon(
"format-list-unordered"),
i18nc(
"@title:menu",
"List Style"), actionCollection);
408 listStyles <<
i18nc(
"@item:inmenu no list style",
"None")
409 <<
i18nc(
"@item:inmenu disc list style",
"Disc")
410 <<
i18nc(
"@item:inmenu circle list style",
"Circle")
411 <<
i18nc(
"@item:inmenu square list style",
"Square")
412 <<
i18nc(
"@item:inmenu numbered lists",
"123")
413 <<
i18nc(
"@item:inmenu lowercase abc lists",
"abc")
414 <<
i18nc(
"@item:inmenu uppercase abc lists",
"ABC")
415 <<
i18nc(
"@item:inmenu lower case roman numerals",
"i ii iii")
416 <<
i18nc(
"@item:inmenu upper case roman numerals",
"I II III");
418 d->action_list_style->setItems(listStyles);
419 d->action_list_style->setCurrentItem(0);
420 d->richTextActionList.append((d->action_list_style));
421 actionCollection->
addAction(
"format_list_style", d->action_list_style);
422 connect(d->action_list_style, SIGNAL(triggered(
int)),
423 this, SLOT(_k_setListStyle(
int)));
424 connect(d->action_list_style, SIGNAL(triggered()),
425 this, SLOT(_k_updateMiscActions()));
429 d->action_list_style = 0;
433 d->action_list_indent =
new KAction(
KIcon(
"format-indent-more"),
i18nc(
"@action",
"Increase Indent"), actionCollection);
434 d->richTextActionList.append((d->action_list_indent));
435 actionCollection->
addAction(
"format_list_indent_more", d->action_list_indent);
436 connect(d->action_list_indent, SIGNAL(triggered()),
438 connect(d->action_list_indent, SIGNAL(triggered()),
439 this, SLOT(_k_updateMiscActions()));
442 d->action_list_indent = 0;
446 d->action_list_dedent =
new KAction(
KIcon(
"format-indent-less"),
i18nc(
"@action",
"Decrease Indent"), actionCollection);
447 d->richTextActionList.append((d->action_list_dedent));
448 actionCollection->
addAction(
"format_list_indent_less", d->action_list_dedent);
449 connect(d->action_list_dedent, SIGNAL(triggered()),
451 connect(d->action_list_dedent, SIGNAL(triggered()),
452 this, SLOT(_k_updateMiscActions()));
455 d->action_list_dedent = 0;
459 d->action_insert_horizontal_rule =
new KAction(
KIcon(
"insert-horizontal-rule"),
i18nc(
"@action",
"Insert Rule Line"), actionCollection);
460 d->richTextActionList.append((d->action_insert_horizontal_rule));
461 actionCollection->
addAction(
"insert_horizontal_rule", d->action_insert_horizontal_rule);
462 connect(d->action_insert_horizontal_rule, SIGNAL(triggered()),
465 actionCollection->
removeAction(d->action_insert_horizontal_rule);
466 d->action_insert_horizontal_rule = 0;
470 d->action_manage_link =
new KAction(
KIcon(
"insert-link"),
i18nc(
"@action",
"Link"), actionCollection);
471 d->richTextActionList.append((d->action_manage_link));
472 actionCollection->
addAction(
"manage_link", d->action_manage_link);
473 connect(d->action_manage_link, SIGNAL(triggered()),
474 this, SLOT(_k_manageLink()));
477 d->action_manage_link = 0;
481 d->action_format_painter =
new KToggleAction(
KIcon(
"draw-brush"),
i18nc(
"@action",
"Format Painter"), actionCollection);
482 d->richTextActionList.append((d->action_format_painter));
483 actionCollection->
addAction(
"format_painter", d->action_format_painter);
484 connect(d->action_format_painter, SIGNAL(toggled(
bool)),
485 this, SLOT(_k_formatPainter(
bool)));
487 actionCollection->
removeAction(d->action_format_painter);
488 d->action_format_painter = 0;
492 d->action_to_plain_text =
new KToggleAction(
i18nc(
"@action",
"To Plain Text"), actionCollection);
493 d->richTextActionList.append((d->action_to_plain_text));
494 actionCollection->
addAction(
"action_to_plain_text", d->action_to_plain_text);
495 connect(d->action_to_plain_text, SIGNAL(triggered()),
498 actionCollection->
removeAction(d->action_to_plain_text);
499 d->action_to_plain_text = 0;
503 d->action_text_subscript =
new KToggleAction(
KIcon(
"format-text-subscript"),
i18nc(
"@action",
"Subscript"), actionCollection);
504 d->richTextActionList.append((d->action_text_subscript));
505 actionCollection->
addAction(
"format_text_subscript", d->action_text_subscript);
507 connect(d->action_text_subscript, SIGNAL(triggered(
bool)),
510 d->action_text_superscript =
new KToggleAction(
KIcon(
"format-text-superscript"),
i18nc(
"@action",
"Superscript"), actionCollection);
511 d->richTextActionList.append((d->action_text_superscript));
512 actionCollection->
addAction(
"format_text_superscript", d->action_text_superscript);
514 connect(d->action_text_superscript, SIGNAL(triggered(
bool)),
517 actionCollection->
removeAction(d->action_text_subscript);
518 d->action_text_subscript = 0;
520 actionCollection->
removeAction(d->action_text_superscript);
521 d->action_text_superscript = 0;
525 disconnect(
this, SIGNAL(currentCharFormatChanged(QTextCharFormat)),
526 this, SLOT(_k_updateCharFormatActions(QTextCharFormat)));
527 disconnect(
this, SIGNAL(cursorPositionChanged()),
528 this, SLOT(_k_updateMiscActions()));
529 connect(
this, SIGNAL(currentCharFormatChanged(QTextCharFormat)),
530 this, SLOT(_k_updateCharFormatActions(QTextCharFormat)));
531 connect(
this, SIGNAL(cursorPositionChanged()),
532 this, SLOT(_k_updateMiscActions()));
534 d->_k_updateMiscActions();
535 d->_k_updateCharFormatActions(currentCharFormat());
541 foreach(
QAction* action, d->richTextActionList)
543 action->setEnabled(enabled);
545 d->richTextEnabled = enabled;
548 void KRichTextWidget::Private::_k_setListStyle(
int index)
550 q->setListStyle(index);
551 _k_updateMiscActions();
554 void KRichTextWidget::Private::_k_updateCharFormatActions(
const QTextCharFormat &format)
556 QFont f = format.font();
558 if (richTextSupport & SupportFontFamily) {
559 action_font_family->setFont(f.family());
561 if (richTextSupport & SupportFontSize) {
562 if (f.pointSize() > 0)
563 action_font_size->setFontSize((
int)f.pointSize());
566 if (richTextSupport & SupportBold) {
567 action_text_bold->setChecked(f.bold());
570 if (richTextSupport & SupportItalic) {
571 action_text_italic->setChecked(f.italic());
574 if (richTextSupport & SupportUnderline) {
575 action_text_underline->setChecked(f.underline());
578 if (richTextSupport & SupportStrikeOut) {
579 action_text_strikeout->setChecked(f.strikeOut());
582 if (richTextSupport & SupportSuperScriptAndSubScript) {
583 QTextCharFormat::VerticalAlignment vAlign = format.verticalAlignment();
584 action_text_superscript->setChecked(vAlign == QTextCharFormat::AlignSuperScript);
585 action_text_subscript->setChecked(vAlign == QTextCharFormat::AlignSubScript);
589 void KRichTextWidget::Private::_k_updateMiscActions()
591 if (richTextSupport & SupportAlignment) {
592 Qt::Alignment a = q->alignment();
593 if (a & Qt::AlignLeft) {
594 action_align_left->setChecked(
true);
595 }
else if (a & Qt::AlignHCenter) {
596 action_align_center->setChecked(
true);
597 }
else if (a & Qt::AlignRight) {
598 action_align_right->setChecked(
true);
599 }
else if (a & Qt::AlignJustify) {
600 action_align_justify->setChecked(
true);
605 if (richTextSupport & SupportChangeListStyle) {
606 if (q->textCursor().currentList()) {
607 action_list_style->setCurrentItem(-q->textCursor().currentList()->format().style());
609 action_list_style->setCurrentItem(0);
614 if ( richTextSupport & SupportIndentLists ) {
615 if ( richTextEnabled ) {
616 action_list_indent->setEnabled( q->canIndentList() );
618 action_list_indent->setEnabled(
false );
622 if ( richTextSupport & SupportDedentLists ) {
623 if ( richTextEnabled ) {
624 action_list_dedent->setEnabled( q->canDedentList() );
626 action_list_dedent->setEnabled(
false );
630 if (richTextSupport & SupportDirection) {
631 const Qt::LayoutDirection direction = q->textCursor().blockFormat().layoutDirection();
632 action_direction_ltr->setChecked(direction == Qt::LeftToRight);
633 action_direction_rtl->setChecked(direction == Qt::RightToLeft);
637 void KRichTextWidget::Private::_k_setTextForegroundColor()
639 QColor currentTextForegroundColor = q->textColor();
642 if (result != QDialog::Accepted)
644 if (!currentTextForegroundColor.isValid())
647 q->setTextForegroundColor(currentTextForegroundColor);
651 void KRichTextWidget::Private::_k_setTextBackgroundColor()
653 QTextCharFormat fmt = q->textCursor().charFormat();
654 QColor currentTextBackgroundColor = fmt.background().color();
657 if (result != QDialog::Accepted)
659 if (!currentTextBackgroundColor.isValid())
662 q->setTextBackgroundColor(currentTextBackgroundColor);
666 void KRichTextWidget::Private::_k_manageLink()
669 KLinkDialog *linkDialog =
new KLinkDialog(q);
670 linkDialog->setLinkText(q->currentLinkText());
671 linkDialog->setLinkUrl(q->currentLinkUrl());
673 if (linkDialog->exec()) {
674 q->updateLink(linkDialog->linkUrl(), linkDialog->linkText());
683 if (d->painterActive) {
686 if (textCursor().hasSelection()) {
687 textCursor().setCharFormat(d->painterFormat);
689 d->painterActive =
false;
690 d->action_format_painter->setChecked(
false);
695 void KRichTextWidget::Private::_k_formatPainter(
bool active)
698 painterFormat = q->currentCharFormat();
699 painterActive =
true;
700 q->viewport()->setCursor(
QCursor(
KIcon(
"draw-brush").pixmap(32, 32), 0, 32));
702 painterFormat = QTextCharFormat();
703 painterActive =
false;
704 q->viewport()->setCursor(Qt::IBeamCursor);
710 d->_k_updateMiscActions();
711 d->_k_updateCharFormatActions(currentCharFormat());
715 #include "krichtextwidget.moc"