diff --git a/src/composer-ng/richtextcomposer.cpp b/src/composer-ng/richtextcomposer.cpp index 2b84aca..3c57c4c 100644 --- a/src/composer-ng/richtextcomposer.cpp +++ b/src/composer-ng/richtextcomposer.cpp @@ -1,550 +1,550 @@ /* 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; } QList 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 = 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)) { evaluateReturnKeySupport(e); } } return true; } bool RichTextComposer::processAutoCorrection(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; } } 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/grantleebuilder/plaintextmarkupbuilder.cpp b/src/grantleebuilder/plaintextmarkupbuilder.cpp index 24dfb1a..5ab67db 100644 --- a/src/grantleebuilder/plaintextmarkupbuilder.cpp +++ b/src/grantleebuilder/plaintextmarkupbuilder.cpp @@ -1,497 +1,496 @@ /* Copyright (c) 2019 Montel Laurent 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 "plaintextmarkupbuilder.h" #include namespace KPIMTextEdit { class PlainTextMarkupBuilderPrivate { public: PlainTextMarkupBuilderPrivate(PlainTextMarkupBuilder *b) : q_ptr(b) {} /** Get a letter string to represent a number. The numbers 1-26 are represented by a-z, and 27-52 by aa-az, 53-79 by ba-bz etc. @param The number to convert @return The letter string representation of the number. */ QString getLetterString(int itemNumber); QString getRomanString(int itemNumber); /** Gets a block of references in the body of the text. This is an ordered list of links and images in the text. */ QString getReferences(); QStringList m_urls; QList currentListItemStyles; QList currentListItemNumbers; QString activeLink; QString m_text; QString m_quoteprefix; PlainTextMarkupBuilder *q_ptr; Q_DECLARE_PUBLIC(PlainTextMarkupBuilder) }; } using namespace KPIMTextEdit; PlainTextMarkupBuilder::PlainTextMarkupBuilder() : d_ptr(new PlainTextMarkupBuilderPrivate(this)) { } QString PlainTextMarkupBuilderPrivate::getRomanString(int item) { QString result; // Code based to gui/text/qtextlist.cpp if (item < 5000) { QString romanNumeral; // works for up to 4999 items auto romanSymbols = QStringLiteral("iiivixxxlxcccdcmmmm"); int c[] = {1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000}; auto n = item; for (auto i = 12; i >= 0; n %= c[i], i--) { auto q = n / c[i]; if (q > 0) { auto startDigit = i + (i + 3) / 4; int numDigits; if (i % 4) { // c[i] == 4|5|9|40|50|90|400|500|900 if ((i - 2) % 4) { // c[i] == 4|9|40|90|400|900 => with subtraction (IV, // IX, XL, XC, // ...) numDigits = 2; } else { // c[i] == 5|50|500 (V, L, D) numDigits = 1; } } else { // c[i] == 1|10|100|1000 (I, II, III, X, XX, ...) numDigits = q; } romanNumeral.append(romanSymbols.mid(startDigit, numDigits)); } } result = romanNumeral; } else { result = QStringLiteral("?"); } return result; } QString PlainTextMarkupBuilderPrivate::getLetterString(int itemNumber) { QString letterString; while (true) { // Create the letter string by prepending one char at a time. // The itemNumber is converted to a number in the base 36 (number of // letters // in the // alphabet plus 10) after being increased by 10 (to pass out the digits // 0 // to 9). letterString.prepend(QStringLiteral("%1").arg( (itemNumber % LETTERSINALPHABET) + DIGITSOFFSET, 0, // no padding while building this string. LETTERSINALPHABET + DIGITSOFFSET)); if ((itemNumber >= LETTERSINALPHABET)) { itemNumber = itemNumber / LETTERSINALPHABET; itemNumber--; } else { break; } } return letterString; } QString PlainTextMarkupBuilderPrivate::getReferences() { QString refs; if (!m_urls.isEmpty()) { refs.append(QStringLiteral("\n--------\n")); auto index = 1; while (!m_urls.isEmpty()) { refs.append( QStringLiteral("[%1] %2\n").arg(index++).arg(m_urls.takeFirst())); } } return refs; } PlainTextMarkupBuilder::~PlainTextMarkupBuilder() { delete d_ptr; } void PlainTextMarkupBuilder::setQuotePrefix(const QString &prefix) { Q_D(PlainTextMarkupBuilder); d->m_quoteprefix = prefix; } void PlainTextMarkupBuilder::beginStrong() { Q_D(PlainTextMarkupBuilder); d->m_text.append(QLatin1Char('*')); } void PlainTextMarkupBuilder::endStrong() { Q_D(PlainTextMarkupBuilder); d->m_text.append(QLatin1Char('*')); } void PlainTextMarkupBuilder::beginEmph() { Q_D(PlainTextMarkupBuilder); d->m_text.append(QLatin1Char('/')); } void PlainTextMarkupBuilder::endEmph() { Q_D(PlainTextMarkupBuilder); d->m_text.append(QLatin1Char('/')); } void PlainTextMarkupBuilder::beginUnderline() { Q_D(PlainTextMarkupBuilder); d->m_text.append(QLatin1Char('_')); } void PlainTextMarkupBuilder::endUnderline() { Q_D(PlainTextMarkupBuilder); d->m_text.append(QLatin1Char('_')); } void PlainTextMarkupBuilder::beginStrikeout() { Q_D(PlainTextMarkupBuilder); d->m_text.append(QLatin1Char('-')); } void PlainTextMarkupBuilder::endStrikeout() { Q_D(PlainTextMarkupBuilder); d->m_text.append(QLatin1Char('-')); } void PlainTextMarkupBuilder::beginAnchor(const QString &href, const QString &name) { Q_D(PlainTextMarkupBuilder); Q_UNUSED(name); if (!d->m_urls.contains(href)) { d->m_urls.append(href); } d->activeLink = href; } void PlainTextMarkupBuilder::endAnchor() { Q_D(PlainTextMarkupBuilder); d->m_text.append( QStringLiteral("[%1]").arg(d->m_urls.indexOf(d->activeLink) + 1)); } void PlainTextMarkupBuilder::endParagraph() { Q_D(PlainTextMarkupBuilder); d->m_text.append(QLatin1Char('\n')); } void PlainTextMarkupBuilder::addNewline() { Q_D(PlainTextMarkupBuilder); d->m_text.append(QLatin1Char('\n')); } void PlainTextMarkupBuilder::insertHorizontalRule(int width) { Q_UNUSED(width) Q_D(PlainTextMarkupBuilder); d->m_text.append(QStringLiteral("--------------------\n")); } int PlainTextMarkupBuilder::addReference(const QString &reference) { Q_D(PlainTextMarkupBuilder); if (!d->m_urls.contains(reference)) d->m_urls.append(reference); return d->m_urls.indexOf(reference) + 1; } void PlainTextMarkupBuilder::insertImage(const QString &src, qreal width, qreal height) { Q_D(PlainTextMarkupBuilder); Q_UNUSED(width) Q_UNUSED(height) auto ref = addReference(src); d->m_text.append(QStringLiteral("[%1]").arg(ref)); } void PlainTextMarkupBuilder::beginList(QTextListFormat::Style style) { Q_D(PlainTextMarkupBuilder); d->currentListItemStyles.append(style); d->currentListItemNumbers.append(0); } void PlainTextMarkupBuilder::endList() { Q_D(PlainTextMarkupBuilder); if (!d->currentListItemNumbers.isEmpty()) { d->currentListItemStyles.removeLast(); d->currentListItemNumbers.removeLast(); } } void PlainTextMarkupBuilder::beginListItem() { Q_D(PlainTextMarkupBuilder); for (auto i = 0; i < d->currentListItemNumbers.size(); i++) { d->m_text.append(QStringLiteral(" ")); } auto itemNumber = d->currentListItemNumbers.last(); switch (d->currentListItemStyles.last()) { case QTextListFormat::ListDisc: d->m_text.append(QStringLiteral(" * ")); break; case QTextListFormat::ListCircle: d->m_text.append(QStringLiteral(" o ")); break; case QTextListFormat::ListSquare: d->m_text.append(QStringLiteral(" - ")); break; case QTextListFormat::ListDecimal: d->m_text.append(QStringLiteral(" %1. ").arg(itemNumber + 1)); break; case QTextListFormat::ListLowerAlpha: d->m_text.append( QStringLiteral(" %1. ").arg(d->getLetterString(itemNumber))); break; case QTextListFormat::ListUpperAlpha: d->m_text.append( QStringLiteral(" %1. ").arg(d->getLetterString(itemNumber).toUpper())); break; case QTextListFormat::ListLowerRoman: d->m_text.append( QStringLiteral(" %1. ").arg(d->getRomanString(itemNumber + 1))); break; case QTextListFormat::ListUpperRoman: d->m_text.append(QStringLiteral(" %1. ").arg( d->getRomanString(itemNumber + 1).toUpper())); break; default: break; } } void PlainTextMarkupBuilder::endListItem() { Q_D(PlainTextMarkupBuilder); d->currentListItemNumbers.last() = d->currentListItemNumbers.last() + 1; d->m_text.append(QLatin1Char('\n')); } void PlainTextMarkupBuilder::beginSuperscript() { Q_D(PlainTextMarkupBuilder); d->m_text.append(QStringLiteral("^{")); } void PlainTextMarkupBuilder::endSuperscript() { Q_D(PlainTextMarkupBuilder); d->m_text.append(QLatin1Char('}')); } void PlainTextMarkupBuilder::beginSubscript() { Q_D(PlainTextMarkupBuilder); d->m_text.append(QStringLiteral("_{")); } void PlainTextMarkupBuilder::endSubscript() { Q_D(PlainTextMarkupBuilder); d->m_text.append(QLatin1Char('}')); } void PlainTextMarkupBuilder::appendLiteralText(const QString &text) { Q_D(PlainTextMarkupBuilder); d->m_text.append(text); } void PlainTextMarkupBuilder::appendRawText(const QString &text) { Q_D(PlainTextMarkupBuilder); d->m_text.append(text); } QString PlainTextMarkupBuilder::getResult() { Q_D(PlainTextMarkupBuilder); auto ret = d->m_text; ret.append(d->getReferences()); d->m_text.clear(); return ret; } void PlainTextMarkupBuilder::beginParagraph(Qt::Alignment a, qreal top, qreal bottom, qreal left, qreal right) { Q_UNUSED(a); - Q_UNUSED(top); - Q_UNUSED(bottom); - Q_UNUSED(left); - Q_UNUSED(right); + Q_D(PlainTextMarkupBuilder); + if (isQuoteBlock(top, bottom, left, right)) { + d->m_text.append(d->m_quoteprefix); + } } bool PlainTextMarkupBuilder::isQuoteBlock(qreal top, qreal bottom, qreal left, qreal right) const { + return (top == 12) && (bottom == 12) && (left == 40) && (right == 40); /* case Html_blockquote: margin[QTextHtmlParser::MarginTop] = 12; margin[QTextHtmlParser::MarginBottom] = 12; margin[QTextHtmlParser::MarginLeft] = 40; margin[QTextHtmlParser::MarginRight] = 40; break; */ - //TODO - return false; } void PlainTextMarkupBuilder::beginBackground(const QBrush &brush) { Q_UNUSED(brush); } void PlainTextMarkupBuilder::beginFontFamily(const QString &family) { Q_UNUSED(family); } void PlainTextMarkupBuilder::beginFontPointSize(int size) { Q_UNUSED(size); } void PlainTextMarkupBuilder::beginForeground(const QBrush &brush) { Q_UNUSED(brush); } void PlainTextMarkupBuilder::beginHeader(int level) { Q_UNUSED(level); } void PlainTextMarkupBuilder::beginTable(qreal cellpadding, qreal cellspacing, const QString &width) { Q_UNUSED(cellpadding); Q_UNUSED(cellspacing); Q_UNUSED(width); } void PlainTextMarkupBuilder::beginTableCell(const QString &width, int colSpan, int rowSpan) { Q_UNUSED(width); Q_UNUSED(colSpan); Q_UNUSED(rowSpan); } void PlainTextMarkupBuilder::beginTableHeaderCell(const QString &width, int colSpan, int rowSpan) { Q_UNUSED(width); Q_UNUSED(colSpan); Q_UNUSED(rowSpan); } void PlainTextMarkupBuilder::beginTableRow() { } void PlainTextMarkupBuilder::endBackground() { } void PlainTextMarkupBuilder::endFontFamily() { } void PlainTextMarkupBuilder::endFontPointSize() { } void PlainTextMarkupBuilder::endForeground() { } void PlainTextMarkupBuilder::endHeader(int level) { Q_UNUSED(level) } void PlainTextMarkupBuilder::endTable() { } void PlainTextMarkupBuilder::endTableCell() { } void PlainTextMarkupBuilder::endTableHeaderCell() { } void PlainTextMarkupBuilder::endTableRow() { }