diff options
author | Eilidh McAdam <eilidh.mcadam@itomig.de> | 2014-12-10 03:50:10 +0000 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2014-12-19 18:20:28 +0100 |
commit | 8826934016d60d0a4a1e824e3f1cff814d915515 (patch) | |
tree | ca1a860c96110c9f72e619f150d69ce4bcd5be52 | |
parent | 3726737273e488ffab02f4a2dded5640521729cb (diff) |
Support for docx import of fixed date and time fields.
If a field is fixed, mark it as such and parse value to seed it.
This is the other half of the docx filter improvement for fdo#59886.
Reviewed on:
https://gerrit.libreoffice.org/13431
Change-Id: Id00c454921cd386589e04b9572f4040898625a6f
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper.cxx | 4 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.cxx | 76 | ||||
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper_Impl.hxx | 7 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLFastContextHandler.cxx | 9 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLFastContextHandler.hxx | 1 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLPropertySetImpl.cxx | 20 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLPropertySetImpl.hxx | 14 | ||||
-rw-r--r-- | writerfilter/source/ooxml/factoryimpl_ns.py | 8 | ||||
-rw-r--r-- | writerfilter/source/ooxml/model.xml | 5 |
9 files changed, 137 insertions, 7 deletions
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx index ec5afab1440a..2f0e43d64ec5 100644 --- a/writerfilter/source/dmapper/DomainMapper.cxx +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -2826,6 +2826,10 @@ void DomainMapper::lcl_text(const sal_uInt8 * data_, size_t len) switch(*data_) { case 0x02: return; //footnote character + case 0x08: // Lock field if in field context + if (m_pImpl->IsOpenField()) + m_pImpl->SetFieldLocked(); + return; case 0x0c: //page break m_pImpl->deferBreak(PAGE_BREAK); return; diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index d080ae84c1e1..a3694bd9e660 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -161,6 +161,7 @@ DomainMapper_Impl::DomainMapper_Impl( m_xComponentContext( xContext ), m_bSetUserFieldContent( false ), m_bSetCitation( false ), + m_bSetDateValue( false ), m_bIsFirstSection( true ), m_bIsColumnBreakDeferred( false ), m_bIsPageBreakDeferred( false ), @@ -2588,6 +2589,13 @@ bool DomainMapper_Impl::IsOpenField() const return !m_aFieldStack.empty(); } +// Mark top field context as containing a fixed field +void DomainMapper_Impl::SetFieldLocked() +{ + if (IsOpenField()) + m_aFieldStack.top()->SetFieldLocked(); +} + HeaderFooterContext::HeaderFooterContext(bool bTextInserted) : m_bTextInserted(bTextInserted) { @@ -2600,7 +2608,8 @@ bool HeaderFooterContext::getTextInserted() FieldContext::FieldContext(uno::Reference< text::XTextRange > const& xStart) : m_bFieldCommandCompleted(false) - ,m_xStartRange( xStart ) + , m_xStartRange( xStart ) + , m_bFieldLocked( false ) { m_pProperties.reset(new PropertyMap()); } @@ -3399,6 +3408,7 @@ void DomainMapper_Impl::CloseFieldCommand() { m_bSetUserFieldContent = false; m_bSetCitation = false; + m_bSetDateValue = false; FieldConversionMap_t aFieldConversionMap = lcl_GetFieldConversion(); try @@ -3509,10 +3519,19 @@ void DomainMapper_Impl::CloseFieldCommand() case FIELD_DATE: if (xFieldProperties.is()) { - //not fixed, - xFieldProperties->setPropertyValue( - rPropNameSupplier.GetName(PROP_IS_FIXED), - uno::makeAny( false )); + // Get field fixed property from the context handler + if (pContext->IsFieldLocked()) + { + xFieldProperties->setPropertyValue( + rPropNameSupplier.GetName(PROP_IS_FIXED), + uno::makeAny( true )); + m_bSetDateValue = true; + } + else + xFieldProperties->setPropertyValue( + rPropNameSupplier.GetName(PROP_IS_FIXED), + uno::makeAny( false )); + xFieldProperties->setPropertyValue( rPropNameSupplier.GetName(PROP_IS_DATE), uno::makeAny( true )); @@ -3902,7 +3921,16 @@ void DomainMapper_Impl::CloseFieldCommand() case FIELD_SYMBOL : break; case FIELD_TEMPLATE: break; case FIELD_TIME : + { + if (pContext->IsFieldLocked()) + { + xFieldProperties->setPropertyValue( + rPropNameSupplier.GetName(PROP_IS_FIXED), + uno::makeAny( true )); + m_bSetDateValue = true; + } SetNumberFormat( pContext->GetCommand(), xFieldProperties ); + } break; case FIELD_TITLE : { @@ -4084,6 +4112,29 @@ void DomainMapper_Impl::AppendFieldResult(OUString const& rString) } } +// Calculates css::DateTime based on ddddd.sssss since 1900-1-0 +::com::sun::star::util::DateTime lcl_dateTimeFromSerial(const double& dSerial) +{ + const sal_uInt32 secondsPerDay = 86400; + const sal_uInt16 secondsPerHour = 3600; + + DateTime d(Date(30, 12, 1899)); + d += (long)dSerial; + + double frac = dSerial - (long)dSerial; + sal_uInt32 seconds = frac * secondsPerDay; + + ::com::sun::star::util::DateTime date; + date.Year = d.GetYear(); + date.Month = d.GetMonth(); + date.Day = d.GetDay(); + date.Hours = seconds / secondsPerHour; + date.Minutes = (seconds % secondsPerHour) / 60; + date.Seconds = seconds % 60; + + return date; +} + void DomainMapper_Impl::SetFieldResult(OUString const& rResult) { #ifdef DEBUG_WRITERFILTER @@ -4159,6 +4210,21 @@ void DomainMapper_Impl::SetFieldResult(OUString const& rResult) uno::makeAny(aValues)); } } + else if ( m_bSetDateValue ) + { + uno::Reference< util::XNumberFormatsSupplier > xNumberSupplier( m_xTextDocument, uno::UNO_QUERY_THROW ); + + uno::Reference< util::XNumberFormatter > xFormatter( ::com::sun::star::util::NumberFormatter::create( m_xComponentContext ), uno::UNO_QUERY_THROW ); + xFormatter->attachNumberFormatsSupplier( xNumberSupplier ); + sal_Int32 nKey = 0; + + uno::Reference< beans::XPropertySet > xFieldProperties( xTextField, uno::UNO_QUERY_THROW); + + xFieldProperties->getPropertyValue( "NumberFormat" ) >>= nKey; + xFieldProperties->setPropertyValue( + "DateTimeValue", + uno::makeAny( lcl_dateTimeFromSerial( xFormatter->convertStringToNumber( nKey, rResult ) ) ) ); + } else { uno::Reference< beans::XPropertySet > xFieldProperties( xTextField, uno::UNO_QUERY_THROW); diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx index 535772bc17d6..30fef54df9d7 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx @@ -139,6 +139,7 @@ class FieldContext OUString m_sCommand; OUString m_sResult; + bool m_bFieldLocked; ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextField > m_xTextField; ::com::sun::star::uno::Reference< ::com::sun::star::text::XFormField > m_xFormField; @@ -166,6 +167,9 @@ public: void SetCommandCompleted() { m_bFieldCommandCompleted = true; } bool IsCommandCompleted() const { return m_bFieldCommandCompleted; } + void SetFieldLocked() { m_bFieldLocked = true; } + bool IsFieldLocked() { return m_bFieldLocked; } + ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > GetCustomField() const { return m_xCustomField; } void SetCustomField( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > const& xCustomField ) { m_xCustomField = xCustomField; } ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextField > GetTextField() const { return m_xTextField;} @@ -330,6 +334,7 @@ private: FieldStack m_aFieldStack; bool m_bSetUserFieldContent; bool m_bSetCitation; + bool m_bSetDateValue; bool m_bIsFirstSection; bool m_bIsColumnBreakDeferred; bool m_bIsPageBreakDeferred; @@ -614,6 +619,8 @@ public: //the current field context waits for the completion of the command bool IsOpenFieldCommand() const; bool IsOpenField() const; + //mark field in current context as locked (fixed) + void SetFieldLocked(); //collect the pieces of the command void AppendFieldCommand(OUString& rPartOfCommand); void handleFieldAsk diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx index 40f5b3b5c5fc..a461ed7089ac 100644 --- a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx +++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx @@ -47,6 +47,7 @@ static const sal_uInt8 cFtnEdnCont = 0x4; static const sal_uInt8 cFieldStart = 0x13; static const sal_uInt8 cFieldSep = 0x14; static const sal_uInt8 cFieldEnd = 0x15; +static const sal_uInt8 cFieldLock = 0x8; namespace writerfilter { namespace ooxml @@ -552,6 +553,14 @@ void OOXMLFastContextHandler::endField() endCharacterGroup(); } +void OOXMLFastContextHandler::lockField() +{ + startCharacterGroup(); + if (isForwardEvents()) + mpStream->text(&cFieldLock, 1); + endCharacterGroup(); +} + void OOXMLFastContextHandler::ftnednref() { if (isForwardEvents()) diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx index 33ea6e02f0cd..a90fa8419cb5 100644 --- a/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx +++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.hxx @@ -164,6 +164,7 @@ public: void startField(); void fieldSeparator(); void endField(); + void lockField(); void ftnednref(); void ftnedncont(); void ftnednsep(); diff --git a/writerfilter/source/ooxml/OOXMLPropertySetImpl.cxx b/writerfilter/source/ooxml/OOXMLPropertySetImpl.cxx index 52e755061e5e..fcd7e2bd8d6e 100644 --- a/writerfilter/source/ooxml/OOXMLPropertySetImpl.cxx +++ b/writerfilter/source/ooxml/OOXMLPropertySetImpl.cxx @@ -831,6 +831,9 @@ void OOXMLPropertySetEntryToString::attribute(Id nId, Value & rValue) mStr = rValue.getString(); } +/* + class: OOXMLPropertySetEntryToInteger +*/ OOXMLPropertySetEntryToInteger::OOXMLPropertySetEntryToInteger(Id nId) : mnId(nId), mnValue(0) @@ -851,6 +854,23 @@ void OOXMLPropertySetEntryToInteger::attribute(Id nId, Value & rValue) mnValue = rValue.getInt(); } +/* + class: OOXMLPropertySetEntryToBool +*/ + +OOXMLPropertySetEntryToBool::OOXMLPropertySetEntryToBool(Id nId) + : mnId(nId), mValue(false) +{} + +OOXMLPropertySetEntryToBool::~OOXMLPropertySetEntryToBool() {} + +void OOXMLPropertySetEntryToBool::sprm(Sprm & /*rSprm*/) {} + +void OOXMLPropertySetEntryToBool::attribute(Id nId, Value & rValue) +{ + if (nId == mnId) + mValue = (rValue.getInt() != 0); +} }} diff --git a/writerfilter/source/ooxml/OOXMLPropertySetImpl.hxx b/writerfilter/source/ooxml/OOXMLPropertySetImpl.hxx index 123160015a70..9d3ca78c8399 100644 --- a/writerfilter/source/ooxml/OOXMLPropertySetImpl.hxx +++ b/writerfilter/source/ooxml/OOXMLPropertySetImpl.hxx @@ -324,6 +324,20 @@ public: int getValue() const { return mnValue;} }; +class OOXMLPropertySetEntryToBool : public Properties +{ + Id mnId; + bool mValue; +public: + OOXMLPropertySetEntryToBool(Id nId); + virtual ~OOXMLPropertySetEntryToBool(); + + virtual void sprm(Sprm & rSprm) SAL_OVERRIDE; + virtual void attribute(Id nId, Value & rValue) SAL_OVERRIDE; + + bool getValue() const { return mValue; } +}; + } // namespace ooxml } // namespace writerfilter diff --git a/writerfilter/source/ooxml/factoryimpl_ns.py b/writerfilter/source/ooxml/factoryimpl_ns.py index 407bb49898eb..90c7ecdd2a8c 100644 --- a/writerfilter/source/ooxml/factoryimpl_ns.py +++ b/writerfilter/source/ooxml/factoryimpl_ns.py @@ -451,6 +451,14 @@ def factoryChooseAction(actionNode): ret.append(" %spHandler->fieldSeparator();" % (extra_space)) elif actionNode.getAttribute("action") == "fieldend": ret.append(" %spHandler->endField();" % (extra_space)) + elif actionNode.getAttribute("action") == "fieldlock": + ret.append(" %s{" % (extra_space)) + ret.append(" %sOOXMLPropertySetEntryToBool aHandler(NS_ooxml::LN_CT_FldChar_fldLock);" % (extra_space)) + ret.append(" %sif (OOXMLFastContextHandlerStream* pStream = dynamic_cast<OOXMLFastContextHandlerStream*>(pHandler))" % (extra_space)) + ret.append(" %spStream->getPropertySetAttrs()->resolve(aHandler);" % (extra_space)) + ret.append(" %sif (aHandler.getValue())" % (extra_space)) + ret.append(" %spHandler->lockField();" % (extra_space)) + ret.append(" %s}" % (extra_space)) elif actionNode.getAttribute("action") == "printproperty": ret.append(" %sif (OOXMLFastContextHandlerStream* pStream = dynamic_cast<OOXMLFastContextHandlerStream*>(pHandler))" % extra_space) ret.append(" %s pStream->sendProperty(%s);" % (extra_space, idToLabel(actionNode.getAttribute("sendtokenid")))) diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml index 925d7ac88667..fc671afda9b5 100644 --- a/writerfilter/source/ooxml/model.xml +++ b/writerfilter/source/ooxml/model.xml @@ -12521,7 +12521,7 @@ <text/> </attribute> <attribute name="fldLock"> - <text/> + <ref name="ST_OnOff"/> </attribute> <attribute name="dirty"> <text/> @@ -12574,7 +12574,7 @@ <ref name="ST_FldCharType"/> </attribute> <attribute name="fldLock"> - <text/> + <ref name="ST_OnOff"/> </attribute> <attribute name="dirty"> <text/> @@ -17511,6 +17511,7 @@ <action name="start" action="fieldend"> <cond tokenid="ooxml:CT_FldChar_fldCharType" value="ooxml:Value_ST_FldCharType_end"/> </action> + <action name="start" action="fieldlock"/> </resource> <resource name="CT_Hyperlink" resource="Stream"> <attribute name="tgtFrame" tokenid="ooxml:CT_Hyperlink_tgtFrame"/> |