diff --git a/scribus/pageitem.cpp b/scribus/pageitem.cpp index af8d4fd..6b5ec2b 100644 --- a/scribus/pageitem.cpp +++ b/scribus/pageitem.cpp @@ -7105,7 +7105,7 @@ void PageItem::restoreDeleteFrameText(SimpleState *ss, bool isUndo) void PageItem::restoreDeleteFrameParagraph(SimpleState *ss, bool isUndo) { - const auto *is = dynamic_cast *>(ss); + const auto *is = dynamic_cast > *>(ss); if (!is) { qFatal("PageItem::restoreDeleteFrameParagraph: dynamic cast failed"); @@ -7116,8 +7116,10 @@ void PageItem::restoreDeleteFrameParagraph(SimpleState *ss, bool isUndo) itemText.deselectAll(); if (isUndo) { + const QPair styles = is->getItem(); itemText.insertChars(start, SpecialChars::PARSEP); - itemText.applyStyle(start, is->getItem()); + itemText.applyStyle(start, styles.first); + itemText.applyStyle(start + 1, styles.second); itemText.setCursorPosition(start + 1); invalid = true; invalidateLayout(); diff --git a/scribus/pageitem_textframe.cpp b/scribus/pageitem_textframe.cpp index 1c5b95c..d5f0afc 100644 --- a/scribus/pageitem_textframe.cpp +++ b/scribus/pageitem_textframe.cpp @@ -27,6 +27,7 @@ for which a new license (GPL+exception) is in place. #include #include #include +#include #include #include #include @@ -4731,7 +4732,7 @@ void PageItem_TextFrame::deleteSelectedTextFromFrame(/*bool findNotes*/) int lastPos = start; CharStyle lastParent = itemText.charStyle(start); UndoState* state = undoManager->getLastUndo(); - ScItemState *ip = nullptr; + ScItemState > *ip = nullptr; ScItemState *is = nullptr; TransactionState *ts = nullptr; bool added = false; @@ -4869,11 +4870,11 @@ void PageItem_TextFrame::deleteSelectedTextFromFrame(/*bool findNotes*/) UndoObject * undoTarget = this; if (isNoteFrame()) undoTarget = m_Doc; - ip = new ScItemState(Um::DeleteText, "", Um::IDelete); + ip = new ScItemState >(Um::DeleteText, "", Um::IDelete); ip->set("DELETE_FRAMEPARA"); ip->set("ETEA", QString("delete_framepara")); ip->set("START", start); - ip->setItem(itemText.paragraphStyle(i)); + ip->setItem(qMakePair(itemText.paragraphStyle(i), itemText.paragraphStyle(i + 1))); lastPos = i + 1; if (lastPos < itemText.length()) lastParent = itemText.charStyle(lastPos); diff --git a/scribus/tests/testStoryText.cpp b/scribus/tests/testStoryText.cpp index a6ede8b..91411e8 100644 --- a/scribus/tests/testStoryText.cpp +++ b/scribus/tests/testStoryText.cpp @@ -82,6 +82,42 @@ void TestStoryText::removePars() QString("0123456789") + SpecialChars::PARSEP + QString("abcdefghijklmnopqrstuVWXYZ")); } +void TestStoryText::removeParSepKeepsLeftParagraphStyle() +{ + StoryText story; + story.insertChars(0, QString("One") + SpecialChars::PARSEP + QString("Two")); + + ParagraphStyle style1; + style1.setAlignment(ParagraphStyle::RightAligned); + ParagraphStyle style2; + style2.setAlignment(ParagraphStyle::Centered); + + story.applyStyle(0, style1); + story.applyStyle(4, style2); + story.removeChars(3, 1); + + QCOMPARE(story.text(0, story.length()), QString("OneTwo")); + QCOMPARE(static_cast(story.paragraphStyle(0).alignment()), static_cast(ParagraphStyle::RightAligned)); +} + +void TestStoryText::removeWholeLeftParagraphKeepsRightParagraphStyle() +{ + StoryText story; + story.insertChars(0, QString("One") + SpecialChars::PARSEP + QString("Two")); + + ParagraphStyle style1; + style1.setAlignment(ParagraphStyle::RightAligned); + ParagraphStyle style2; + style2.setAlignment(ParagraphStyle::Centered); + + story.applyStyle(0, style1); + story.applyStyle(4, style2); + story.removeChars(0, 4); + + QCOMPARE(story.text(0, story.length()), QString("Two")); + QCOMPARE(static_cast(story.paragraphStyle(0).alignment()), static_cast(ParagraphStyle::Centered)); +} + void TestStoryText::applyCharStyle() { StoryText story; diff --git a/scribus/tests/testStoryText.h b/scribus/tests/testStoryText.h index 6558752..104dcff 100644 --- a/scribus/tests/testStoryText.h +++ b/scribus/tests/testStoryText.h @@ -25,6 +25,8 @@ private slots: void insertPar(); void removePar(); void removePars(); + void removeParSepKeepsLeftParagraphStyle(); + void removeWholeLeftParagraphKeepsRightParagraphStyle(); void applyCharStyle(); void removeCharStyle(); }; diff --git a/scribus/text/storytext.cpp b/scribus/text/storytext.cpp index 4214bb5..04d70e9 100644 --- a/scribus/text/storytext.cpp +++ b/scribus/text/storytext.cpp @@ -549,8 +549,12 @@ void StoryText::insert(int pos, const StoryText& other, bool onlySelection) need to remove the ParagraphStyle structure and replace all pointers to it... */ -void StoryText::removeParSep(int pos) +void StoryText::removeParSep(int pos, bool preserveParagraphStyle) { + ParagraphStyle preservedStyle; + if (preserveParagraphStyle) + preservedStyle = paragraphStyle(pos); + ScText* it = item(pos); if (it->parstyle) { @@ -560,7 +564,33 @@ void StoryText::removeParSep(int pos) // demote this parsep so the assert code in replaceCharStyleContextInParagraph() // doesn't choke: it->ch = QChar(); - d->replaceCharStyleContextInParagraph(pos, paragraphStyle(pos+1).charStyleContext()); + + if (preserveParagraphStyle) + { + int stylePos = pos + 1; + while (stylePos < length() && d->at(stylePos)->ch != SpecialChars::PARSEP) + ++stylePos; + + if (stylePos < length()) + { + if (!d->at(stylePos)->parstyle) + { + d->at(stylePos)->parstyle = new ParagraphStyle(); + d->at(stylePos)->parstyle->setContext(&d->pstyleContext); + } + *d->at(stylePos)->parstyle = preservedStyle; + d->at(stylePos)->parstyle->setContext(&d->pstyleContext); + d->replaceCharStyleContextInParagraph(stylePos, d->at(stylePos)->parstyle->charStyleContext()); + } + else + { + d->trailingStyle = preservedStyle; + d->trailingStyle.setContext(&d->pstyleContext); + d->replaceCharStyleContextInParagraph(length(), d->trailingStyle.charStyleContext()); + } + } + else + d->replaceCharStyleContextInParagraph(pos, paragraphStyle(pos + 1).charStyleContext()); } /** @@ -673,7 +703,20 @@ void StoryText::removeChars(int pos, uint len) { ScText *it = d->at(i); if (it->ch == SpecialChars::PARSEP) - removeParSep(i); + { + bool preserveParagraphStyle = false; + for (int j = i - 1; j >= 0; --j) + { + if (d->at(j)->ch == SpecialChars::PARSEP) + break; + if (j < pos) + { + preserveParagraphStyle = true; + break; + } + } + removeParSep(i, preserveParagraphStyle); + } if ((it->ch == SpecialChars::OBJECT) && (it->mark != nullptr)) d->marksCount--; d->takeAt(i); @@ -851,7 +894,7 @@ void StoryText::replaceChar(int pos, QChar ch) uint oldMarksCount = d->marksCount; if (item->ch == SpecialChars::PARSEP) - removeParSep(pos); + removeParSep(pos, pos > 0 && text(pos - 1) != SpecialChars::PARSEP); if ((item->ch == SpecialChars::OBJECT) && (item->mark != nullptr)) d->marksCount--; item->ch = ch; diff --git a/scribus/text/storytext.h b/scribus/text/storytext.h index 7920d56..ef49a29 100644 --- a/scribus/text/storytext.h +++ b/scribus/text/storytext.h @@ -335,7 +335,7 @@ private: /// mark these runs as invalid, ie. need itemize and shaping void invalidate(int firstRun, int lastRun); - void removeParSep(int pos); + void removeParSep(int pos, bool preserveParagraphStyle = false); void insertParSep(int pos); // private: