diff options
Diffstat (limited to 'sfx2/source/doc/SfxDocumentMetaData.cxx')
-rw-r--r-- | sfx2/source/doc/SfxDocumentMetaData.cxx | 198 |
1 files changed, 124 insertions, 74 deletions
diff --git a/sfx2/source/doc/SfxDocumentMetaData.cxx b/sfx2/source/doc/SfxDocumentMetaData.cxx index 1423e712242e..476d6f5186a5 100644 --- a/sfx2/source/doc/SfxDocumentMetaData.cxx +++ b/sfx2/source/doc/SfxDocumentMetaData.cxx @@ -66,6 +66,7 @@ #include "com/sun/star/xml/xpath/XXPathAPI.hpp" #include "com/sun/star/util/Date.hpp" #include "com/sun/star/util/Time.hpp" +#include "com/sun/star/util/Duration.hpp" #include "SfxDocumentMetaData.hxx" #include "rtl/ustrbuf.hxx" @@ -79,6 +80,7 @@ #include "comphelper/storagehelper.hxx" #include "comphelper/mediadescriptor.hxx" #include "comphelper/sequenceasvector.hxx" +#include "comphelper/stlunosequence.hxx" #include "sot/storage.hxx" #include "sfx2/docfile.hxx" #include "sax/tools/converter.hxx" @@ -322,7 +324,7 @@ private: /// standard meta data (multiple occurrences) std::map< ::rtl::OUString, std::vector<css::uno::Reference<css::xml::dom::XNode> > > m_metaList; - /// user-defined meta data (meta:user-defined) + /// user-defined meta data (meta:user-defined) @ATTENTION may be null! css::uno::Reference<css::beans::XPropertyContainer> m_xUserDefined; // now for some meta-data attributes; these are not updated directly in the // DOM because updates (detecting "empty" elements) would be quite messy @@ -468,6 +470,11 @@ const char* s_nsODFMeta = "urn:oasis:names:tc:opendocument:xmlns:meta:1.0"; const char* s_metaXml = "meta.xml"; +bool isValidDate(const css::util::Date & i_rDate) +{ + return i_rDate.Month > 0; +} + bool isValidDateTime(const css::util::DateTime & i_rDateTime) { return i_rDateTime.Month > 0; @@ -499,16 +506,25 @@ getQualifier(const char* i_name) { return ::rtl::OUString::createFromAscii(ns); } +bool SAL_CALL +textToDateOrDateTime(css::util::Date & io_rd, css::util::DateTime & io_rdt, + bool & o_rIsDateTime, ::rtl::OUString i_text) throw () +{ + if (::sax::Converter::convertDateOrDateTime( + io_rd, io_rdt, o_rIsDateTime, i_text)) { + return true; + } else { + DBG_WARNING1("SfxDocumentMetaData: invalid date: %s", + OUStringToOString(i_text, RTL_TEXTENCODING_UTF8).getStr()); + return false; + } +} + // convert string to date/time bool SAL_CALL textToDateTime(css::util::DateTime & io_rdt, ::rtl::OUString i_text) throw () { if (::sax::Converter::convertDateTime(io_rdt, i_text)) { - // NB: there may be rounding errors; handle these here - if (io_rdt.HundredthSeconds > 0) { - io_rdt.Seconds++; - io_rdt.HundredthSeconds = 0; - } return true; } else { DBG_WARNING1("SfxDocumentMetaData: invalid date: %s", @@ -527,6 +543,20 @@ textToDateTimeDefault(::rtl::OUString i_text) throw () return dt; } +// convert date to string +::rtl::OUString SAL_CALL +dateToText(css::util::Date const& i_rd) throw () +{ + if (isValidDate(i_rd)) { + ::rtl::OUStringBuffer buf; + ::sax::Converter::convertDate(buf, i_rd); + return buf.makeStringAndClear(); + } else { + return ::rtl::OUString(); + } +} + + // convert date/time to string ::rtl::OUString SAL_CALL dateTimeToText(css::util::DateTime const& i_rdt) throw () @@ -541,60 +571,48 @@ dateTimeToText(css::util::DateTime const& i_rdt) throw () } // convert string to duration -bool SAL_CALL -textToDuration(css::util::Time& io_rut, ::rtl::OUString i_text) throw () +bool +textToDuration(css::util::Duration& io_rDur, ::rtl::OUString const& i_rText) +throw () { - css::util::DateTime dt; - if (::sax::Converter::convertTime(dt, i_text)) { - // NB: there may be rounding errors; handle these here - if (dt.HundredthSeconds > 0) { - dt.Seconds++; - dt.HundredthSeconds = 0; - } - io_rut.Hours = dt.Hours; - io_rut.Minutes = dt.Minutes; - io_rut.Seconds = dt.Seconds; - io_rut.HundredthSeconds = dt.HundredthSeconds; + if (::sax::Converter::convertDuration(io_rDur, i_rText)) { return true; } else { DBG_WARNING1("SfxDocumentMetaData: invalid duration: %s", - OUStringToOString(i_text, RTL_TEXTENCODING_UTF8).getStr()); + OUStringToOString(i_rText, RTL_TEXTENCODING_UTF8).getStr()); return false; } } -sal_Int32 SAL_CALL textToDuration(::rtl::OUString i_text) throw () +sal_Int32 textToDuration(::rtl::OUString const& i_rText) throw () { - css::util::Time t; - if (textToDuration(t, i_text)) { - return t.Hours * 3600 + t.Minutes * 60 + t.Seconds; + css::util::Duration d; + if (textToDuration(d, i_rText)) { + return (d.Days * (24*3600)) + + (d.Hours * 3600) + (d.Minutes * 60) + d.Seconds; } else { return 0; // default } } // convert duration to string -::rtl::OUString SAL_CALL durationToText(css::util::Time const& i_rut) throw () +::rtl::OUString durationToText(css::util::Duration const& i_rDur) throw () { - css::util::DateTime dt; - dt.Hours = i_rut.Hours; - dt.Minutes = i_rut.Minutes; - dt.Seconds = i_rut.Seconds; - dt.HundredthSeconds = i_rut.HundredthSeconds; ::rtl::OUStringBuffer buf; - ::sax::Converter::convertTime(buf, dt); + ::sax::Converter::convertDuration(buf, i_rDur); return buf.makeStringAndClear(); } // convert duration to string ::rtl::OUString SAL_CALL durationToText(sal_Int32 i_value) throw () { - css::util::Time ut; - ut.Hours = static_cast<sal_Int16>(i_value / 3600); - ut.Minutes = static_cast<sal_Int16>((i_value % 3600) / 60); - ut.Seconds = static_cast<sal_Int16>(i_value % 60); - ut.HundredthSeconds = 0; - return durationToText(ut); + css::util::Duration ud; + ud.Days = static_cast<sal_Int16>(i_value / (24 * 3600)); + ud.Hours = static_cast<sal_Int16>((i_value % (24 * 3600)) / 3600); + ud.Minutes = static_cast<sal_Int16>((i_value % 3600) / 60); + ud.Seconds = static_cast<sal_Int16>(i_value % 60); + ud.HundredthSeconds = 0; + return durationToText(ud); } // extract base URL (necessary for converting relative links) @@ -921,17 +939,26 @@ propsToStrings(css::uno::Reference<css::beans::XPropertySet> const & i_xPropSet) } else if (type == ::cppu::UnoType<css::util::Date>::get()) { css::util::Date d; any >>= d; - css::util::DateTime dt; - dt.Year = d.Year; - dt.Month = d.Month; - dt.Day = d.Day; - values.push_back(dateTimeToText(dt)); + values.push_back(dateToText(d)); as.push_back(std::make_pair(vt, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("date")))); } else if (type == ::cppu::UnoType<css::util::Time>::get()) { + // #i97029#: replaced by Duration + // Time is supported for backward compatibility with OOo 3.x, x<=2 css::util::Time ut; any >>= ut; - values.push_back(durationToText(ut)); + css::util::Duration ud; + ud.Hours = ut.Hours; + ud.Minutes = ut.Minutes; + ud.Seconds = ut.Seconds; + ud.HundredthSeconds = ut.HundredthSeconds; + values.push_back(durationToText(ud)); + as.push_back(std::make_pair(vt, + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("time")))); + } else if (type == ::cppu::UnoType<css::util::Duration>::get()) { + css::util::Duration ud; + any >>= ud; + values.push_back(durationToText(ud)); as.push_back(std::make_pair(vt, ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("time")))); } else if (::cppu::UnoType<double>::get().isAssignableFrom(type)) { @@ -998,9 +1025,12 @@ SfxDocumentMetaData::updateElement(const char *i_name, void SAL_CALL SfxDocumentMetaData::updateUserDefinedAndAttributes() { createUserDefined(); - css::uno::Reference<css::beans::XPropertySet> xPSet(m_xUserDefined,css::uno::UNO_QUERY_THROW); - std::pair<css::uno::Sequence< ::rtl::OUString>, AttrVector> udStringsAttrs = propsToStrings(xPSet); - (void) setMetaList("meta:user-defined", udStringsAttrs.first,&udStringsAttrs.second); + const css::uno::Reference<css::beans::XPropertySet> xPSet(m_xUserDefined, + css::uno::UNO_QUERY_THROW); + const std::pair<css::uno::Sequence< ::rtl::OUString>, AttrVector> + udStringsAttrs( propsToStrings(xPSet) ); + (void) setMetaList("meta:user-defined", udStringsAttrs.first, + &udStringsAttrs.second); // update elements with attributes std::vector<std::pair<const char *, ::rtl::OUString> > attributes; @@ -1217,15 +1247,13 @@ void SAL_CALL SfxDocumentMetaData::init( std::vector<css::uno::Reference<css::xml::dom::XNode> > & vec = m_metaList[::rtl::OUString::createFromAscii("meta:user-defined")]; - // user-defined meta data: create PropertyBag which only accepts property - // values of allowed types + m_xUserDefined.clear(); // #i105826#: reset (may be re-initialization) if ( !vec.empty() ) { createUserDefined(); } // user-defined meta data: initialize PropertySet from DOM nodes - for (std::vector<css::uno::Reference<css::xml::dom::XNode> >::iterator it = vec.begin(); it != vec.end(); ++it) { css::uno::Reference<css::xml::dom::XElement> xElem(*it, @@ -1248,18 +1276,24 @@ void SAL_CALL SfxDocumentMetaData::init( continue; } } else if (type.equalsAscii("date")) { + bool isDateTime; + css::util::Date d; css::util::DateTime dt; - if (textToDateTime(dt, text)) { - any <<= dt; + if (textToDateOrDateTime(d, dt, isDateTime, text)) { + if (isDateTime) { + any <<= dt; + } else { + any <<= d; + } } else { DBG_WARNING1("SfxDocumentMetaData: invalid date: %s", OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr()); continue; } } else if (type.equalsAscii("time")) { - css::util::Time ut; - if (textToDuration(ut, text)) { - any <<= ut; + css::util::Duration ud; + if (textToDuration(ud, text)) { + any <<= ud; } else { DBG_WARNING1("SfxDocumentMetaData: invalid time: %s", OUStringToOString(text, RTL_TEXTENCODING_UTF8).getStr()); @@ -1301,10 +1335,14 @@ void SAL_CALL SfxDocumentMetaData::init( //////////////////////////////////////////////////////////////////////////// SfxDocumentMetaData::SfxDocumentMetaData( - css::uno::Reference< css::uno::XComponentContext > const & context) : - BaseMutex(), SfxDocumentMetaData_Base(m_aMutex), - m_xContext(context), m_NotifyListeners(m_aMutex), - m_isInitialized(false), m_isModified(false) + css::uno::Reference< css::uno::XComponentContext > const & context) + : BaseMutex() + , SfxDocumentMetaData_Base(m_aMutex) + , m_xContext(context) + , m_NotifyListeners(m_aMutex) + , m_isInitialized(false) + , m_isModified(false) + , m_AutoloadSecs(0) { DBG_ASSERT(context.is(), "SfxDocumentMetaData: context is null"); DBG_ASSERT(context->getServiceManager().is(), @@ -2168,7 +2206,7 @@ void SAL_CALL SfxDocumentMetaData::setModified( ::sal_Bool bModified ) ::osl::MutexGuard g(m_aMutex); checkInit(); m_isModified = bModified; - if ( !bModified ) + if ( !bModified && m_xUserDefined.is() ) { xMB.set(m_xUserDefined, css::uno::UNO_QUERY); DBG_ASSERT(xMB.is(), @@ -2241,46 +2279,58 @@ void SAL_CALL SfxDocumentMetaData::serialize( void SfxDocumentMetaData::createUserDefined() { + // user-defined meta data: create PropertyBag which only accepts property + // values of allowed types if ( !m_xUserDefined.is() ) { - css::uno::Sequence<css::uno::Type> types(10); + css::uno::Sequence<css::uno::Type> types(11); types[0] = ::cppu::UnoType<bool>::get(); types[1] = ::cppu::UnoType< ::rtl::OUString>::get(); types[2] = ::cppu::UnoType<css::util::DateTime>::get(); types[3] = ::cppu::UnoType<css::util::Date>::get(); - types[4] = ::cppu::UnoType<css::util::Time>::get(); + types[4] = ::cppu::UnoType<css::util::Duration>::get(); types[5] = ::cppu::UnoType<float>::get(); types[6] = ::cppu::UnoType<double>::get(); types[7] = ::cppu::UnoType<sal_Int16>::get(); types[8] = ::cppu::UnoType<sal_Int32>::get(); types[9] = ::cppu::UnoType<sal_Int64>::get(); + // Time is supported for backward compatibility with OOo 3.x, x<=2 + types[10] = ::cppu::UnoType<css::util::Time>::get(); css::uno::Sequence<css::uno::Any> args(2); args[0] <<= css::beans::NamedValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AllowedTypes")), css::uno::makeAny(types)); - // #i94175#: ODF 1.1 allows empty user-defined property names! - args[1] <<= css::beans::NamedValue( - ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AllowEmptyPropertyName")), + // #i94175#: ODF allows empty user-defined property names! + args[1] <<= css::beans::NamedValue( ::rtl::OUString( + RTL_CONSTASCII_USTRINGPARAM("AllowEmptyPropertyName")), css::uno::makeAny(sal_True)); - css::uno::Reference<css::lang::XMultiComponentFactory> xMsf (m_xContext->getServiceManager()); + const css::uno::Reference<css::lang::XMultiComponentFactory> xMsf( + m_xContext->getServiceManager()); m_xUserDefined.set( - xMsf->createInstanceWithContext(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.beans.PropertyBag")), m_xContext), + xMsf->createInstanceWithContext( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.beans.PropertyBag")), m_xContext), css::uno::UNO_QUERY_THROW); - css::uno::Reference<css::lang::XInitialization> xInit(m_xUserDefined, - css::uno::UNO_QUERY); + const css::uno::Reference<css::lang::XInitialization> xInit( + m_xUserDefined, css::uno::UNO_QUERY); if (xInit.is()) { xInit->initialize(args); } - css::uno::Reference<css::util::XModifyBroadcaster> xMB(m_xUserDefined,css::uno::UNO_QUERY); + const css::uno::Reference<css::util::XModifyBroadcaster> xMB( + m_xUserDefined, css::uno::UNO_QUERY); if (xMB.is()) { - css::uno::Sequence< css::uno::Reference< css::uno::XInterface > > aListener = m_NotifyListeners.getElements(); - const css::uno::Reference< css::uno::XInterface >* pIter = aListener.getConstArray(); - const css::uno::Reference< css::uno::XInterface >* pEnd = pIter + aListener.getLength(); - for(;pIter != pEnd;++pIter ) - xMB->addModifyListener(css::uno::Reference< css::util::XModifyListener >(*pIter,css::uno::UNO_QUERY)); + const css::uno::Sequence<css::uno::Reference<css::uno::XInterface> > + listeners(m_NotifyListeners.getElements()); + for (css::uno::Reference< css::uno::XInterface > const * iter = + ::comphelper::stl_begin(listeners); + iter != ::comphelper::stl_end(listeners); ++iter) { + xMB->addModifyListener( + css::uno::Reference< css::util::XModifyListener >(*iter, + css::uno::UNO_QUERY)); + } } } } |