connectivity/source/parse/sqliterator.cxx | 24 ++++++------- include/connectivity/sqliterator.hxx | 3 + sw/qa/extras/uiwriter/uiwriter2.cxx | 52 ++++++++++++++++++++++++++++++ sw/source/core/edit/edfcol.cxx | 38 +++++++++++++++++++++ 4 files changed, 103 insertions(+), 14 deletions(-)
New commits: commit ce89c11c5aa2e01f9827da199c68ab9803e6013e Author: Caolán McNamara <[email protected]> AuthorDate: Sun Sep 26 21:13:43 2021 +0100 Commit: Caolán McNamara <[email protected]> CommitDate: Mon Sep 27 16:37:15 2021 +0200 pass the column names in as an external argument Change-Id: I14ab9e6de0a704076a1c632b6b33aaeabdfc23d9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122660 Tested-by: Jenkins Reviewed-by: Caolán McNamara <[email protected]> diff --git a/connectivity/source/parse/sqliterator.cxx b/connectivity/source/parse/sqliterator.cxx index ef7873a6c302..aed5b6bfcb38 100644 --- a/connectivity/source/parse/sqliterator.cxx +++ b/connectivity/source/parse/sqliterator.cxx @@ -1406,7 +1406,7 @@ void OSQLParseTreeIterator::traverseParameter(const OSQLParseNode* _pParseNode nType = ::connectivity::OSQLParser::getFunctionParameterType( pParent->getChild(0)->getTokenID(), i+1); } - OUString aNewColName( getUniqueColumnName( sParameterName ) ); + OUString aNewColName(getUniqueColumnName(getSelectColumnNames(), sParameterName)); rtl::Reference<OParseColumn> pColumn = new OParseColumn(aNewColName, OUString(), @@ -1539,7 +1539,7 @@ void OSQLParseTreeIterator::appendColumns(const OUString& _rTableAlias, const OS for(;pBegin != pEnd;++pBegin) { - OUString aName(getUniqueColumnName(*pBegin)); + OUString aName(getUniqueColumnName(getSelectColumnNames(), *pBegin)); Reference< XPropertySet > xColumn; if(xColumns->hasByName(*pBegin) && (xColumns->getByName(*pBegin) >>= xColumn) && xColumn.is()) { @@ -1600,7 +1600,7 @@ void OSQLParseTreeIterator::setSelectColumnName(const OUString & rColumnName,con ) continue; - OUString aNewColName(getUniqueColumnName(rColumnAlias)); + OUString aNewColName(getUniqueColumnName(getSelectColumnNames(), rColumnAlias)); rtl::Reference<OParseColumn> pColumn = new OParseColumn(xColumn,isCaseSensitive()); xNewColumn = pColumn; @@ -1615,7 +1615,7 @@ void OSQLParseTreeIterator::setSelectColumnName(const OUString & rColumnName,con { // no function (due to the above !bFkt), no existing column // => assume an expression - OUString aNewColName( getUniqueColumnName( rColumnAlias ) ); + OUString aNewColName(getUniqueColumnName(getSelectColumnNames(), rColumnAlias)); // did not find a column with this name in any of the tables rtl::Reference<OParseColumn> pColumn = new OParseColumn( aNewColName, @@ -1644,7 +1644,7 @@ void OSQLParseTreeIterator::setSelectColumnName(const OUString & rColumnName,con } else { - OUString aNewColName(getUniqueColumnName(rColumnAlias)); + OUString aNewColName(getUniqueColumnName(getSelectColumnNames(), rColumnAlias)); rtl::Reference<OParseColumn> pColumn = new OParseColumn(aNewColName,OUString(),OUString(),OUString(), ColumnValue::NULLABLE_UNKNOWN,0,0,_nType,false,false,isCaseSensitive(), @@ -1665,7 +1665,7 @@ void OSQLParseTreeIterator::setSelectColumnName(const OUString & rColumnName,con { if (bFkt) { - OUString aNewColName(getUniqueColumnName(rColumnAlias)); + OUString aNewColName(getUniqueColumnName(getSelectColumnNames(), rColumnAlias)); rtl::Reference<OParseColumn> pColumn = new OParseColumn(aNewColName,OUString(),OUString(),OUString(), ColumnValue::NULLABLE_UNKNOWN,0,0,_nType,false,false,isCaseSensitive(), @@ -1684,7 +1684,7 @@ void OSQLParseTreeIterator::setSelectColumnName(const OUString & rColumnName,con Reference< XPropertySet > xColumn; if (aFind->second->getColumns()->hasByName(rColumnName) && (aFind->second->getColumns()->getByName(rColumnName) >>= xColumn)) { - OUString aNewColName(getUniqueColumnName(rColumnAlias)); + OUString aNewColName(getUniqueColumnName(getSelectColumnNames(), rColumnAlias)); rtl::Reference<OParseColumn> pColumn = new OParseColumn(xColumn,isCaseSensitive()); pColumn->setName(aNewColName); @@ -1703,7 +1703,7 @@ void OSQLParseTreeIterator::setSelectColumnName(const OUString & rColumnName,con // Table does not exist or lacking field if (bError) { - OUString aNewColName(getUniqueColumnName(rColumnAlias)); + OUString aNewColName(getUniqueColumnName(getSelectColumnNames(), rColumnAlias)); rtl::Reference<OParseColumn> pColumn = new OParseColumn(aNewColName,OUString(),OUString(),OUString(), ColumnValue::NULLABLE_UNKNOWN,0,0,DataType::VARCHAR,false,false,isCaseSensitive(), @@ -1729,12 +1729,10 @@ std::vector<OUString> OSQLParseTreeIterator::getSelectColumnNames() const return aColumnNames; } -OUString OSQLParseTreeIterator::getUniqueColumnName(const OUString& rColumnName) const +OUString OSQLParseTreeIterator::getUniqueColumnName(const std::vector<OUString>& rColumnNames, const OUString& rColumnName) const { - std::vector<OUString> aColumnNames(getSelectColumnNames()); - ::comphelper::UStringMixLess aCompare(isCaseSensitive()); - if (!std::binary_search(aColumnNames.begin(), aColumnNames.end(), rColumnName, aCompare)) + if (!std::binary_search(rColumnNames.begin(), rColumnNames.end(), rColumnName, aCompare)) return rColumnName; OUString aAlias; @@ -1743,7 +1741,7 @@ OUString OSQLParseTreeIterator::getUniqueColumnName(const OUString& rColumnName) { aAlias = rColumnName + OUString::number(i++); } - while (std::binary_search(aColumnNames.begin(), aColumnNames.end(), aAlias, aCompare)); + while (std::binary_search(rColumnNames.begin(), rColumnNames.end(), aAlias, aCompare)); return aAlias; } diff --git a/include/connectivity/sqliterator.hxx b/include/connectivity/sqliterator.hxx index 6c529c69b37f..201b3129419f 100644 --- a/include/connectivity/sqliterator.hxx +++ b/include/connectivity/sqliterator.hxx @@ -108,7 +108,8 @@ namespace connectivity // get all the column names of m_aSelectColumns and return in a vector sorted by a UStringMixLess that's constructed from // isCaseSensitive() std::vector<OUString> getSelectColumnNames() const; - OUString getUniqueColumnName(const OUString & rColumnName) const; + // rColumnNames is expected to be sorted as returned by getSelectColumnNames + OUString getUniqueColumnName(const std::vector<OUString>& rColumnNames, const OUString & rColumnName) const; /** finds the column with a given name, belonging to a given table, in a given tables collection @param _rTables commit c364532e6b06391a0584f58142c2366d28c803dd Author: László Németh <[email protected]> AuthorDate: Mon Sep 27 11:36:50 2021 +0200 Commit: László Németh <[email protected]> CommitDate: Mon Sep 27 16:37:08 2021 +0200 tdf#144272 sw: track change of paragraph style Modifying style of a paragraph, e.g. from "Standard" or "Text body" to "Heading n" styles wasn't recorded by change tracking. Now it's possible to track and reject these changes also after DOCX export/import. Note: ODF track changes doesn't support format-only changes, so likely it will need to export the paragraph content two times, with the old and with the new paragraph styles, too). Note: selecting multiple paragraphs to modify their styles at once doesn't record the changes, yet, because multi-paragraph ParagraphFormat redline range hasn't supported by AppendRedline(). Change-Id: I2d81fa23c59b7b75b3101dc3f2bb8c9eed8ab165 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/122707 Tested-by: Jenkins Reviewed-by: László Németh <[email protected]> diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx b/sw/qa/extras/uiwriter/uiwriter2.cxx index 1a9cbdc7d84f..4a273afa49a1 100644 --- a/sw/qa/extras/uiwriter/uiwriter2.cxx +++ b/sw/qa/extras/uiwriter/uiwriter2.cxx @@ -3194,6 +3194,58 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf50447_keep_hints) } } +CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf144272) +{ + SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "tdf50447.fodt"); + + SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell(); + + // turn on red-lining and show changes + pDoc->getIDocumentRedlineAccess().SetRedlineFlags(RedlineFlags::On | RedlineFlags::ShowDelete + | RedlineFlags::ShowInsert); + CPPUNIT_ASSERT_MESSAGE("redlining should be on", + pDoc->getIDocumentRedlineAccess().IsRedlineOn()); + CPPUNIT_ASSERT_MESSAGE( + "redlines should be visible", + IDocumentRedlineAccess::IsShowChanges(pDoc->getIDocumentRedlineAccess().GetRedlineFlags())); + + // paragraph style of the first paragraph: Heading 1, second paragraph: Standard + + CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), + getProperty<OUString>(getParagraph(1), "ParaStyleName")); + CPPUNIT_ASSERT_EQUAL(OUString("Standard"), + getProperty<OUString>(getParagraph(2), "ParaStyleName")); + + // modify with track changes: Standard and Heading 2 + + uno::Sequence<beans::PropertyValue> aPropertyValues = comphelper::InitPropertySequence({ + { "Style", uno::makeAny(OUString("Standard")) }, + { "FamilyName", uno::makeAny(OUString("ParagraphStyles")) }, + }); + dispatchCommand(mxComponent, ".uno:StyleApply", aPropertyValues); + pWrtShell->Down(/*bSelect=*/false); + aPropertyValues = comphelper::InitPropertySequence({ + { "Style", uno::makeAny(OUString("Heading 2")) }, + { "FamilyName", uno::makeAny(OUString("ParagraphStyles")) }, + }); + dispatchCommand(mxComponent, ".uno:StyleApply", aPropertyValues); + + CPPUNIT_ASSERT_EQUAL(OUString("Standard"), + getProperty<OUString>(getParagraph(1), "ParaStyleName")); + CPPUNIT_ASSERT_EQUAL(OUString("Heading 2"), + getProperty<OUString>(getParagraph(2), "ParaStyleName")); + + // reject tracked changes + dispatchCommand(mxComponent, ".uno:RejectAllTrackedChanges", {}); + + // This was Standard (missing reject) + CPPUNIT_ASSERT_EQUAL(OUString("Heading 1"), + getProperty<OUString>(getParagraph(1), "ParaStyleName")); + // This was Heading 2 (missing reject) + CPPUNIT_ASSERT_EQUAL(OUString("Standard"), + getProperty<OUString>(getParagraph(2), "ParaStyleName")); +} + CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, testTdf101873) { SwDoc* pDoc = createSwDoc(); diff --git a/sw/source/core/edit/edfcol.cxx b/sw/source/core/edit/edfcol.cxx index 6b76f14623b9..dbed7a76db0f 100644 --- a/sw/source/core/edit/edfcol.cxx +++ b/sw/source/core/edit/edfcol.cxx @@ -68,6 +68,8 @@ #include <vcl/weld.hxx> #include <vcl/virdev.hxx> +#include <redline.hxx> +#include <poolfmt.hxx> #include <hintids.hxx> #include <doc.hxx> #include <IDocumentUndoRedo.hxx> @@ -2216,6 +2218,21 @@ void SwEditShell::SetTextFormatColl(SwTextFormatColl *pFormat, GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eRedlMode ); } + // store previous paragraph style for track changes + OUString sParaStyleName; + sal_uInt16 nPoolId = USHRT_MAX; + SwContentNode * pCnt = rPaM.Start()->nNode.GetNode().GetContentNode(); + if ( pCnt && pCnt->GetTextNode() && GetDoc()->getIDocumentRedlineAccess().IsRedlineOn() ) + { + const SwTextFormatColl* pTextFormatColl = pCnt->GetTextNode()->GetTextColl(); + sal_uInt16 nStylePoolId = pTextFormatColl->GetPoolFormatId(); + // default paragraph style + if ( nStylePoolId == RES_POOLCOLL_STANDARD ) + nPoolId = nStylePoolId; + else + sParaStyleName = pTextFormatColl->GetName(); + } + // Change the paragraph style to pLocal and remove all direct paragraph formatting. GetDoc()->SetTextFormatColl(rPaM, pLocal, true, bResetListAttrs, GetLayout()); @@ -2227,6 +2244,27 @@ void SwEditShell::SetTextFormatColl(SwTextFormatColl *pFormat, aPaM.End()->nContent = pEndTextNode->GetText().getLength(); } GetDoc()->RstTextAttrs(aPaM, /*bInclRefToxMark=*/false, /*bExactRange=*/true, GetLayout()); + + // add redline tracking the previous paragraph style + if ( GetDoc()->getIDocumentRedlineAccess().IsRedlineOn() && + // multi-paragraph ParagraphFormat redline ranges + // haven't supported by AppendRedline(), yet + // TODO handle multi-paragraph selections, too, + // e.g. by breaking them to single paragraphs + aPaM.Start()->nNode == aPaM.End()->nNode ) + { + SwRangeRedline * pRedline = new SwRangeRedline( RedlineType::ParagraphFormat, aPaM ); + auto const result(GetDoc()->getIDocumentRedlineAccess().AppendRedline( pRedline, true)); + // store original paragraph style to reject formatting change + if ( IDocumentRedlineAccess::AppendResult::IGNORED != result && + ( nPoolId == RES_POOLCOLL_STANDARD || !sParaStyleName.isEmpty() ) ) + { + std::unique_ptr<SwRedlineExtraData_FormatColl> xExtra; + xExtra.reset(new SwRedlineExtraData_FormatColl(sParaStyleName, nPoolId, nullptr)); + if (xExtra) + pRedline->SetExtraData( xExtra.get() ); + } + } } }
