summaryrefslogtreecommitdiff
path: root/writerfilter
diff options
context:
space:
mode:
authorTamás Zolnai <tamas.zolnai@collabora.com>2019-07-10 18:22:31 +0200
committerTamás Zolnai <tamas.zolnai@collabora.com>2019-07-17 11:40:00 +0200
commit047220d82b3eefa5fdeec186752b70205a16369b (patch)
treeb4b8fcfca643326bc64b91d8cef31dc5e502297d /writerfilter
parent38229d47b2aec0f49da56ce937a203a8b4ca1fb3 (diff)
MSForms: Rework text-based date form field's representation
* Better to represent it similar to text form field with two marking characters selecting a text range * So the text between the two marks can be anything (not only a well formatted date) and also have any character formatting. * With this we handle the case when the user needs a placeholder text in the date field or when the user needs time values (hour, minute, sec) next to the date. Reviewed-on: https://gerrit.libreoffice.org/75459 Tested-by: Jenkins Reviewed-by: Tamás Zolnai <tamas.zolnai@collabora.com> (cherry picked from commit 68e1be4ccbb90ee9a788962219a88312c4ffbea2) Change-Id: Id60a50a2028058f8a6a080e265c0730d88b98543
Diffstat (limited to 'writerfilter')
-rw-r--r--writerfilter/source/dmapper/DomainMapper.cxx81
-rw-r--r--writerfilter/source/dmapper/SdtHelper.cxx41
-rw-r--r--writerfilter/source/dmapper/SdtHelper.hxx12
3 files changed, 83 insertions, 51 deletions
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index b542d43bc2c0..95bd864fc63a 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -2408,6 +2408,7 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext )
case NS_ooxml::LN_CT_SdtPr_date:
{
resolveSprmProps(*this, rSprm);
+ m_pImpl->m_pSdtHelper->setDateFieldStartRange(GetCurrentTextRange()->getEnd());
}
break;
case NS_ooxml::LN_CT_SdtDate_dateFormat:
@@ -3009,10 +3010,6 @@ void DomainMapper::lcl_startCharacterGroup()
// call setSdtEndDeferred(false) here, that will happen only in lcl_utext().
m_pImpl->GetTopContext()->Insert(PROP_SDT_END_BEFORE, uno::makeAny(true), true, CHAR_GRAB_BAG);
}
-
- // Remember formatting of the date control as it only supports plain strings natively.
- if (!m_pImpl->m_pSdtHelper->getDateFormat().isEmpty())
- enableInteropGrabBag("CharFormat");
}
void DomainMapper::lcl_endCharacterGroup()
@@ -3181,48 +3178,43 @@ void DomainMapper::lcl_utext(const sal_uInt8 * data_, size_t len)
return;
}
}
- else if (m_pImpl->m_pSdtHelper->validateDateFormat())
- {
- // Date field will be imported, so we don't need the corresponding date text in most of the cases
- // however when fullDate is not specified, but we have a date string we need to import it as
- // simple text (this is the case when user sets date field manually in MSO).
- if((!m_pImpl->m_pSdtHelper->getDate().toString().isEmpty() || sText.isEmpty()) &&
- (!IsInHeaderFooter() || !m_pImpl->IsDiscardHeaderFooter())) // discard date control with header / footer
- {
- return;
- }
- // Remove date field attributes to avoid to import an actual date field
- m_pImpl->m_pSdtHelper->getDateFormat().truncate();
- m_pImpl->m_pSdtHelper->getLocale().truncate();
- }
else if (!m_pImpl->m_pSdtHelper->isInteropGrabBagEmpty())
{
- // there are unsupported SDT properties in the document
- // save them in the paragraph interop grab bag
- if (m_pImpl->IsDiscardHeaderFooter())
+ // Ignore grabbag when we have a date field, it can conflict during export
+ if(m_pImpl->m_pSdtHelper->validateDateFormat())
{
- // Unless we're supposed to ignore this header/footer.
m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear();
- return;
}
- if((m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_checkbox") ||
- m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_text") ||
- m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_dataBinding") ||
- m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_citation") ||
- (m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_id") &&
- m_pImpl->m_pSdtHelper->getInteropGrabBagSize() == 1)) && !m_pImpl->m_pSdtHelper->isOutsideAParagraph())
+ else
{
- PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_CHARACTER);
- if (m_pImpl->IsOpenField())
- // We have a field, insert the SDT properties to the field's grab-bag, so they won't be lost.
- pContext = m_pImpl->GetTopFieldContext()->getProperties();
+ // there are unsupported SDT properties in the document
+ // save them in the paragraph interop grab bag
+ if (m_pImpl->IsDiscardHeaderFooter())
+ {
+ // Unless we're supposed to ignore this header/footer.
+ m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear();
+ return;
+ }
+ if((m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_checkbox") ||
+ m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_text") ||
+ m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_dataBinding") ||
+ m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_citation") ||
+ (m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_id") &&
+ m_pImpl->m_pSdtHelper->getInteropGrabBagSize() == 1)) && !m_pImpl->m_pSdtHelper->isOutsideAParagraph())
+ {
+ PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_CHARACTER);
- pContext->Insert(PROP_SDTPR, uno::makeAny(m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear()), true, CHAR_GRAB_BAG);
+ if (m_pImpl->IsOpenField())
+ // We have a field, insert the SDT properties to the field's grab-bag, so they won't be lost.
+ pContext = m_pImpl->GetTopFieldContext()->getProperties();
+
+ pContext->Insert(PROP_SDTPR, uno::makeAny(m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear()), true, CHAR_GRAB_BAG);
+ }
+ else
+ m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH)->Insert(PROP_SDTPR,
+ uno::makeAny(m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear()), true, PARA_GRAB_BAG);
}
- else
- m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH)->Insert(PROP_SDTPR,
- uno::makeAny(m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear()), true, PARA_GRAB_BAG);
}
else if (len == 1 && sText[0] == 0x03)
{
@@ -3248,6 +3240,21 @@ void DomainMapper::lcl_utext(const sal_uInt8 * data_, size_t len)
return;
}
}
+ else if (m_pImpl->m_pSdtHelper->validateDateFormat())
+ {
+ if(IsInHeaderFooter() && m_pImpl->IsDiscardHeaderFooter())
+ {
+ m_pImpl->m_pSdtHelper->getDateFormat().truncate();
+ m_pImpl->m_pSdtHelper->getLocale().truncate();
+ return;
+ }
+ if((m_pImpl->hasTableManager() && m_pImpl->getTableManager().isInTable()) ||
+ m_pImpl->m_nTableDepth > 0)
+ {
+ // Inside a table we need to import date field earlier
+ m_pImpl->m_pSdtHelper->createDateContentControl(true);
+ }
+ }
if (!m_pImpl->hasTableManager())
return;
diff --git a/writerfilter/source/dmapper/SdtHelper.cxx b/writerfilter/source/dmapper/SdtHelper.cxx
index 6dd39b71b03c..0a109c53d000 100644
--- a/writerfilter/source/dmapper/SdtHelper.cxx
+++ b/writerfilter/source/dmapper/SdtHelper.cxx
@@ -98,24 +98,40 @@ bool SdtHelper::validateDateFormat()
return !m_sDateFormat.toString().isEmpty() && !m_sLocale.toString().isEmpty();
}
-void SdtHelper::createDateContentControl()
+void SdtHelper::createDateContentControl(bool bInsideTable)
{
+ if(!m_xDateFieldStartRange.is())
+ return;
+
uno::Reference<text::XTextCursor> xCrsr;
if(m_rDM_Impl.HasTopText())
{
uno::Reference<text::XTextAppend> xTextAppend = m_rDM_Impl.GetTopTextAppend();
if (xTextAppend.is())
- xCrsr = xTextAppend->createTextCursorByRange(xTextAppend->getEnd());
+ {
+ xCrsr = xTextAppend->createTextCursorByRange(xTextAppend);
+ }
}
if (xCrsr.is())
{
+ try
+ {
+ xCrsr->gotoRange(m_xDateFieldStartRange, false);
+ if(bInsideTable)
+ xCrsr->goRight(1, false);
+ xCrsr->gotoEnd(true);
+ }
+ catch (uno::Exception&) {
+ OSL_ENSURE(false, "Cannot get the right text range for date field");
+ return;
+ }
+
uno::Reference< uno::XInterface > xFieldInterface;
- xFieldInterface = m_rDM_Impl.GetTextFactory()->createInstance("com.sun.star.text.FormFieldmark");
+ xFieldInterface = m_rDM_Impl.GetTextFactory()->createInstance("com.sun.star.text.Fieldmark");
uno::Reference< text::XFormField > xFormField( xFieldInterface, uno::UNO_QUERY );
uno::Reference< text::XTextContent > xToInsert(xFormField, uno::UNO_QUERY);
if ( xFormField.is() && xToInsert.is() )
{
- xCrsr->gotoEnd(true);
xToInsert->attach( uno::Reference< text::XTextRange >( xCrsr, uno::UNO_QUERY_THROW ));
xFormField->setFieldType(ODF_FORMDATE);
uno::Reference<container::XNameContainer> xNameCont = xFormField->getParameters();
@@ -126,15 +142,14 @@ void SdtHelper::createDateContentControl()
sDateFormat = sDateFormat.replaceAll("'", "\"");
xNameCont->insertByName(ODF_FORMDATE_DATEFORMAT, uno::makeAny(sDateFormat));
xNameCont->insertByName(ODF_FORMDATE_DATEFORMAT_LANGUAGE, uno::makeAny(m_sLocale.makeStringAndClear()));
- OUString sDate = m_sDate.makeStringAndClear();
- if(!sDate.isEmpty())
- {
- // Remove time part of the full date
- sal_Int32 nTimeSep = sDate.indexOf("T");
- if(nTimeSep != -1)
- sDate = sDate.copy(0, nTimeSep);
- xNameCont->insertByName(ODF_FORMDATE_CURRENTDATE, uno::makeAny(sDate));
- }
+ }
+ OUString sFullDate = m_sDate.makeStringAndClear();
+ if(!sFullDate.isEmpty())
+ {
+ sal_Int32 nTimeSep = sFullDate.indexOf("T");
+ if(nTimeSep != -1)
+ sFullDate = sFullDate.copy(0, nTimeSep);
+ xNameCont->insertByName(ODF_FORMDATE_CURRENTDATE, uno::makeAny(sFullDate));
}
}
}
diff --git a/writerfilter/source/dmapper/SdtHelper.hxx b/writerfilter/source/dmapper/SdtHelper.hxx
index 01abd4117adb..5efb397edd8a 100644
--- a/writerfilter/source/dmapper/SdtHelper.hxx
+++ b/writerfilter/source/dmapper/SdtHelper.hxx
@@ -13,6 +13,7 @@
#include <vector>
#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
#include <rtl/ustrbuf.hxx>
#include <tools/ref.hxx>
@@ -56,6 +57,8 @@ class SdtHelper final : public virtual SvRefBase
OUStringBuffer m_sDate;
/// Date format string as it comes from the ooxml document.
OUStringBuffer m_sDateFormat;
+ /// Start range of the date field
+ css::uno::Reference<css::text::XTextRange> m_xDateFieldStartRange;
/// Locale string as it comes from the ooxml document.
OUStringBuffer m_sLocale;
/// Grab bag to store unsupported SDTs, aiming to save them back on export.
@@ -79,15 +82,22 @@ public:
{
return m_aSdtTexts;
}
+
OUStringBuffer& getDate()
{
return m_sDate;
}
+
OUStringBuffer& getDateFormat()
{
return m_sDateFormat;
}
+ void setDateFieldStartRange(const css::uno::Reference<css::text::XTextRange>& xStartRange)
+ {
+ m_xDateFieldStartRange = xStartRange;
+ }
+
/// Decides if we have enough information to create a date control.
bool validateDateFormat();
@@ -114,7 +124,7 @@ public:
/// Create drop-down control from w:sdt's w:dropDownList.
void createDropDownControl();
/// Create date control from w:sdt's w:date.
- void createDateContentControl();
+ void createDateContentControl(bool bInsideTable = false);
void appendToInteropGrabBag(const css::beans::PropertyValue& rValue);
css::uno::Sequence<css::beans::PropertyValue> getInteropGrabBagAndClear();