Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sw/qa/core/doc/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 15 kB image not shown  

Quelle  DocumentRedlineManager.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */


#include <swmodeltestbase.hxx>

#include <editeng/wghtitem.hxx>
#include <comphelper/scopeguard.hxx>
#include <comphelper/propertyvalue.hxx>

#include <IDocumentRedlineAccess.hxx>
#include <docsh.hxx>
#include <redline.hxx>
#include <view.hxx>
#include <wrtsh.hxx>
#include <swmodule.hxx>
#include <strings.hrc>
#include <fchrfmt.hxx>
#include <ndtxt.hxx>

namespace
{
/// Covers sw/source/core/doc/DocumentRedlineManager.cxx fixes.
class Test : public SwModelTestBase
{
public:
    Test()
        : SwModelTestBase(u"/sw/qa/core/doc/data/"_ustr)
    {
    }
};

CPPUNIT_TEST_FIXTURE(Test, testRedlineIns)
{
    // Given a document with an insert redline:
    createSwDoc("ins.docx");

    // When selecting BBB (a subset of the insert) and marking that as bold:
    SwDocShell* pDocShell = getSwDocShell();
    SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
    pWrtShell->SttEndDoc(/*bStt=*/true);
    pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 3, /*bBasicCall=*/false);
    pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 3, /*bBasicCall=*/false);
    SwView& rView = pWrtShell->GetView();
    {
        SvxWeightItem aWeightItem(WEIGHT_BOLD, RES_CHRATR_WEIGHT);
        SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END> aSet(rView.GetPool());
        aSet.Put(aWeightItem);
        pWrtShell->SetAttrSet(aSet);
    }

    // Then make sure BBB is covered by an insert-then-format redline:
    SwDoc* pDoc = getSwDocShell()->GetDoc();
    IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess();
    SwRedlineTable& rRedlines = rIDRA.GetRedlineTable();
    {
        // Without the accompanying fix in place, this test would have failed with:
        // - Expected: 1
        // - Actual  : 3
        // i.e. no redline was created for the format change.
        CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), rRedlines.size());
        CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlines[0]->GetType());
        const SwRedlineData& rRedlineData1 = rRedlines[1]->GetRedlineData(0);
        CPPUNIT_ASSERT_EQUAL(RedlineType::Format, rRedlineData1.GetType());
        CPPUNIT_ASSERT(rRedlineData1.Next());
        const SwRedlineData& rInnerRedlineData = *rRedlineData1.Next();
        CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rInnerRedlineData.GetType());
        CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlines[2]->GetType());
    }

    // And when undoing:
    pWrtShell->Undo();

    // Then make sure we again have a single insert that covers all text:
    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: 1
    // - Actual  : 2
    // i.e. the insert redline of BBB was lost on undo.
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());
    CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlines[0]->GetType());
    CPPUNIT_ASSERT_EQUAL(u"AAABBBCCC"_ustr, rRedlines[0]->GetText());

    // And when redoing:
    pWrtShell->Redo();

    // Then make sure we get <ins>AAA<format>BBB</format>CCC</ins>:
    {
        CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), rRedlines.size());
        CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlines[0]->GetType());
        const SwRedlineData& rRedlineData1 = rRedlines[1]->GetRedlineData(0);
        CPPUNIT_ASSERT_EQUAL(RedlineType::Format, rRedlineData1.GetType());
        // Without the accompanying fix in place, this test would have failed, the "format" redline
        // has no underlying "insert" redline.
        CPPUNIT_ASSERT(rRedlineData1.Next());
        const SwRedlineData& rInnerRedlineData = *rRedlineData1.Next();
        CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rInnerRedlineData.GetType());
        CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlines[2]->GetType());
    }
}

CPPUNIT_TEST_FIXTURE(Test, testInsThenFormatSelf)
{
    // Given a document with <ins>A<format>B</format>C</ins> redlines, created by Alice:
    createSwDoc("ins-then-format-self.docx");
    SwModule* pModule = SwModule::get();
    pModule->SetRedlineAuthor("Alice");
    comphelper::ScopeGuard g(
        [pModule] { pModule->SetRedlineAuthor(SwResId(STR_REDLINE_UNKNOWN_AUTHOR)); });
    SwDocShell* pDocShell = getSwDocShell();
    SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
    pWrtShell->SttEndDoc(/*bStt=*/false);
    SwDoc* pDoc = pDocShell->GetDoc();
    IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess();
    SwRedlineTable& rRedlines = rIDRA.GetRedlineTable();
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), rRedlines.size());
    pWrtShell->DelLeft();
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), rRedlines.size());

    // When deleting B:
    pWrtShell->DelLeft();

    // Then make sure that B is removed from the document (since this is a self-insert):
    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: 1
    // - Actual  : 2
    // i.e. a delete was created instead of removing the insert.
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());
}

CPPUNIT_TEST_FIXTURE(Test, testFormatRedlineRecordOldCharStyle)
{
    // Given a document with one char style applied + redline record on:
    createSwDoc();
    SwDocShell* pDocShell = getSwDocShell();
    SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
    pWrtShell->Insert(u"x"_ustr);
    pWrtShell->SelAll();
    uno::Sequence<beans::PropertyValue> aPropertyValues = {
        comphelper::makePropertyValue(u"Style"_ustr, uno::Any(u"Emphasis"_ustr)),
        comphelper::makePropertyValue(u"FamilyName"_ustr, uno::Any(u"CharacterStyles"_ustr)),
    };
    dispatchCommand(mxComponent, u".uno:StyleApply"_ustr, aPropertyValues);
    pDocShell->SetChangeRecording(true);

    // When changing to a second char style:
    aPropertyValues = {
        comphelper::makePropertyValue(u"Style"_ustr, uno::Any(u"Strong Emphasis"_ustr)),
        comphelper::makePropertyValue(u"FamilyName"_ustr, uno::Any(u"CharacterStyles"_ustr)),
    };
    dispatchCommand(mxComponent, u".uno:StyleApply"_ustr, aPropertyValues);

    // Then make sure the redline refers to the old char style and just to that:
    SwDoc* pDoc = pDocShell->GetDoc();
    IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess();
    SwRedlineTable& rRedlines = rIDRA.GetRedlineTable();
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());
    const SwRangeRedline& rRedline = *rRedlines[0];
    CPPUNIT_ASSERT_EQUAL(RedlineType::Format, rRedline.GetType());
    auto pExtraData = dynamic_cast<const SwRedlineExtraData_FormatColl*>(rRedline.GetExtraData());
    CPPUNIT_ASSERT(pExtraData);
    std::shared_ptr<SfxItemSet> pRedlineSet = pExtraData->GetItemSet();
    CPPUNIT_ASSERT(pRedlineSet);
    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: 1
    // - Actual  : 5
    // i.e. more than just the char style change was recorded, which was unexpected.
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt16>(1), pRedlineSet->Count());
    const SwFormatCharFormat& rOldCharFormat = pRedlineSet->Get(RES_TXTATR_CHARFMT);
    CPPUNIT_ASSERT_EQUAL(u"Emphasis"_ustr, rOldCharFormat.GetCharFormat()->GetName().toString());
}

CPPUNIT_TEST_FIXTURE(Test, testDelThenFormatDirect)
{
    // Given a document with a delete redline, part of it has a format redline on top:
    createSwDoc("del-then-format.docx");

    // When "directly" accepting the delete-then-format redline:
    SwDocShell* pDocShell = getSwDocShell();
    SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
    pWrtShell->AcceptRedline(1, /*bDirect=*/true);

    // Then make sure that the format gets accepted, and the delete redline is kept:
    SwDoc* pDoc = pDocShell->GetDoc();
    IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess();
    SwRedlineTable& rRedlines = rIDRA.GetRedlineTable();
    {
        // Without the accompanying fix in place, this test would have failed with:
        // - Expected: 1
        // - Actual  : 0
        // i.e. when ignoring the "direct" parameter, the delete redline was accepted instead of the
        // format one.
        CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());
        const SwRedlineData& rRedlineData = rRedlines[0]->GetRedlineData(0);
        CPPUNIT_ASSERT_EQUAL(RedlineType::Delete, rRedlineData.GetType());
        CPPUNIT_ASSERT(!rRedlineData.Next());

        // After first char inside the redline: bold.
        pWrtShell->SttEndDoc(/*bStt=*/true);
        pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 4, /*bBasicCall=*/false);
        SfxItemSetFixed<RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT> aSet(pDoc->GetAttrPool());
        pWrtShell->GetCurAttr(aSet);
        const SvxWeightItem& rWeightItem = aSet.Get(RES_CHRATR_WEIGHT);
        CPPUNIT_ASSERT_EQUAL(WEIGHT_BOLD, rWeightItem.GetValue());
    }

    // And given an undo, so we can redo:
    pWrtShell->Undo();
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), rRedlines.size());

    // When doing the same again via redo:
    pWrtShell->Redo();

    // Then make sure we again have a single large delete:
    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: 1
    // - Actual  : 2
    // i.e. instead of a large delete redline, we have 2 small ones for AAA and CCC only.
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());

    // And given a reset state:
    pWrtShell->Undo();
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), rRedlines.size());

    // When "directly" rejecting the delete-then-format redline:
    pWrtShell->RejectRedline(1, /*bDirect=*/true);

    // Then make sure that the format gets rejected and the delete redline is kept:
    {
        CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());
        const SwRedlineData& rRedlineData = rRedlines[0]->GetRedlineData(0);
        // Without the accompanying fix in place, this test would have failed with:
        // - Expected: 1 (delete)
        // - Actual  : 2 (format)
        // i.e. the delete redline was rejected and format remained, not the other way around.
        CPPUNIT_ASSERT_EQUAL(RedlineType::Delete, rRedlineData.GetType());
        CPPUNIT_ASSERT(!rRedlineData.Next());

        // After first char inside the redline: not bold anymore.
        pWrtShell->SttEndDoc(/*bStt=*/true);
        pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 4, /*bBasicCall=*/false);
        SfxItemSetFixed<RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT> aSet(pDoc->GetAttrPool());
        pWrtShell->GetCurAttr(aSet);
        const SvxWeightItem& rWeightItem = aSet.Get(RES_CHRATR_WEIGHT);
        CPPUNIT_ASSERT_EQUAL(WEIGHT_NORMAL, rWeightItem.GetValue());
    }

    // And given an undo:
    pWrtShell->Undo();

    // When redoing:
    pWrtShell->Redo();

    // Then make sure that we only get a single big delete redline:
    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: 1
    // - Actual  : 3
    // i.e. we got <del>AAA</del><format>BBB</format><del>CCC</del> instead of one big delete
    // redline.
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());
}

CPPUNIT_TEST_FIXTURE(Test, testInsThenFormatDirect)
{
    // Given a document with an insert redline, part of it has a format redline on top:
    createSwDoc("ins-then-format.docx");

    // When "directly" accepting the insert-then-format redline:
    SwDocShell* pDocShell = getSwDocShell();
    SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
    pWrtShell->AcceptRedline(1, /*bDirect=*/true);

    // Then make sure that the format gets accepted, and the insert redline is kept:
    SwDoc* pDoc = pDocShell->GetDoc();
    IDocumentRedlineAccess& rIDRA = pDoc->getIDocumentRedlineAccess();
    SwRedlineTable& rRedlines = rIDRA.GetRedlineTable();
    {
        // Without the accompanying fix in place, this test would have failed with:
        // - Expected: 1
        // - Actual  : 3
        // i.e. the accept didn't do anything in direct mode.
        CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());
        const SwRedlineData& rRedlineData = rRedlines[0]->GetRedlineData(0);
        CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlineData.GetType());
        CPPUNIT_ASSERT(!rRedlineData.Next());

        // After first char inside the redline: bold.
        pWrtShell->SttEndDoc(/*bStt=*/true);
        pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 4, /*bBasicCall=*/false);
        SfxItemSetFixed<RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT> aSet(pDoc->GetAttrPool());
        pWrtShell->GetCurAttr(aSet);
        const SvxWeightItem& rWeightItem = aSet.Get(RES_CHRATR_WEIGHT);
        CPPUNIT_ASSERT_EQUAL(WEIGHT_BOLD, rWeightItem.GetValue());
    }

    // And given an undo, so we can redo:
    pWrtShell->Undo();
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), rRedlines.size());

    // When doing the same again via redo:
    pWrtShell->Redo();

    // Then make sure we again have a single large insert:
    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: 1
    // - Actual  : 3
    // i.e. redo was broken, the middle part was a format redline instead of an insert redline.
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());

    // And given a reset state:
    pWrtShell->Undo();
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), rRedlines.size());

    // When "directly" rejecting the insert-then-format redline:
    pWrtShell->RejectRedline(1, /*bDirect=*/true);

    // Then make sure that the format gets rejected and the insert redline is kept:
    {
        SwTextNode* pTextNode = pWrtShell->GetCursor()->GetPointNode().GetTextNode();
        // Without the accompanying fix in place, this test would have failed with:
        // - Expected: AAABBBCCC
        // - Actual  : AAACCC
        // i.e. the insert was rejected, not the format.
        CPPUNIT_ASSERT_EQUAL(u"AAABBBCCC"_ustr, pTextNode->GetText());
        CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());
        const SwRedlineData& rRedlineData = rRedlines[0]->GetRedlineData(0);
        CPPUNIT_ASSERT_EQUAL(RedlineType::Insert, rRedlineData.GetType());
        CPPUNIT_ASSERT(!rRedlineData.Next());

        // After first char inside the redline: not bold anymore.
        pWrtShell->SttEndDoc(/*bStt=*/true);
        pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 4, /*bBasicCall=*/false);
        SfxItemSetFixed<RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT> aSet(pDoc->GetAttrPool());
        pWrtShell->GetCurAttr(aSet);
        const SvxWeightItem& rWeightItem = aSet.Get(RES_CHRATR_WEIGHT);
        CPPUNIT_ASSERT_EQUAL(WEIGHT_NORMAL, rWeightItem.GetValue());
    }

    // And given an undo:
    pWrtShell->Undo();

    // When redoing:
    pWrtShell->Redo();

    // Then make sure that we only get a single big insert redline:
    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: 1
    // - Actual  : 2
    // i.e. we got <ins>AAA</ins>BBB<ins>CCC</ins> instead of one big insert.
    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rRedlines.size());
}
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=92 H=91 G=91

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.