diff --git a/CMakeLists.txt b/CMakeLists.txt index b2cfbcf..35a5a7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,121 +1,121 @@ cmake_minimum_required(VERSION 3.5) -set(PIM_VERSION "5.12.41") +set(PIM_VERSION "5.12.42") project(KPimTextEdit VERSION ${PIM_VERSION}) # ECM setup set(KF5_MIN_VERSION "5.62.0") find_package(ECM ${KF5_MIN_VERSION} CONFIG REQUIRED) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) if (POLICY CMP0053) cmake_policy(SET CMP0053 NEW) endif() include(KDEInstallDirs) include(KDECMakeSettings) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(GenerateExportHeader) include(ECMGenerateHeaders) include(ECMGeneratePriFile) include(ECMSetupVersion) include(FeatureSummary) include(ECMAddTests) include(ECMQtDeclareLoggingCategory) set(KPIMTEXTEDIT_LIB_VERSION ${PIM_VERSION}) ecm_setup_version(PROJECT VARIABLE_PREFIX KPIMTEXTEDIT VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kpimtextedit_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5PimTextEditConfigVersion.cmake" SOVERSION 5 ) set(QT_REQUIRED_VERSION "5.11.0") find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Widgets) find_package(Grantlee5 "5.1" CONFIG REQUIRED) set_package_properties(Grantlee5 PROPERTIES DESCRIPTION "A plug-in based String Template system for Qt" URL "https://github.com/steveire/grantlee" PURPOSE "Required for the RichText composer" TYPE REQUIRED ) ########### Find packages ########### find_package(KF5Codecs ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Config ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5ConfigWidgets ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5CoreAddons ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5I18n ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5IconThemes ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5KIO ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Sonnet ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5SyntaxHighlighting ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5WidgetsAddons ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5XmlGui ${KF5_MIN_VERSION} CONFIG REQUIRED) option(BUILD_DESIGNERPLUGIN "Build plugin for Qt Designer" ON) add_feature_info(DESIGNERPLUGIN ${BUILD_DESIGNERPLUGIN} "Build plugin for Qt Designer") add_definitions(-DTRANSLATION_DOMAIN=\"libkpimtextedit\") if (EXISTS "${CMAKE_SOURCE_DIR}/.git") add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000) endif() add_definitions(-DQT_NO_FOREACH) find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS TextToSpeech) if(BUILD_TESTING) find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Test) add_definitions(-DBUILD_TESTING) endif() ########### Targets ########### add_subdirectory(src) if(BUILD_TESTING) find_package(KF5TextWidgets ${KF5_MIN_VERSION} CONFIG REQUIRED) add_subdirectory(autotests) add_subdirectory(tests) endif() ########### CMake Config Files ########### set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5PimTextEdit") configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/KF5PimTextEditConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KF5PimTextEditConfig.cmake" INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KF5PimTextEditConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KF5PimTextEditConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) install(EXPORT KF5PimTextEditTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KF5PimTextEditTargets.cmake NAMESPACE KF5:: ) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/kpimtextedit_version.h DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5} COMPONENT Devel ) install(FILES kpimtextedit.categories DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/composer-ng/richtextcomposer.cpp b/src/composer-ng/richtextcomposer.cpp index cc3e41a..bd5a3bc 100644 --- a/src/composer-ng/richtextcomposer.cpp +++ b/src/composer-ng/richtextcomposer.cpp @@ -1,572 +1,572 @@ /* Copyright (C) 2015-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "richtextcomposer.h" #include "richtextcomposercontroler.h" #include "richtextcomposeractions.h" #include "richtextcomposerimages.h" #include "richtextcomposeremailquotehighlighter.h" #include "nestedlisthelper_p.h" #include "richtextexternalcomposer.h" #include "grantleebuilder/plaintextmarkupbuilder.h" #include "grantleebuilder/markupdirector.h" #include #include #include #include "richtextcomposeremailquotedecorator.h" #include #include #include #include using namespace KPIMTextEdit; class Q_DECL_HIDDEN RichTextComposer::RichTextComposerPrivate { public: RichTextComposerPrivate(RichTextComposer *qq) : q(qq) { composerControler = new RichTextComposerControler(q, q); richTextComposerActions = new RichTextComposerActions(composerControler, q); externalComposer = new KPIMTextEdit::RichTextExternalComposer(q, q); q->connect(externalComposer, &RichTextExternalComposer::externalEditorClosed, qq, &RichTextComposer::externalEditorClosed); q->connect(externalComposer, &RichTextExternalComposer::externalEditorStarted, qq, &RichTextComposer::externalEditorStarted); q->connect(q, &RichTextComposer::textModeChanged, q, &RichTextComposer::slotTextModeChanged); } QString quotePrefix; RichTextComposerControler *composerControler = nullptr; RichTextComposerActions *richTextComposerActions = nullptr; KPIMTextEdit::RichTextExternalComposer *externalComposer = nullptr; RichTextComposer *q = nullptr; RichTextComposer::Mode mode = RichTextComposer::Plain; bool forcePlainTextMarkup = false; }; RichTextComposer::RichTextComposer(QWidget *parent) : KPIMTextEdit::RichTextEditor(parent) , d(new RichTextComposerPrivate(this)) { setAcceptRichText(false); } RichTextComposer::~RichTextComposer() { delete d; } KPIMTextEdit::RichTextExternalComposer *RichTextComposer::externalComposer() const { return d->externalComposer; } KPIMTextEdit::RichTextComposerControler *RichTextComposer::composerControler() const { return d->composerControler; } KPIMTextEdit::RichTextComposerActions *RichTextComposer::composerActions() const { return d->richTextComposerActions; } QVector RichTextComposer::richTextActionList() const { return d->richTextComposerActions->richTextActionList(); } void RichTextComposer::setEnableActions(bool state) { for (QAction *act : richTextActionList()) { act->setEnabled(state); } } void RichTextComposer::createActions(KActionCollection *ac) { d->richTextComposerActions->createActions(ac); } void RichTextComposer::updateHighLighter() { KPIMTextEdit::RichTextComposerEmailQuoteHighlighter *hlighter = qobject_cast(highlighter()); if (hlighter) { hlighter->toggleSpellHighlighting(checkSpellingEnabled()); } } void RichTextComposer::clearDecorator() { //Nothing } void RichTextComposer::createHighlighter() { KPIMTextEdit::RichTextComposerEmailQuoteHighlighter *highlighter = new KPIMTextEdit::RichTextComposerEmailQuoteHighlighter(this); highlighter->toggleSpellHighlighting(checkSpellingEnabled()); setHighlighterColors(highlighter); setHighlighter(highlighter); } void RichTextComposer::setHighlighterColors(KPIMTextEdit::RichTextComposerEmailQuoteHighlighter *highlighter) { Q_UNUSED(highlighter); } void RichTextComposer::setUseExternalEditor(bool use) { d->externalComposer->setUseExternalEditor(use); } void RichTextComposer::setExternalEditorPath(const QString &path) { d->externalComposer->setExternalEditorPath(path); } bool RichTextComposer::checkExternalEditorFinished() { return d->externalComposer->checkExternalEditorFinished(); } void RichTextComposer::killExternalEditor() { d->externalComposer->killExternalEditor(); } RichTextComposer::Mode RichTextComposer::textMode() const { return d->mode; } void RichTextComposer::enableWordWrap(int wrapColumn) { setWordWrapMode(QTextOption::WordWrap); setLineWrapMode(QTextEdit::FixedColumnWidth); setLineWrapColumnOrWidth(wrapColumn); } void RichTextComposer::disableWordWrap() { setLineWrapMode(QTextEdit::WidgetWidth); } int RichTextComposer::linePosition() const { const QTextCursor cursor = textCursor(); const QTextDocument *doc = document(); QTextBlock block = doc->begin(); int lineCount = 0; // Simply using cursor.block.blockNumber() would not work since that does not // take word-wrapping into account, i.e. it is possible to have more than one // line in a block. // // What we have to do therefore is to iterate over the blocks and count the // lines in them. Once we have reached the block where the cursor is, we have // to iterate over each line in it, to find the exact line in the block where // the cursor is. while (block.isValid()) { const QTextLayout *layout = block.layout(); // If the current block has the cursor in it, iterate over all its lines if (block == cursor.block()) { // Special case: Cursor at end of single non-wrapped line, exit early // in this case as the logic below can't handle it if (block.lineCount() == layout->lineCount()) { return lineCount; } const int cursorBasePosition = cursor.position() - block.position(); const int numberOfLine(layout->lineCount()); for (int i = 0; i < numberOfLine; ++i) { QTextLine line = layout->lineAt(i); if (cursorBasePosition >= line.textStart() && cursorBasePosition < line.textStart() + line.textLength()) { break; } lineCount++; } return lineCount; } else { // No, cursor is not in the current block lineCount += layout->lineCount(); } block = block.next(); } // Only gets here if the cursor block can't be found, shouldn't happen except // for an empty document maybe return lineCount; } int RichTextComposer::columnNumber() const { const QTextCursor cursor = textCursor(); return cursor.columnNumber(); } void RichTextComposer::forcePlainTextMarkup(bool force) { d->forcePlainTextMarkup = force; } void RichTextComposer::insertPlainTextImplementation() { if (d->forcePlainTextMarkup) { KPIMTextEdit::PlainTextMarkupBuilder *pb = new KPIMTextEdit::PlainTextMarkupBuilder(); pb->setQuotePrefix(defaultQuoteSign()); KPIMTextEdit::MarkupDirector *pmd = new KPIMTextEdit::MarkupDirector(pb); pmd->processDocument(document()); const QString plainText = pb->getResult(); document()->setPlainText(plainText); delete pmd; delete pb; } else { document()->setPlainText(document()->toPlainText()); } } void RichTextComposer::slotChangeInsertMode() { setOverwriteMode(!overwriteMode()); Q_EMIT insertModeChanged(); } void RichTextComposer::activateRichText() { if (d->mode == RichTextComposer::Plain) { setAcceptRichText(true); d->mode = RichTextComposer::Rich; Q_EMIT textModeChanged(d->mode); } } void RichTextComposer::switchToPlainText() { if (d->mode == RichTextComposer::Rich) { d->mode = RichTextComposer::Plain; // TODO: Warn the user about this? insertPlainTextImplementation(); setAcceptRichText(false); Q_EMIT textModeChanged(d->mode); } } QString RichTextComposer::textOrHtml() const { if (textMode() == Rich) { return d->composerControler->toCleanHtml(); } else { return toPlainText(); } } void RichTextComposer::setTextOrHtml(const QString &text) { // might be rich text if (Qt::mightBeRichText(text)) { if (d->mode == RichTextComposer::Plain) { activateRichText(); } setHtml(text); } else { setPlainText(text); } } void RichTextComposer::evaluateReturnKeySupport(QKeyEvent *event) { if (event->key() == Qt::Key_Return) { QTextCursor cursor = textCursor(); int oldPos = cursor.position(); int blockPos = cursor.block().position(); //selection all the line. cursor.movePosition(QTextCursor::StartOfBlock); cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); QString lineText = cursor.selectedText(); if (((oldPos - blockPos) > 0) && ((oldPos - blockPos) < int(lineText.length()))) { bool isQuotedLine = false; int bot = 0; // bot = begin of text after quote indicators while (bot < lineText.length()) { if ((lineText[bot] == QChar::fromLatin1('>')) || (lineText[bot] == QChar::fromLatin1('|'))) { isQuotedLine = true; ++bot; } else if (lineText[bot].isSpace()) { ++bot; } else { break; } } evaluateListSupport(event); // duplicate quote indicators of the previous line before the new // line if the line actually contained text (apart from the quote // indicators) and the cursor is behind the quote indicators if (isQuotedLine && (bot != lineText.length()) && ((oldPos - blockPos) >= int(bot))) { // The cursor position might have changed unpredictably if there was selected // text which got replaced by a new line, so we query it again: cursor.movePosition(QTextCursor::StartOfBlock); cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); QString newLine = cursor.selectedText(); // remove leading white space from the new line and instead // add the quote indicators of the previous line int leadingWhiteSpaceCount = 0; while ((leadingWhiteSpaceCount < newLine.length()) && newLine[leadingWhiteSpaceCount].isSpace()) { ++leadingWhiteSpaceCount; } newLine.replace(0, leadingWhiteSpaceCount, lineText.left(bot)); cursor.insertText(newLine); //cursor.setPosition( cursor.position() + 2 ); cursor.movePosition(QTextCursor::StartOfBlock); setTextCursor(cursor); } } else { evaluateListSupport(event); } } else { evaluateListSupport(event); } } void RichTextComposer::evaluateListSupport(QKeyEvent *event) { bool handled = false; if (textCursor().currentList()) { // handled is False if the key press event was not handled or not completely // handled by the Helper class. handled = d->composerControler->nestedListHelper()->handleBeforeKeyPressEvent(event); } if (!handled) { KPIMTextEdit::RichTextEditor::keyPressEvent(event); } if (textCursor().currentList()) { d->composerControler->nestedListHelper()->handleAfterKeyPressEvent(event); } Q_EMIT cursorPositionChanged(); } bool RichTextComposer::processKeyEvent(QKeyEvent *e) { if (d->externalComposer->useExternalEditor() && (e->key() != Qt::Key_Shift) && (e->key() != Qt::Key_Control) && (e->key() != Qt::Key_Meta) && (e->key() != Qt::Key_CapsLock) && (e->key() != Qt::Key_NumLock) && (e->key() != Qt::Key_ScrollLock) && (e->key() != Qt::Key_Alt) && (e->key() != Qt::Key_AltGr)) { if (!d->externalComposer->isInProgress()) { d->externalComposer->startExternalEditor(); } return true; } if (e->key() == Qt::Key_Up && e->modifiers() != Qt::ShiftModifier && textCursor().block().position() == 0 && textCursor().block().layout()->lineForTextPosition(textCursor().position()).lineNumber() == 0) { textCursor().clearSelection(); Q_EMIT focusUp(); } else if (e->key() == Qt::Key_Backtab && e->modifiers() == Qt::ShiftModifier) { textCursor().clearSelection(); Q_EMIT focusUp(); } else { - if (!processAutoCorrection(e)) { + if (!processModifyText(e)) { evaluateReturnKeySupport(e); } } return true; } -bool RichTextComposer::processAutoCorrection(QKeyEvent *event) +bool RichTextComposer::processModifyText(QKeyEvent *event) { Q_UNUSED(event); return false; } void RichTextComposer::keyPressEvent(QKeyEvent *e) { processKeyEvent(e); } Sonnet::SpellCheckDecorator *RichTextComposer::createSpellCheckDecorator() { return new KPIMTextEdit::RichTextComposerEmailQuoteDecorator(this); } QString RichTextComposer::smartQuote(const QString &msg) { return msg; } void RichTextComposer::setQuotePrefixName(const QString "ePrefix) { d->quotePrefix = quotePrefix; } QString RichTextComposer::quotePrefixName() const { if (!d->quotePrefix.simplified().isEmpty()) { return d->quotePrefix; } else { return QStringLiteral(">"); } } int RichTextComposer::quoteLength(const QString &line, bool oneQuote) const { if (!d->quotePrefix.simplified().isEmpty()) { if (line.startsWith(d->quotePrefix)) { return d->quotePrefix.length(); } else { return 0; } } else { bool quoteFound = false; int startOfText = -1; const int lineLength(line.length()); for (int i = 0; i < lineLength; ++i) { if (line[i] == QLatin1Char('>') || line[i] == QLatin1Char('|')) { if (quoteFound && oneQuote) { break; } quoteFound = true; } else if (line[i] != QLatin1Char(' ')) { startOfText = i; break; } } if (quoteFound) { //We found a quote but it's just quote element => 1 => remove 1 char. if (startOfText == -1) { startOfText = 1; } return startOfText; } else { return 0; } } } void RichTextComposer::setCursorPositionFromStart(unsigned int pos) { d->composerControler->setCursorPositionFromStart(pos); } bool RichTextComposer::isLineQuoted(const QString &line) const { return quoteLength(line) > 0; } const QString RichTextComposer::defaultQuoteSign() const { if (!d->quotePrefix.simplified().isEmpty()) { return d->quotePrefix; } else { return QStringLiteral("> "); } } void RichTextComposer::insertFromMimeData(const QMimeData *source) { // Add an image if that is on the clipboard if (textMode() == RichTextComposer::Rich && source->hasImage()) { const QImage image = qvariant_cast(source->imageData()); QFileInfo fi; d->composerControler->composerImages()->insertImage(image, fi); return; } // Attempt to paste HTML contents into the text edit in plain text mode, // prevent this and prevent plain text instead. if (textMode() == RichTextComposer::Plain && source->hasHtml()) { if (source->hasText()) { insertPlainText(source->text()); return; } } if (textMode() == RichTextComposer::Rich) { if (source->hasText()) { const QString sourceText = source->text(); if (sourceText.startsWith(QLatin1String("http://")) || sourceText.startsWith(QLatin1String("https://")) || sourceText.startsWith(QLatin1String("ftps://")) || sourceText.startsWith(QLatin1String("ftp://")) || sourceText.startsWith(QLatin1String("mailto:")) || sourceText.startsWith(QLatin1String("smb://")) || sourceText.startsWith(QLatin1String("file://")) || sourceText.startsWith(QLatin1String("webdavs://")) || sourceText.startsWith(QLatin1String("imaps://")) || sourceText.startsWith(QLatin1String("sftp://")) || sourceText.startsWith(QLatin1String("fish://")) || sourceText.startsWith(QLatin1String("tel:")) ) { insertHtml(QStringLiteral("%1 ").arg(sourceText)); return; } } } KPIMTextEdit::RichTextEditor::insertFromMimeData(source); } bool RichTextComposer::canInsertFromMimeData(const QMimeData *source) const { if (source->hasHtml() && textMode() == RichTextComposer::Rich) { return true; } if (source->hasText()) { return true; } if (textMode() == RichTextComposer::Rich && source->hasImage()) { return true; } return KPIMTextEdit::RichTextEditor::canInsertFromMimeData(source); } void RichTextComposer::mouseReleaseEvent(QMouseEvent *event) { if (d->composerControler->painterActive()) { d->composerControler->disablePainter(); d->richTextComposerActions->uncheckActionFormatPainter(); } KPIMTextEdit::RichTextEditor::mouseReleaseEvent(event); } void RichTextComposer::slotTextModeChanged(KPIMTextEdit::RichTextComposer::Mode mode) { d->composerControler->textModeChanged(mode); d->richTextComposerActions->textModeChanged(mode); } diff --git a/src/composer-ng/richtextcomposer.h b/src/composer-ng/richtextcomposer.h index 793debf..a8a1630 100644 --- a/src/composer-ng/richtextcomposer.h +++ b/src/composer-ng/richtextcomposer.h @@ -1,155 +1,155 @@ /* Copyright (C) 2015-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KPIMTEXTEDITRICHTEXTCOMPOSER_H #define KPIMTEXTEDITRICHTEXTCOMPOSER_H #include "kpimtextedit_export.h" #include class KActionCollection; namespace KPIMTextEdit { class RichTextComposerControler; class RichTextComposerActions; class RichTextExternalComposer; class RichTextComposerEmailQuoteHighlighter; /** * @brief The RichTextComposer class * @author Laurent Montel */ class KPIMTEXTEDIT_EXPORT RichTextComposer : public KPIMTextEdit::RichTextEditor { Q_OBJECT public: explicit RichTextComposer(QWidget *parent = nullptr); ~RichTextComposer() override; enum Mode { Plain, ///< Plain text mode Rich ///< Rich text mode }; /** * @return The current text mode */ Q_REQUIRED_RESULT Mode textMode() const; /** * Enables word wrap. Words will be wrapped at the specified column. * * @param wrapColumn the column where words will be wrapped */ void enableWordWrap(int wrapColumn); /** * Disables word wrap. * Note that words are still wrapped at the end of the editor; no scrollbar * will appear. */ void disableWordWrap(); /** * @return the line number where the cursor is. This takes word-wrapping * into account. Line numbers start at 0. */ Q_REQUIRED_RESULT int linePosition() const; /** * @return the column number where the cursor is. */ Q_REQUIRED_RESULT int columnNumber() const; void forcePlainTextMarkup(bool force); void activateRichText(); void switchToPlainText(); void setTextOrHtml(const QString &text); Q_REQUIRED_RESULT QString textOrHtml() const; virtual void setHighlighterColors(KPIMTextEdit::RichTextComposerEmailQuoteHighlighter *highlighter); void setUseExternalEditor(bool use); void setExternalEditorPath(const QString &path); Q_REQUIRED_RESULT bool checkExternalEditorFinished(); void killExternalEditor(); //Redefine it for each apps virtual QString smartQuote(const QString &msg); //need by kmail void setQuotePrefixName(const QString "ePrefix); Q_REQUIRED_RESULT QString quotePrefixName() const; void setCursorPositionFromStart(unsigned int pos); Q_REQUIRED_RESULT int quoteLength(const QString &line, bool oneQuote = false) const; Q_REQUIRED_RESULT bool isLineQuoted(const QString &line) const; const QString defaultQuoteSign() const; void createActions(KActionCollection *ac); QVector richTextActionList() const; void setEnableActions(bool state); KPIMTextEdit::RichTextComposerControler *composerControler() const; KPIMTextEdit::RichTextExternalComposer *externalComposer() const; KPIMTextEdit::RichTextComposerActions *composerActions() const; void createHighlighter() override; - virtual bool processAutoCorrection(QKeyEvent *event); + virtual bool processModifyText(QKeyEvent *event); public Q_SLOTS: void insertPlainTextImplementation(); void slotChangeInsertMode(); Q_SIGNALS: void insertModeChanged(); /** * Emitted whenever the text mode is changed. * * @param mode The new text mode */ void textModeChanged(KPIMTextEdit::RichTextComposer::Mode mode); /** * Emitted when the user uses the up arrow in the first line. The application * should then put the focus on the widget above the text edit. */ void focusUp(); void externalEditorStarted(); void externalEditorClosed(); void insertEmoticon(const QString &str); protected: void keyPressEvent(QKeyEvent *event) override; Sonnet::SpellCheckDecorator *createSpellCheckDecorator() override; void insertFromMimeData(const QMimeData *source) override; bool canInsertFromMimeData(const QMimeData *source) const override; void mouseReleaseEvent(QMouseEvent *event) override; void clearDecorator() override; void updateHighLighter() override; bool processKeyEvent(QKeyEvent *e); private: void slotTextModeChanged(KPIMTextEdit::RichTextComposer::Mode mode); void evaluateListSupport(QKeyEvent *event); void evaluateReturnKeySupport(QKeyEvent *event); class RichTextComposerPrivate; RichTextComposerPrivate *const d; }; } #endif // RICHTEXTCOMPOSER_H