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 <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
This commit is contained in:
Tobias Lippert
2014-06-01 14:24:51 +02:00
committed by Caolán McNamara
parent 1534c33633
commit 0a1b1511fa
4 changed files with 204 additions and 47 deletions

View File

@@ -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;
};

View File

@@ -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;

View File

@@ -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);

View File

@@ -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: */