sw/inc/ToxTextGenerator.hxx | 26 +++++ sw/inc/chpfld.hxx | 4 sw/qa/cppunit/tox/test_ToxTextGenerator.cxx | 92 +++++++++++++++++++ sw/source/core/tox/ToxTextGenerator.cxx | 129 ++++++++++++++++++---------- 4 files changed, 204 insertions(+), 47 deletions(-)
New commits: commit 0a1b1511faaa3302429d93ccdad3eb41dc8f36cb Author: Tobias Lippert <d...@fastmail.fm> Date: Sun Jun 1 14:24:51 2014 +0200 Unittest generation of text for chapter entries in the TOC Conflicts: sw/inc/ToxTextGenerator.hxx sw/qa/cppunit/tox/test_ToxTextGenerator.cxx sw/source/core/tox/ToxTextGenerator.cxx Change-Id: I343958f85fb6718215a0caa456a825d72f168a57 Reviewed-on: https://gerrit.libreoffice.org/9612 Reviewed-by: Caolán McNamara <caol...@redhat.com> Tested-by: Caolán McNamara <caol...@redhat.com> diff --git a/sw/inc/ToxTextGenerator.hxx b/sw/inc/ToxTextGenerator.hxx index ba79177..fa52fba 100644 --- a/sw/inc/ToxTextGenerator.hxx +++ b/sw/inc/ToxTextGenerator.hxx @@ -30,8 +30,13 @@ class SfxItemSet; class SwAttrPool; class SwFmtAutoFmt; +class SwChapterField; +class SwChapterFieldType; +class SwCntntFrm; +class SwCntntNode; class SwDoc; class SwForm; +class SwFormToken; class SwPageDesc; class SwTxtAttr; class SwTxtNode; @@ -47,7 +52,7 @@ class SW_DLLPUBLIC ToxTextGenerator public: ToxTextGenerator(const SwForm& toxForm); - ~ToxTextGenerator(); + virtual ~ToxTextGenerator(); /** Generate the text for an entry of a table of X (X is, e.g., content). * @@ -118,6 +123,25 @@ private: static OUString GetNumStringOfFirstNode(const SwTOXSortTabBase& rBase, bool bUsePrefix, sal_uInt8 nLevel); + /** Handle a chapter token. + */ + OUString + HandleChapterToken(const SwTOXSortTabBase& rBase, const SwFormToken& aToken, SwDoc* pDoc) const; + + /** Generate the text for a chapter token. + */ + OUString + GenerateTextForChapterToken(const SwFormToken& chapterToken, const SwCntntFrm* contentFrame, + const SwCntntNode *contentNode) const; + + /** Obtain a ChapterField to use for the text generation. + * @internal + * This method is overridden in the unittests. Do not override it yourself. + */ + virtual SwChapterField + ObtainChapterField(SwChapterFieldType* chapterFieldType, const SwFormToken* chapterToken, + const SwCntntFrm* contentFrame, const SwCntntNode *contentNode) const; + friend class ::ToxTextGeneratorTest; }; diff --git a/sw/inc/chpfld.hxx b/sw/inc/chpfld.hxx index 452c42c..dc59de1 100644 --- a/sw/inc/chpfld.hxx +++ b/sw/inc/chpfld.hxx @@ -24,6 +24,7 @@ class SwFrm; class SwCntntNode; class SwTxtNode; +class ToxTextGeneratorTest; enum SwChapterFormat { @@ -36,7 +37,7 @@ enum SwChapterFormat CF_END }; -class SwChapterFieldType : public SwFieldType +class SW_DLLPUBLIC SwChapterFieldType : public SwFieldType { public: SwChapterFieldType(); @@ -48,6 +49,7 @@ public: class SW_DLLPUBLIC SwChapterField : public SwField { friend class SwChapterFieldType; + friend class ToxTextGeneratorTest; // the unittest needs to mock the chapter fields. sal_uInt8 nLevel; OUString sTitle; OUString sNumber; diff --git a/sw/qa/cppunit/tox/test_ToxTextGenerator.cxx b/sw/qa/cppunit/tox/test_ToxTextGenerator.cxx index c2e1dcb..7ef8506 100644 --- a/sw/qa/cppunit/tox/test_ToxTextGenerator.cxx +++ b/sw/qa/cppunit/tox/test_ToxTextGenerator.cxx @@ -8,6 +8,7 @@ */ #include "rtl/ustring.hxx" +#include "chpfld.hxx" #include "tox.hxx" #include "txmsrt.hxx" #include "ToxTextGenerator.hxx" @@ -25,12 +26,18 @@ public: void OneAtSignIsReturnedForPageNumberPlaceholderOfOneItem(); void TwoAtSignsAreReturnedForPageNumberPlaceholderOfOneItem(); void EmptyStringIsReturnedAsNumStringIfNoTextMarkIsSet(); + void EmptyStringIsReturnedAsNumStringIfToxSourcesIsEmpty(); + void ChapterNumberWithoutTextIsGeneratedForNoprepstTitle(); + void ChapterNumberWithTitleIsGeneratedForNumberNoPrepst(); CPPUNIT_TEST_SUITE(ToxTextGeneratorTest); CPPUNIT_TEST(EmptyStringIsReturnedForPageNumberPlaceholderOfZeroItems); CPPUNIT_TEST(OneAtSignIsReturnedForPageNumberPlaceholderOfOneItem); CPPUNIT_TEST(TwoAtSignsAreReturnedForPageNumberPlaceholderOfOneItem); CPPUNIT_TEST(EmptyStringIsReturnedAsNumStringIfNoTextMarkIsSet); + CPPUNIT_TEST(EmptyStringIsReturnedAsNumStringIfToxSourcesIsEmpty); + CPPUNIT_TEST(ChapterNumberWithoutTextIsGeneratedForNoprepstTitle); + CPPUNIT_TEST(ChapterNumberWithTitleIsGeneratedForNumberNoPrepst); CPPUNIT_TEST_SUITE_END(); }; @@ -82,6 +89,91 @@ ToxTextGeneratorTest::EmptyStringIsReturnedAsNumStringIfNoTextMarkIsSet() CPPUNIT_ASSERT_EQUAL(expected, actual); } +void +ToxTextGeneratorTest::EmptyStringIsReturnedAsNumStringIfToxSourcesIsEmpty() +{ + MockedSortTab sortTab; + sortTab.pTxtMark = reinterpret_cast<SwTxtTOXMark*>(1); + + OUString expected(""); + OUString actual = ToxTextGenerator::GetNumStringOfFirstNode(sortTab, false, 0); + CPPUNIT_ASSERT_EQUAL(expected, actual); +} + +class ToxTextGeneratorWithMockedChapterField : public ToxTextGenerator { +public: + ToxTextGeneratorWithMockedChapterField(SwForm &form) + : ToxTextGenerator(form), mChapterFieldType(), mChapterField(&mChapterFieldType) {;} + + SwChapterField& + GetChapterField() { + return mChapterField; + } + +private: + SwChapterField + ObtainChapterField(SwChapterFieldType* chapterFieldType, const SwFormToken* chapterToken, + const SwCntntFrm* contentFrame, const SwCntntNode *contentNode) const { + // get rid of 'unused-parameters' warnings + (void)(chapterFieldType);(void)(chapterToken);(void)(contentFrame);(void)(contentNode); + return mChapterField; + } + + SwChapterFieldType mChapterFieldType; + SwChapterField mChapterField; +}; + +void +ToxTextGeneratorTest::ChapterNumberWithoutTextIsGeneratedForNoprepstTitle() +{ + SwForm form; + ToxTextGeneratorWithMockedChapterField ttg(form); + // set all values to make sure they are not used + ttg.GetChapterField().sNumber = "1"; + ttg.GetChapterField().sPre = "PRE"; + ttg.GetChapterField().sPost = "POST"; + ttg.GetChapterField().sTitle = "TITLE"; + + SwFormToken token(TOKEN_CHAPTER_INFO); + token.nChapterFormat = CF_NUM_NOPREPST_TITLE; + + OUString expected("1"); + OUString actual = ttg.GenerateTextForChapterToken(token, NULL, NULL); + CPPUNIT_ASSERT_EQUAL(expected, actual); + + // we cannot mock the pre- and suffix generation in the chapterfield. We just test that sNumber and + // sTitle are used and hope that the pre- and suffix addition works. + token.nChapterFormat = CF_NUMBER; + expected = ttg.GenerateTextForChapterToken(token, NULL, NULL); + CPPUNIT_ASSERT_EQUAL(expected, actual); +} + + +void +ToxTextGeneratorTest::ChapterNumberWithTitleIsGeneratedForNumberNoPrepst() +{ + SwForm form; + ToxTextGeneratorWithMockedChapterField ttg(form); + // set all values to make sure they are not used + ttg.GetChapterField().sNumber = "5"; + ttg.GetChapterField().sPre = "PRE"; + ttg.GetChapterField().sPost = "POST"; + ttg.GetChapterField().sTitle = "myTitle"; + + SwFormToken token(TOKEN_CHAPTER_INFO); + token.nChapterFormat = CF_NUMBER_NOPREPST; + + OUString expected("5 myTitle"); + OUString actual = ttg.GenerateTextForChapterToken(token, NULL, NULL); + CPPUNIT_ASSERT_EQUAL(expected, actual); + + // we cannot mock the pre- and suffix generation in the chapterfield. We just test that sNumber and + // sTitle are used and hope that the pre- and suffix addition works. + token.nChapterFormat = CF_NUM_TITLE; + expected = ttg.GenerateTextForChapterToken(token, NULL, NULL); + CPPUNIT_ASSERT_EQUAL(expected, actual); +} + // Put the test suite in the registry CPPUNIT_TEST_SUITE_REGISTRATION(ToxTextGeneratorTest); diff --git a/sw/source/core/tox/ToxTextGenerator.cxx b/sw/source/core/tox/ToxTextGenerator.cxx index 1360f6d..67de2cd 100644 --- a/sw/source/core/tox/ToxTextGenerator.cxx +++ b/sw/source/core/tox/ToxTextGenerator.cxx @@ -46,18 +46,34 @@ #include <boost/foreach.hpp> #include <boost/make_shared.hpp> +#include <cassert> + +namespace { + +bool sortTabHasNoToxSourcesOrFirstToxSourceHasNoNode(const SwTOXSortTabBase& sortTab) +{ + if (sortTab.aTOXSources.empty()) { + return true; + } + if (sortTab.aTOXSources.at(0).pNd != NULL) { + return true; + } + return false; +} + +} // end anonymous namespace namespace sw { OUString ToxTextGenerator::GetNumStringOfFirstNode( const SwTOXSortTabBase& rBase, bool bUsePrefix, sal_uInt8 nLevel ) { - OUString sRet; - if (!rBase.pTxtMark) { // only if it's not a Mark - return sRet; + if (sortTabHasNoToxSourcesOrFirstToxSourceHasNoNode(rBase)) { + return OUString(); } - if (rBase.aTOXSources.empty()) { + OUString sRet; + if (!rBase.pTxtMark) { // only if it's not a Mark return sRet; } @@ -87,6 +103,54 @@ ToxTextGenerator::ToxTextGenerator(const SwForm& toxForm) ToxTextGenerator::~ToxTextGenerator() {;} +OUString +ToxTextGenerator::HandleChapterToken(const SwTOXSortTabBase& rBase, const SwFormToken& aToken, + SwDoc* pDoc) const +{ + if (sortTabHasNoToxSourcesOrFirstToxSourceHasNoNode(rBase)) { + return OUString(); + } + + // A bit tricky: Find a random Frame + const SwCntntNode* contentNode = rBase.aTOXSources.at(0).pNd->GetCntntNode(); + if (!contentNode) { + return OUString(); + } + + // #i53420# + const SwCntntFrm* contentFrame = contentNode->getLayoutFrm(pDoc->GetCurrentLayout()); + if (!contentFrame) { + return OUString(); + } + + return GenerateTextForChapterToken(aToken, contentFrame, contentNode); +} + +OUString +ToxTextGenerator::GenerateTextForChapterToken(const SwFormToken& chapterToken, const SwCntntFrm* contentFrame, + const SwCntntNode *contentNode) const +{ + OUString retval; + + SwChapterFieldType chapterFieldType; + SwChapterField aFld = ObtainChapterField(&chapterFieldType, &chapterToken, contentFrame, contentNode); + + //---> #i89791# + // continue to support CF_NUMBER and CF_NUM_TITLE in order to handle ODF 1.0/1.1 written by OOo 3.x + // in the same way as OOo 2.x would handle them. + if (CF_NUM_NOPREPST_TITLE == chapterToken.nChapterFormat || CF_NUMBER == chapterToken.nChapterFormat) { + retval += aFld.GetNumber(); // get the string number without pre/postfix + } + else if (CF_NUMBER_NOPREPST == chapterToken.nChapterFormat || CF_NUM_TITLE == chapterToken.nChapterFormat) { + retval += aFld.GetNumber(); + retval += " "; + retval += aFld.GetTitle(); + } else if (CF_TITLE == chapterToken.nChapterFormat) { + retval += aFld.GetTitle(); + } + return retval; +} + // Add parameter <_TOXSectNdIdx> and <_pDefaultPageDesc> in order to control, // which page description is used, no appropriate one is found. void ToxTextGenerator::GenerateText(SwDoc* pDoc, const std::vector<SwTOXSortTabBase*> &entries, @@ -224,46 +288,7 @@ void ToxTextGenerator::GenerateText(SwDoc* pDoc, const std::vector<SwTOXSortTabB break; case TOKEN_CHAPTER_INFO: - { - // A bit tricky: Find a random Frame - const SwTOXSource* pTOXSource = 0; - if (!rBase.aTOXSources.empty()) - pTOXSource = &rBase.aTOXSources[0]; - - // #i53420# - if ( pTOXSource && pTOXSource->pNd && - pTOXSource->pNd->IsCntntNode() ) - { - const SwCntntFrm* pFrm = pTOXSource->pNd->getLayoutFrm( pDoc->GetCurrentLayout() ); - if( pFrm ) - { - SwChapterFieldType aFldTyp; - SwChapterField aFld( &aFldTyp, aToken.nChapterFormat ); - aFld.SetLevel( static_cast<sal_uInt8>(aToken.nOutlineLevel - 1) ); - // #i53420# - aFld.ChangeExpansion( pFrm, - dynamic_cast<const SwCntntNode*>(pTOXSource->pNd), - true ); - //---> #i89791# - // continue to support CF_NUMBER - // and CF_NUM_TITLE in order to handle ODF 1.0/1.1 - // written by OOo 3.x in the same way as OOo 2.x - // would handle them. - if ( CF_NUM_NOPREPST_TITLE == aToken.nChapterFormat || - CF_NUMBER == aToken.nChapterFormat ) - rTxt += aFld.GetNumber(); // get the string number without pre/postfix - else if ( CF_NUMBER_NOPREPST == aToken.nChapterFormat || - CF_NUM_TITLE == aToken.nChapterFormat ) - { - rTxt += aFld.GetNumber(); - rTxt += " "; - rTxt += aFld.GetTitle(); - } - else if(CF_TITLE == aToken.nChapterFormat) - rTxt += aFld.GetTitle(); - } - } - } + rTxt += HandleChapterToken(rBase, aToken, pDoc); break; case TOKEN_LINK_START: @@ -375,7 +400,7 @@ ToxTextGenerator::ApplyHandledTextToken(const HandledTextToken& htt, SwTxtNode& } } -OUString +/*static*/ OUString ToxTextGenerator::ConstructPageNumberPlaceholder(size_t numberOfToxSources) { OUString retval; @@ -392,6 +417,20 @@ ToxTextGenerator::ConstructPageNumberPlaceholder(size_t numberOfToxSources) return retval; } +/*virtual*/ SwChapterField +ToxTextGenerator::ObtainChapterField(SwChapterFieldType* chapterFieldType, + const SwFormToken* chapterToken, const SwCntntFrm* contentFrame, + const SwCntntNode* contentNode) const +{ + assert(chapterToken); + assert(chapterToken->nOutlineLevel >= 1); + + SwChapterField retval(chapterFieldType, chapterToken->nChapterFormat); + retval.SetLevel(static_cast<sal_uInt8>(chapterToken->nOutlineLevel - 1)); + // #i53420# + retval.ChangeExpansion(contentFrame, contentNode, true); + return retval; +} } // end namespace sw /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits