28 #include <kactioncollection.h>
29 #include <kactionmenu.h>
30 #include <klocalizedstring.h>
31 #include <ktoggleaction.h>
32 #include <kcolorscheme.h>
33 #include <KConfigGroup>
37 #include <QtCore/QEvent>
39 #include <QtGui/QTextCursor>
40 #include <QtGui/QTextCharFormat>
41 #include <QTextDocumentFragment>
50 class KopeteRichTextWidget::Private
53 Private(
KopeteRichTextWidget *parent, KActionCollection *ac, Kopete::Protocol::Capabilities caps)
54 : q(parent), actionCollection(ac), protocolCaps(caps), resettingCharFormat(false), empty(true), updating(false), changingTextMode(false),
55 checkSpelling(0), toggleRichText(0), reset(0)
60 KActionCollection *actionCollection;
62 QList<QKeySequence> sendKeySequenceList;
64 const Kopete::Protocol::Capabilities protocolCaps;
70 QTextCharFormat lastCharFormat;
71 bool resettingCharFormat;
76 bool changingTextMode;
78 KToggleAction* autoResize;
79 KToggleAction* checkSpelling;
80 KToggleAction* toggleRichText;
83 void mergeAll(
const QTextCharFormat& format);
89 d(new Private(this, actionCollection, protocolCaps))
91 connect(
this, SIGNAL(textModeChanged(KRichTextEdit::Mode)),
95 setRichTextSupport(KopeteRichTextWidget::DisableRichText);
96 d->changingTextMode =
true;
98 d->changingTextMode =
false;
100 setCurrentPlainCharFormat(d->defaultPlainFormat);
102 connect(
this, SIGNAL(currentCharFormatChanged(QTextCharFormat)),
105 connect(
this, SIGNAL(textChanged()),
111 KConfigGroup configGroupMode( KGlobal::config(), QLatin1String(
"KopeteChatWindowGroupMode" ));
112 KConfigGroup configIndividual( KGlobal::config(), QLatin1String(
"KopeteChatWindowIndividualMode" ));
113 configGroupMode.writeEntry(
"AutoResize", d->autoResize->isChecked());
114 configIndividual.writeEntry(
"AutoResize", d->autoResize->isChecked());
120 if (Qt::mightBeRichText(text))
128 setPlainText(doc.toPlainText());
139 setCheckSpellingEnabled(b);
144 int currentFontHeight = QFontMetrics(font()).height();
145 int difference = document()->size().toSize().height() - size().height() + currentFontHeight;
153 connect(
this, SIGNAL(textChanged()),
164 KConfigGroup config(KGlobal::config(), QLatin1String(
"KopeteChatWindowIndividualMode"));
166 bool autoResizeEnabled = config.readEntry(
"AutoResize",
true);
167 d->autoResize =
new KToggleAction( i18n(
"Input auto-resize"), actionCollection );
169 d->autoResize->setChecked(autoResizeEnabled);
171 actionCollection->addAction(
"enable_autoresize", d->autoResize );
173 if (!d->checkSpelling)
175 d->checkSpelling =
new KToggleAction(KIcon(
"tools-check-spelling"), i18n(
"Automatic Spell Checking"), actionCollection);
176 actionCollection->addAction(
"enable_auto_spell_check", d->checkSpelling);
177 d->checkSpelling->setChecked(
true);
181 bool richTextSupport = (getProtocolRichTextSupport() != KopeteRichTextWidget::DisableRichText);
182 if (!d->toggleRichText && richTextSupport)
184 d->toggleRichText =
new KToggleAction(KIcon(
"draw-freehand"), i18n(
"Enable &Rich Text"), actionCollection);
185 actionCollection->addAction(
"enable_richtext", d->toggleRichText);
187 connect(d->toggleRichText, SIGNAL(toggled(
bool)),
this, SLOT(
setRichTextEnabled(
bool)));
189 else if (d->toggleRichText && !richTextSupport)
191 actionCollection->removeAction(d->toggleRichText);
192 d->toggleRichText = 0;
197 d->reset =
new KAction(KIcon(
"format-stroke-color"), i18n(
"Reset Font And Color"), actionCollection);
198 actionCollection->addAction(
"format_font_and_color_reset", d->reset);
203 actionCollection->removeAction(d->reset);
207 KRichTextWidget::createActions(actionCollection);
211 disconnect(
this, SIGNAL(currentCharFormatChanged(QTextCharFormat)),
212 this, SLOT(_k_updateCharFormatActions(QTextCharFormat)));
220 KopeteRichTextWidget::RichTextSupport richText = getProtocolRichTextSupport();
221 if (enable && richText != KopeteRichTextWidget::DisableRichText)
223 setRichTextSupport(richText);
224 d->changingTextMode =
true;
225 enableRichTextMode();
226 d->changingTextMode =
false;
232 setRichTextSupport(KopeteRichTextWidget::DisableRichText);
233 d->changingTextMode =
true;
235 d->changingTextMode =
false;
237 setCurrentPlainCharFormat(d->defaultPlainFormat);
240 if (d->toggleRichText)
256 d->currentRichFormat.setFontFamily(family);
260 if (d->protocolCaps & Kopete::Protocol::BaseFont)
262 QTextCharFormat format;
263 format.setFontFamily(family);
268 KRichTextWidget::setFontFamily(family);
274 d->currentRichFormat.setFontPointSize(size);
278 if (d->protocolCaps & Kopete::Protocol::BaseFont)
280 QTextCharFormat format;
281 format.setFontPointSize(size);
286 KRichTextWidget::setFontSize(size);
292 QFont font = d->currentRichFormat.font();
294 d->currentRichFormat.setFont(font);
299 if (d->protocolCaps & Kopete::Protocol::BaseBFormatting)
301 QTextCharFormat format;
302 format.setFontWeight(d->currentRichFormat.fontWeight());
307 KRichTextWidget::setTextBold(bold);
313 d->currentRichFormat.setFontItalic(italic);
317 if (d->protocolCaps & Kopete::Protocol::BaseIFormatting)
319 QTextCharFormat format;
320 format.setFontItalic(italic);
325 KRichTextWidget::setTextItalic(italic);
331 d->currentRichFormat.setFontUnderline(underline);
335 if (d->protocolCaps & Kopete::Protocol::BaseUFormatting)
337 QTextCharFormat format;
338 format.setFontItalic(underline);
343 KRichTextWidget::setTextUnderline(underline);
349 kDebug() <<
"Strikeout not supported!";
352 void KopeteRichTextWidget::setCurrentCharFormat(
const QTextCharFormat & format)
354 d->lastCharFormat = format;
355 KRichTextWidget::setCurrentCharFormat(format);
361 if (d->resettingCharFormat)
364 if (f != QTextCharFormat() || !document()->isEmpty())
366 d->lastCharFormat = f;
367 bool bOpaque = d->lastCharFormat.foreground().isOpaque();
368 bool fOpaque = d->lastCharFormat.background().isOpaque();
371 d->lastCharFormat.setForeground(palette().color(QPalette::Active, QPalette::Text));
373 d->lastCharFormat.setBackground(palette().color(QPalette::Active, QPalette::Base));
375 if (!fOpaque || !bOpaque)
377 d->resettingCharFormat =
true;
378 KRichTextWidget::setCurrentCharFormat(d->lastCharFormat);
379 d->resettingCharFormat =
false;
384 d->currentRichFormat = d->lastCharFormat;
386 if (d->protocolCaps & Kopete::Protocol::BaseBgColor)
388 QPalette palette = this->palette();
389 palette.setColor(QPalette::Active, QPalette::Base, d->lastCharFormat.background().color());
390 palette.setColor(QPalette::Inactive, QPalette::Base, d->lastCharFormat.background().color());
391 this->setPalette(palette);
397 d->resettingCharFormat =
true;
398 KRichTextWidget::setCurrentCharFormat(d->lastCharFormat);
399 d->resettingCharFormat =
false;
401 updateActionStates();
409 bool empty = document()->isEmpty();
410 if (!empty && d->empty)
413 QTextCursor cursor = textCursor();
414 cursor.beginEditBlock();
415 cursor.select(QTextCursor::Document);
416 cursor.mergeCharFormat(d->currentRichFormat);
417 mergeCurrentCharFormat(d->currentRichFormat);
418 cursor.endEditBlock();
427 if (source->hasUrls())
429 QList<QUrl> urls = source->urls();
432 textCursor().insertText(urls[0].toString());
438 if (source->hasHtml())
440 d->empty = d->empty && source->html().isEmpty();
444 QTextDocumentFragment frag = QTextDocumentFragment::fromHtml(source->html());
445 d->empty = frag.toPlainText().trimmed().isEmpty();
449 KRichTextWidget::insertFromMimeData(source);
454 if (event->type() == QEvent::ShortcutOverride)
456 QKeyEvent *keyEvent =
dynamic_cast<QKeyEvent*
>(
event);
459 if (keyEvent->matches(QKeySequence::Copy) && !textCursor().hasSelection())
465 return QWidget::event(event);
467 if ((keyEvent->matches(QKeySequence::MoveToPreviousPage) || keyEvent->matches(QKeySequence::MoveToNextPage))
468 && document()->isEmpty())
472 return QWidget::event(event);
476 if (event->type() == QEvent::ShortcutOverride ||
event->type() == QEvent::KeyRelease ||
event->type() == QEvent::KeyPress){
477 QKeyEvent *keyEvent =
dynamic_cast<QKeyEvent*
>(
event);
480 QKeySequence keyEventSequance(keyEvent->modifiers() + keyEvent->key());
481 foreach(
const QKeySequence& sendKeySequence, d->sendKeySequenceList)
483 if (keyEventSequance.matches(sendKeySequence))
491 return KRichTextWidget::event(event);
496 d->sendKeySequenceList = keySequenceList;
501 d->defaultPlainFormat = format;
502 setCurrentPlainCharFormat(d->defaultPlainFormat);
505 void KopeteRichTextWidget::setCurrentPlainCharFormat(
const QTextCharFormat & format)
510 setCurrentCharFormat(format);
514 QPalette palette = this->palette();
515 palette.setColor(QPalette::Active, QPalette::Base, format.background().color());
516 palette.setColor(QPalette::Inactive, QPalette::Base, format.background().color());
517 this->setPalette(palette);
522 bool usingDefaultFormat = (d->defaultRichFormat == d->currentRichFormat);
524 d->defaultRichFormat = format;
525 if (usingDefaultFormat)
531 d->currentRichFormat = format;
535 setCurrentCharFormat(format);
536 if (d->protocolCaps & (Kopete::Protocol::BaseFormatting | Kopete::Protocol::BaseColor))
542 if (d->protocolCaps & Kopete::Protocol::BaseBgColor)
543 color = format.background().color();
545 color = KColorScheme(QPalette::Active, KColorScheme::View).background().color();
547 QPalette palette = this->palette();
548 palette.setColor(QPalette::Active, QPalette::Base, color);
549 palette.setColor(QPalette::Inactive, QPalette::Base, color);
550 this->setPalette(palette);
556 return d->defaultPlainFormat;
561 return d->defaultRichFormat;
566 return d->currentRichFormat;
571 return (textMode() == KopeteRichTextWidget::Rich);
576 if (d->changingTextMode ==
false)
578 kWarning() <<
"Unexpected text mode change!!!";
579 kWarning() << kBacktrace();
583 KopeteRichTextWidget::RichTextSupport KopeteRichTextWidget::getProtocolRichTextSupport()
const
585 KopeteRichTextWidget::RichTextSupport richText = KopeteRichTextWidget::DisableRichText;
588 if ((d->protocolCaps & Kopete::Protocol::BaseBFormatting) || (d->protocolCaps & Kopete::Protocol::RichBFormatting))
590 richText |= KopeteRichTextWidget::SupportBold;
593 if ((d->protocolCaps & Kopete::Protocol::BaseIFormatting) || (d->protocolCaps & Kopete::Protocol::RichIFormatting))
595 richText |= KopeteRichTextWidget::SupportItalic;
598 if ((d->protocolCaps & Kopete::Protocol::BaseUFormatting) || (d->protocolCaps & Kopete::Protocol::RichUFormatting))
600 richText |= KopeteRichTextWidget::SupportUnderline;
603 if ((d->protocolCaps & Kopete::Protocol::BaseFont) || (d->protocolCaps & Kopete::Protocol::RichFont))
605 richText |= KopeteRichTextWidget::SupportFontFamily | KopeteRichTextWidget::SupportFontSize;
608 if ((d->protocolCaps & Kopete::Protocol::BaseFgColor) || (d->protocolCaps & Kopete::Protocol::RichFgColor))
610 richText |= KopeteRichTextWidget::SupportTextForegroundColor;
613 if ((d->protocolCaps & Kopete::Protocol::BaseBgColor) || (d->protocolCaps & Kopete::Protocol::RichBgColor))
615 richText |= KopeteRichTextWidget::SupportTextBackgroundColor;
618 if (d->protocolCaps & Kopete::Protocol::Alignment)
620 richText |= KopeteRichTextWidget::SupportAlignment;
626 void KopeteRichTextWidget::Private::mergeAll(
const QTextCharFormat& format)
628 QTextCursor cursor = q->textCursor();
629 cursor.beginEditBlock();
630 cursor.select(QTextCursor::Document);
631 cursor.mergeCharFormat(format);
632 q->mergeCurrentCharFormat(format);
633 cursor.endEditBlock();
637 #include "kopeterichtextwidget.moc"
void documentSizeUpdated(int difference)
QTextCharFormat defaultPlainFormat() const
void setDefaultRichCharFormat(const QTextCharFormat &format)
void slotCheckSpellingChanged(bool b)
void setRichTextEnabled(bool enable)
enable/disable rich text support
void setTextBold(bool bold)
void richTextSupportChanged()
void setTextItalic(bool italic)
virtual bool event(QEvent *event)
virtual void createActions(KActionCollection *actionCollection)
void setTextUnderline(bool underline)
void setSendKeySequenceList(const QList< QKeySequence > &keySequenceList)
A KopeteRichTextWidget with overridden behaviors.
QTextCharFormat currentRichFormat() const
void setCurrentRichCharFormat(const QTextCharFormat &format)
void updateCharFormat(const QTextCharFormat &)
void slotEnableAutoResize(bool enable)
void setTextOrHtml(const QString &text)
bool isRichTextEnabled() const
KopeteRichTextWidget(QWidget *parent, Kopete::Protocol::Capabilities protocolCaps, KActionCollection *actionCollection)
Private class that helps to provide binary compatibility between releases.
void setFontSize(int size)
virtual void insertFromMimeData(const QMimeData *source)
void slotResetFontAndColor()
void setDefaultPlainCharFormat(const QTextCharFormat &format)
void setTextStrikeOut(bool strikeout)
void slotTextModeChanged(KRichTextEdit::Mode mode)
QTextCharFormat defaultRichFormat() const
void slotDocumentSizeUpdated()
void setFontFamily(QString family)