summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2012-08-02 17:01:19 +0100
committerCaolán McNamara <caolanm@redhat.com>2012-08-03 10:55:43 +0100
commit27c2fe405ca55a2630176a657fb4895c5e31fcea (patch)
treeac4b00a96e7882647b5cc21c0c133b2ece54d538
parentab852cc0b6fe6e3a8b398b7fa0313a1425adf31b (diff)
Related: fdo#46757 extend ModelToViewHelper for more cases
beef up ModelToViewHelper to be able to optionally expand fields, collapse hidden text and collapse/expand redline deleted text Change-Id: I6d4d0969102ad9699f7fafe091b2eff6a5707bc4
-rw-r--r--sw/CppunitTest_sw_swdoc_test.mk1
-rw-r--r--sw/inc/modeltoviewhelper.hxx37
-rw-r--r--sw/qa/core/swdoc-test.cxx111
-rw-r--r--sw/source/core/txtnode/ndtxt.cxx152
4 files changed, 263 insertions, 38 deletions
diff --git a/sw/CppunitTest_sw_swdoc_test.mk b/sw/CppunitTest_sw_swdoc_test.mk
index 94ebab35597f..b3ab7d72f3f0 100644
--- a/sw/CppunitTest_sw_swdoc_test.mk
+++ b/sw/CppunitTest_sw_swdoc_test.mk
@@ -77,6 +77,7 @@ $(eval $(call gb_CppunitTest_use_externals,sw_swdoc_test,\
$(eval $(call gb_CppunitTest_set_include,sw_swdoc_test,\
-I$(SRCDIR)/sw/source/ui/inc \
+ -I$(SRCDIR)/sw/source/core/inc \
-I$(SRCDIR)/sw/inc \
$$(INCLUDE) \
))
diff --git a/sw/inc/modeltoviewhelper.hxx b/sw/inc/modeltoviewhelper.hxx
index c7a80c5b4278..835044d61e3e 100644
--- a/sw/inc/modeltoviewhelper.hxx
+++ b/sw/inc/modeltoviewhelper.hxx
@@ -34,7 +34,38 @@ class SwTxtNode;
to expand the fields to get the string as it appears in the view. Two
helper functions are provided to convert model positions to view positions
and vice versa.
+
+ CH_TXTATR_BREAKWORD -> SwTxtNode will have field attributes associated with these
+ . .
+ . .
+ . .
+ AAAAA BBBBB # CCCCC # DDDDD
+ | | | |
+ | | | |
+ | ---------
+ | | .
+ | | .
+ | | .......... bounds of a hidden text character attribute
+ ------
+ .
+ .
+ .............. a range of text defined in redline region as deleted
+
+ 0000: pass through gives: AAAAA BBBBB # CCCCC # DDDDD
+ 0001: only expanding fields gives: AAAAA BBBBB foo CCCCC foo DDDDD
+ 0010: only hiding hiddens gives: AAAAA CCCCC # DDDDD
+ 0100: only hiding redlines gives: AAAABB # CCCCC # DDDDD
+ 0011: expanding fields + hiding hiddens gives: AAAAA CCCC foo DDDDD
+ 0101: expanding fields + hiding redlines gives: AAAA B foo CCCCC foo DDDDD
+ 0110: hiding hiddens + hiding redlines gives: AAAACCCC # DDDDD
+ 0111: expanding fields + hiding hiddens + hiding redlines gives: AAAABB foo CCCCC foo DDDDD
*/
+
+#define PASSTHROUGH 0x0000
+#define EXPANDFIELDS 0x0001
+#define HIDEINVISIBLE 0x0002
+#define HIDEREDLINED 0x0004
+
class ModelToViewHelper
{
/** For each field in the model string, there is an entry in the conversion
@@ -67,8 +98,10 @@ public:
ModelPosition() : mnPos(0), mnSubPos(0), mbIsField(false) {}
};
- ModelToViewHelper(const SwTxtNode &rNode);
- ModelToViewHelper() {} //pass through filter, view == model
+ ModelToViewHelper(const SwTxtNode &rNode, int eMode = EXPANDFIELDS);
+ ModelToViewHelper() //pass through filter, view == model
+ {
+ }
/** Converts a model position into a view position
diff --git a/sw/qa/core/swdoc-test.cxx b/sw/qa/core/swdoc-test.cxx
index 3e26b1f2d451..a5df1433aaa6 100644
--- a/sw/qa/core/swdoc-test.cxx
+++ b/sw/qa/core/swdoc-test.cxx
@@ -38,6 +38,7 @@
#include <unotools/tempfile.hxx>
#include <editeng/langitem.hxx>
+#include <editeng/charhiddenitem.hxx>
#include <sfx2/app.hxx>
#include <sfx2/docfilt.hxx>
@@ -63,6 +64,8 @@
#include "fmtfld.hxx"
#include "redline.hxx"
#include "docary.hxx"
+#include "modeltoviewhelper.hxx"
+#include "scriptinfo.hxx"
SO2_DECL_REF(SwDocShell)
SO2_IMPL_REF(SwDocShell)
@@ -81,6 +84,7 @@ public:
void testPageDescName();
void testFileNameFields();
void testDocStat();
+ void testModelToViewHelper();
void testSwScanner();
void testUserPerceivedCharCount();
void testGraphicAnchorDeletion();
@@ -90,6 +94,7 @@ public:
CPPUNIT_TEST(testPageDescName);
CPPUNIT_TEST(testFileNameFields);
CPPUNIT_TEST(testDocStat);
+ CPPUNIT_TEST(testModelToViewHelper);
CPPUNIT_TEST(testSwScanner);
CPPUNIT_TEST(testUserPerceivedCharCount);
CPPUNIT_TEST(testGraphicAnchorDeletion);
@@ -222,6 +227,112 @@ void SwDocTest::testUserPerceivedCharCount()
CPPUNIT_ASSERT_MESSAGE("Surrogate Pair should be counted as single character", nCount == 1);
}
+void SwDocTest::testModelToViewHelper()
+{
+ SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
+ SwPaM aPaM(aIdx);
+
+ {
+ SwFmtFtn aFtn;
+ aFtn.SetNumStr(rtl::OUString("foo"));
+
+ m_pDoc->AppendTxtNode(*aPaM.GetPoint());
+ m_pDoc->InsertString(aPaM, rtl::OUString("AAAAA BBBBB "));
+ SwTxtNode* pTxtNode = aPaM.GetNode()->GetTxtNode();
+ xub_StrLen nPos = aPaM.GetPoint()->nContent.GetIndex();
+ pTxtNode->InsertItem(aFtn, nPos, nPos);
+ m_pDoc->InsertString(aPaM, rtl::OUString(" CCCCC "));
+ nPos = aPaM.GetPoint()->nContent.GetIndex();
+ pTxtNode->InsertItem(aFtn, nPos, nPos);
+ m_pDoc->InsertString(aPaM, rtl::OUString(" DDDDD"));
+ CPPUNIT_ASSERT(pTxtNode->GetTxt().Len() == (4*5) + 5 + 2);
+
+ //set start of selection to first B
+ aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), 6);
+ aPaM.SetMark();
+ //set end of selection to last C
+ aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), 14);
+ //set character attribute hidden on range
+ SvxCharHiddenItem aHidden(true, RES_CHRATR_HIDDEN);
+ m_pDoc->InsertPoolItem(aPaM, aHidden, 0 );
+
+ //turn on red-lining and show changes
+ m_pDoc->SetRedlineMode(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_DELETE|nsRedlineMode_t::REDLINE_SHOW_INSERT);
+ CPPUNIT_ASSERT_MESSAGE("redlining should be on", m_pDoc->IsRedlineOn());
+ CPPUNIT_ASSERT_MESSAGE("redlines should be visible", IDocumentRedlineAccess::IsShowChanges(m_pDoc->GetRedlineMode()));
+
+ //set start of selection to last A
+ aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), 4);
+ aPaM.SetMark();
+ //set end of selection to second last B
+ aPaM.GetPoint()->nContent.Assign(aPaM.GetCntntNode(), 9);
+ m_pDoc->DeleteAndJoin(aPaM); //redline-aware deletion api
+
+ {
+ ModelToViewHelper aModelToViewHelper(*pTxtNode, PASSTHROUGH);
+ rtl::OUString sViewText = aModelToViewHelper.getViewText();
+ rtl::OUString sModelText = pTxtNode->GetTxt();
+ CPPUNIT_ASSERT(sViewText == sModelText);
+ }
+
+ {
+ ModelToViewHelper aModelToViewHelper(*pTxtNode, EXPANDFIELDS);
+ rtl::OUString sViewText = aModelToViewHelper.getViewText();
+ CPPUNIT_ASSERT(sViewText == "AAAAA BBBBB foo CCCCC foo DDDDD");
+ }
+
+ {
+ ModelToViewHelper aModelToViewHelper(*pTxtNode, HIDEINVISIBLE);
+ rtl::OUString sViewText = aModelToViewHelper.getViewText();
+ rtl::OUStringBuffer aBuffer;
+ aBuffer.append("AAAAA CCCCC ");
+ aBuffer.append(CH_TXTATR_BREAKWORD);
+ aBuffer.append(" DDDDD");
+ CPPUNIT_ASSERT(sViewText == aBuffer.makeStringAndClear());
+ }
+
+ {
+ ModelToViewHelper aModelToViewHelper(*pTxtNode, HIDEREDLINED);
+ rtl::OUString sViewText = aModelToViewHelper.getViewText();
+ rtl::OUStringBuffer aBuffer;
+ aBuffer.append("AAAABB ");
+ aBuffer.append(CH_TXTATR_BREAKWORD);
+ aBuffer.append(" CCCCC ");
+ aBuffer.append(CH_TXTATR_BREAKWORD);
+ aBuffer.append(" DDDDD");
+ CPPUNIT_ASSERT(sViewText == aBuffer.makeStringAndClear());
+ }
+
+ {
+ ModelToViewHelper aModelToViewHelper(*pTxtNode, EXPANDFIELDS | HIDEINVISIBLE);
+ rtl::OUString sViewText = aModelToViewHelper.getViewText();
+ CPPUNIT_ASSERT(sViewText == "AAAAA CCCCC foo DDDDD");
+ }
+
+ {
+ ModelToViewHelper aModelToViewHelper(*pTxtNode, EXPANDFIELDS | HIDEREDLINED);
+ rtl::OUString sViewText = aModelToViewHelper.getViewText();
+ CPPUNIT_ASSERT(sViewText == "AAAABB foo CCCCC foo DDDDD");
+ }
+
+ {
+ ModelToViewHelper aModelToViewHelper(*pTxtNode, HIDEINVISIBLE | HIDEREDLINED);
+ rtl::OUString sViewText = aModelToViewHelper.getViewText();
+ rtl::OUStringBuffer aBuffer;
+ aBuffer.append("AAAACCCCC ");
+ aBuffer.append(CH_TXTATR_BREAKWORD);
+ aBuffer.append(" DDDDD");
+ CPPUNIT_ASSERT(sViewText == aBuffer.makeStringAndClear());
+ }
+
+ {
+ ModelToViewHelper aModelToViewHelper(*pTxtNode, EXPANDFIELDS | HIDEINVISIBLE | HIDEREDLINED);
+ rtl::OUString sViewText = aModelToViewHelper.getViewText();
+ CPPUNIT_ASSERT(sViewText == "AAAACCCCC foo DDDDD");
+ }
+ }
+}
+
void SwDocTest::testSwScanner()
{
SwNodeIndex aIdx(m_pDoc->GetNodes().GetEndOfContent(), -1);
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 90e9a2b6f26c..22ddb66b2934 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -37,6 +37,7 @@
#include <editeng/tstpitem.hxx>
#include <svl/urihelper.hxx>
#include <svl/ctloptions.hxx>
+#include <tools/multisel.hxx>
#include <swmodule.hxx>
#include <txtfld.hxx>
#include <txtinet.hxx>
@@ -3092,52 +3093,131 @@ sal_Bool SwTxtNode::GetExpandTxt( SwTxtNode& rDestNd, const SwIndex* pDestIdx,
return sal_True;
}
-ModelToViewHelper::ModelToViewHelper(const SwTxtNode &rNode)
+struct block
+{
+ sal_Int32 m_nStart;
+ sal_Int32 m_nLen;
+ bool m_bVisible;
+ std::vector<const SwTxtAttr*> m_aAttrs;
+ block(sal_Int32 nStart, sal_Int32 nLen, bool bVisible)
+ : m_nStart(nStart), m_nLen(nLen), m_bVisible(bVisible)
+ {
+ }
+};
+
+struct containsPos
+{
+ const sal_Int32 m_nPos;
+ containsPos(const sal_Int32 nPos)
+ : m_nPos(nPos)
+ {
+ }
+ bool operator() (const block& rIn) const
+ {
+ return m_nPos >= rIn.m_nStart && m_nPos < rIn.m_nStart + rIn.m_nLen;
+ }
+};
+
+ModelToViewHelper::ModelToViewHelper(const SwTxtNode &rNode, int eMode)
{
const rtl::OUString& rNodeText = rNode.GetTxt();
m_aRetText = rNodeText;
- const SwpHints* pSwpHints2 = rNode.GetpSwpHints();
- xub_StrLen nPos = 0;
+ if (eMode == PASSTHROUGH)
+ return;
+
+ Range aRange( 0, rNodeText.isEmpty() ? 0 : rNodeText.getLength() - 1);
+ MultiSelection aHiddenMulti(aRange);
+
+ if (eMode & HIDEINVISIBLE)
+ SwScriptInfo::selectHiddenTextProperty(rNode, aHiddenMulti);
- for ( sal_uInt16 i = 0; pSwpHints2 && i < pSwpHints2->Count(); ++i )
+ if (eMode & HIDEREDLINED)
+ SwScriptInfo::selectRedLineDeleted(rNode, aHiddenMulti);
+
+ std::vector<block> aBlocks;
+
+ sal_Int32 nShownStart = 0;
+ for (size_t i = 0; i < aHiddenMulti.GetRangeCount(); ++i)
{
- const SwTxtAttr* pAttr = (*pSwpHints2)[i];
- bool bReplace = false;
- xub_StrLen nFieldPos(STRING_NOTFOUND);
- rtl::OUString aExpand;
- switch (pAttr->Which())
+ const Range& rRange = aHiddenMulti.GetRange(i);
+ sal_Int32 nHiddenStart = rRange.Min();
+ sal_Int32 nHiddenEnd = rRange.Max() + 1;
+ sal_Int32 nHiddenLen = nHiddenEnd - nHiddenStart;
+
+ sal_Int32 nShownEnd = nHiddenStart;
+ sal_Int32 nShownLen = nShownEnd - nShownStart;
+
+ if (nShownLen)
+ aBlocks.push_back(block(nShownStart, nShownLen, true));
+
+ if (nHiddenLen)
+ aBlocks.push_back(block(nHiddenStart, nHiddenLen, false));
+
+ nShownStart = nHiddenEnd;
+ }
+
+ sal_Int32 nTrailingShownLen = rNodeText.getLength() - nShownStart;
+ if (nTrailingShownLen)
+ aBlocks.push_back(block(nShownStart, nTrailingShownLen, true));
+
+ if (eMode & EXPANDFIELDS)
+ {
+ const SwpHints* pSwpHints2 = rNode.GetpSwpHints();
+ for ( sal_uInt16 i = 0; pSwpHints2 && i < pSwpHints2->Count(); ++i )
{
- case RES_TXTATR_FIELD:
- bReplace = true;
- aExpand =
- static_cast<SwTxtFld const*>(pAttr)->GetFld().GetFld()
- ->ExpandField(true);
- nFieldPos = *pAttr->GetStart();
- break;
- case RES_TXTATR_FTN:
- {
- bReplace = true;
- const SwFmtFtn& rFtn = static_cast<SwTxtFtn const*>(pAttr)->GetFtn();
- const SwDoc *pDoc = rNode.GetDoc();
- aExpand = rFtn.GetViewNumStr(*pDoc);
- nFieldPos = *pAttr->GetStart();
- }
- break;
- default:
- if (pAttr->HasDummyChar())
- {
- bReplace = true;
- nFieldPos = *pAttr->GetStart();
- }
- break;
+ const SwTxtAttr* pAttr = (*pSwpHints2)[i];
+ if (pAttr->HasDummyChar())
+ {
+ xub_StrLen nDummyCharPos = *pAttr->GetStart();
+ if (aHiddenMulti.IsSelected(nDummyCharPos))
+ continue;
+ std::vector<block>::iterator aFind = std::find_if(aBlocks.begin(), aBlocks.end(), containsPos(nDummyCharPos));
+ aFind->m_aAttrs.push_back(pAttr);
+ }
}
+ }
+
+ sal_Int32 nOffset = 0;
+ for (std::vector<block>::iterator i = aBlocks.begin(); i != aBlocks.end(); ++i)
+ {
+ if (!i->m_bVisible)
+ {
+ const sal_Int32 nHiddenStart = i->m_nStart;
+ const sal_Int32 nHiddenLen = i->m_nLen;
- if (bReplace)
+ m_aRetText = m_aRetText.replaceAt( nOffset + nHiddenStart, nHiddenLen, rtl::OUString() );
+ m_aMap.push_back( ConversionMapEntry( nHiddenStart, nOffset + nHiddenStart ) );
+ nOffset -= nHiddenLen;
+ }
+ else
{
- m_aRetText = m_aRetText.replaceAt( nPos + nFieldPos, 1, aExpand );
- m_aMap.push_back( ConversionMapEntry( nFieldPos, nPos + nFieldPos ) );
- nPos += ( aExpand.getLength() - 1 );
+ for (std::vector<const SwTxtAttr*>::iterator j = i->m_aAttrs.begin(); j != i->m_aAttrs.end(); ++j)
+ {
+ const SwTxtAttr* pAttr = *j;
+ xub_StrLen nFieldPos = *pAttr->GetStart();
+ rtl::OUString aExpand;
+ switch (pAttr->Which())
+ {
+ case RES_TXTATR_FIELD:
+ aExpand =
+ static_cast<SwTxtFld const*>(pAttr)->GetFld().GetFld()
+ ->ExpandField(true);
+ break;
+ case RES_TXTATR_FTN:
+ {
+ const SwFmtFtn& rFtn = static_cast<SwTxtFtn const*>(pAttr)->GetFtn();
+ const SwDoc *pDoc = rNode.GetDoc();
+ aExpand = rFtn.GetViewNumStr(*pDoc);
+ }
+ break;
+ default:
+ break;
+ }
+ m_aRetText = m_aRetText.replaceAt( nOffset + nFieldPos, 1, aExpand );
+ m_aMap.push_back( ConversionMapEntry( nFieldPos, nOffset + nFieldPos ) );
+ nOffset += ( aExpand.getLength() - 1 );
+ }
}
}