1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #include "vbadocumentproperties.hxx"
20 #include <cppuhelper/implbase.hxx>
21 #include <sal/log.hxx>
22 #include <com/sun/star/document/XDocumentProperties.hpp>
23 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
24 #include <com/sun/star/beans/NamedValue.hpp>
25 #include <com/sun/star/beans/XPropertyContainer.hpp>
26 #include <ooo/vba/word/WdBuiltInProperty.hpp>
27 #include <ooo/vba/office/MsoDocProperties.hpp>
28 #include <comphelper/diagnose_ex.hxx>
30 #include "wordvbahelper.hxx"
33 #include <unotxdoc.hxx>
36 using namespace ::ooo::vba
;
39 /// @throws lang::IllegalArgumentException
40 static sal_Int8
lcl_toMSOPropType( const uno::Type
& aType
)
42 sal_Int16 msoType
= office::MsoDocProperties::msoPropertyTypeString
;
44 switch ( aType
.getTypeClass() )
46 case uno::TypeClass_BOOLEAN
:
47 msoType
= office::MsoDocProperties::msoPropertyTypeBoolean
;
49 case uno::TypeClass_FLOAT
:
50 msoType
= office::MsoDocProperties::msoPropertyTypeFloat
;
52 case uno::TypeClass_STRUCT
: // Assume date
53 msoType
= office::MsoDocProperties::msoPropertyTypeDate
;
55 case uno::TypeClass_BYTE
:
56 case uno::TypeClass_SHORT
:
57 case uno::TypeClass_LONG
:
58 case uno::TypeClass_HYPER
:
59 msoType
= office::MsoDocProperties::msoPropertyTypeNumber
;
62 throw lang::IllegalArgumentException();
69 class PropertGetSetHelper
72 rtl::Reference
< SwXTextDocument
> m_xModel
;
73 uno::Reference
<document::XDocumentProperties
> m_xDocProps
;
75 explicit PropertGetSetHelper( rtl::Reference
< SwXTextDocument
> xModel
) : m_xModel(std::move( xModel
))
77 m_xDocProps
.set(m_xModel
->getDocumentProperties(), uno::UNO_SET_THROW
);
79 virtual ~PropertGetSetHelper() {}
80 virtual uno::Any
getPropertyValue( const OUString
& rPropName
) = 0;
81 virtual void setPropertyValue( const OUString
& rPropName
, const uno::Any
& aValue
) = 0;
82 uno::Reference
< beans::XPropertySet
> getUserDefinedProperties() {
83 return uno::Reference
<beans::XPropertySet
>(
84 m_xDocProps
->getUserDefinedProperties(), uno::UNO_QUERY_THROW
);
89 class BuiltinPropertyGetSetHelper
: public PropertGetSetHelper
92 explicit BuiltinPropertyGetSetHelper( const rtl::Reference
< SwXTextDocument
>& xModel
) :PropertGetSetHelper( xModel
)
95 virtual uno::Any
getPropertyValue( const OUString
& rPropName
) override
97 if ( rPropName
== "EditingDuration" )
99 sal_Int32
const nSecs
= m_xDocProps
->getEditingDuration();
100 return uno::Any( nSecs
/60 ); // minutes
102 else if ("Title" == rPropName
)
104 return uno::Any(m_xDocProps
->getTitle());
106 else if ("Subject" == rPropName
)
108 return uno::Any(m_xDocProps
->getSubject());
110 else if ("Author" == rPropName
)
112 return uno::Any(m_xDocProps
->getAuthor());
114 else if ("Keywords" == rPropName
)
116 return uno::Any(m_xDocProps
->getKeywords());
118 else if ("Description" == rPropName
)
120 return uno::Any(m_xDocProps
->getDescription());
122 else if ("Template" == rPropName
)
124 return uno::Any(m_xDocProps
->getTemplateName());
126 else if ("ModifiedBy" == rPropName
)
128 return uno::Any(m_xDocProps
->getModifiedBy());
130 else if ("Generator" == rPropName
)
132 return uno::Any(m_xDocProps
->getGenerator());
134 else if ("PrintDate" == rPropName
)
136 return uno::Any(m_xDocProps
->getPrintDate());
138 else if ("CreationDate" == rPropName
)
140 return uno::Any(m_xDocProps
->getCreationDate());
142 else if ("ModifyDate" == rPropName
)
144 return uno::Any(m_xDocProps
->getModificationDate());
146 else if ("AutoloadURL" == rPropName
)
148 return uno::Any(m_xDocProps
->getAutoloadURL());
152 // fall back to user-defined properties
153 return getUserDefinedProperties()->getPropertyValue(rPropName
);
156 virtual void setPropertyValue( const OUString
& rPropName
, const uno::Any
& aValue
) override
158 if ("EditingDuration" == rPropName
)
161 if (aValue
>>= nMins
)
163 m_xDocProps
->setEditingDuration(nMins
* 60); // convert minutes
166 else if ("Title" == rPropName
)
171 m_xDocProps
->setTitle(str
);
174 else if ("Subject" == rPropName
)
179 m_xDocProps
->setSubject(str
);
182 else if ("Author" == rPropName
)
187 m_xDocProps
->setAuthor(str
);
190 else if ("Keywords" == rPropName
)
192 uno::Sequence
<OUString
> keywords
;
193 if (aValue
>>= keywords
)
195 m_xDocProps
->setKeywords(keywords
);
198 else if ("Description" == rPropName
)
203 m_xDocProps
->setDescription(str
);
206 else if ("Template" == rPropName
)
211 m_xDocProps
->setTemplateName(str
);
214 else if ("ModifiedBy" == rPropName
)
219 m_xDocProps
->setModifiedBy(str
);
222 else if ("Generator" == rPropName
)
227 return m_xDocProps
->setGenerator(str
);
230 else if ("PrintDate" == rPropName
)
235 m_xDocProps
->setPrintDate(dt
);
238 else if ("CreationDate" == rPropName
)
243 m_xDocProps
->setCreationDate(dt
);
246 else if ("ModifyDate" == rPropName
)
251 m_xDocProps
->setModificationDate(dt
);
254 else if ("AutoloadURL" == rPropName
)
259 m_xDocProps
->setAutoloadURL(str
);
264 // fall back to user-defined properties
265 getUserDefinedProperties()->setPropertyValue(rPropName
, aValue
);
270 class CustomPropertyGetSetHelper
: public BuiltinPropertyGetSetHelper
273 explicit CustomPropertyGetSetHelper( const rtl::Reference
< SwXTextDocument
>& xModel
) :BuiltinPropertyGetSetHelper( xModel
)
276 virtual uno::Any
getPropertyValue( const OUString
& rPropName
) override
278 return getUserDefinedProperties()->getPropertyValue(rPropName
);
280 virtual void setPropertyValue(
281 const OUString
& rPropName
, const uno::Any
& rValue
) override
283 return getUserDefinedProperties()->setPropertyValue(rPropName
, rValue
);
287 class StatisticPropertyGetSetHelper
: public PropertGetSetHelper
289 SwDocShell
* mpDocShell
;
291 explicit StatisticPropertyGetSetHelper( const rtl::Reference
< SwXTextDocument
>& xModel
) :PropertGetSetHelper( xModel
) , mpDocShell( nullptr )
293 mpDocShell
= m_xModel
->GetDocShell();
295 virtual uno::Any
getPropertyValue( const OUString
& rPropName
) override
299 // Characters, ParagraphCount & WordCount are available from
300 // the model ( and additionally these also update the statics object )
301 return m_xModel
->getPropertyValue( rPropName
);
303 catch (const uno::Exception
&)
305 TOOLS_WARN_EXCEPTION("sw.vba", "");
308 if ( rPropName
== "LineCount" ) // special processing needed
312 if (SwFEShell
* pFEShell
= mpDocShell
->GetFEShell())
313 aReturn
<<= pFEShell
->GetLineCount();
318 uno::Sequence
< beans::NamedValue
> const stats(
319 m_xDocProps
->getDocumentStatistics());
321 auto pStat
= std::find_if(stats
.begin(), stats
.end(),
322 [&rPropName
](const beans::NamedValue
& rStat
) { return rPropName
== rStat
.Name
; });
323 if (pStat
== stats
.end())
324 throw uno::RuntimeException(); // bad Property
326 aReturn
= pStat
->Value
;
331 virtual void setPropertyValue( const OUString
& rPropName
, const uno::Any
& aValue
) override
333 uno::Sequence
< beans::NamedValue
> stats(
334 m_xDocProps
->getDocumentStatistics());
336 auto [begin
, end
] = asNonConstRange(stats
);
337 auto pStat
= std::find_if(begin
, end
,
338 [&rPropName
](const beans::NamedValue
& rStat
) { return rPropName
== rStat
.Name
; });
341 pStat
->Value
= aValue
;
342 m_xDocProps
->setDocumentStatistics(stats
);
351 OUString msOOOPropName
;
352 std::shared_ptr
< PropertGetSetHelper
> mpPropGetSetHelper
;
354 static DocPropInfo
createDocPropInfo( const OUString
& sDesc
, const OUString
& sPropName
, std::shared_ptr
< PropertGetSetHelper
> const & rHelper
)
357 aItem
.msMSODesc
= sDesc
;
358 aItem
.msOOOPropName
= sPropName
;
359 aItem
.mpPropGetSetHelper
= rHelper
;
363 static DocPropInfo
createDocPropInfo( const char* sDesc
, const char* sPropName
, std::shared_ptr
< PropertGetSetHelper
> const & rHelper
)
365 return createDocPropInfo( OUString::createFromAscii( sDesc
), OUString::createFromAscii( sPropName
), rHelper
);
369 if ( mpPropGetSetHelper
)
370 return mpPropGetSetHelper
->getPropertyValue( msOOOPropName
);
373 void setValue( const uno::Any
& rValue
)
375 if ( mpPropGetSetHelper
)
376 mpPropGetSetHelper
->setPropertyValue( msOOOPropName
, rValue
);
378 uno::Reference
< beans::XPropertySet
> getUserDefinedProperties()
380 uno::Reference
< beans::XPropertySet
> xProps
;
381 if ( mpPropGetSetHelper
)
382 return mpPropGetSetHelper
->getUserDefinedProperties();
389 typedef std::unordered_map
< sal_Int32
, DocPropInfo
> MSOIndexToOODocPropInfo
;
393 class BuiltInIndexHelper
395 MSOIndexToOODocPropInfo m_docPropInfoMap
;
398 explicit BuiltInIndexHelper( const rtl::Reference
< SwXTextDocument
>& xModel
)
400 auto aStandardHelper
= std::make_shared
<BuiltinPropertyGetSetHelper
>( xModel
);
401 auto aUsingStatsHelper
= std::make_shared
<StatisticPropertyGetSetHelper
>( xModel
);
403 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyTitle
] = DocPropInfo::createDocPropInfo( "Title", "Title", aStandardHelper
);
404 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertySubject
] = DocPropInfo::createDocPropInfo( "Subject", "Subject", aStandardHelper
);
405 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyAuthor
] = DocPropInfo::createDocPropInfo( "Author", "Author", aStandardHelper
);
406 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyKeywords
] = DocPropInfo::createDocPropInfo( "Keywords", "Keywords", aStandardHelper
);
407 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyComments
] = DocPropInfo::createDocPropInfo( "Comments", "Description", aStandardHelper
);
408 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyTemplate
] = DocPropInfo::createDocPropInfo( "Template", "Template", aStandardHelper
);
409 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyLastAuthor
] = DocPropInfo::createDocPropInfo( "Last author", "ModifiedBy", aStandardHelper
); // doesn't seem to exist - throw or return nothing ?
410 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyRevision
] = DocPropInfo::createDocPropInfo( "Revision number", "EditingCycles", aStandardHelper
); // doesn't seem to exist - throw or return nothing ?
411 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyAppName
] = DocPropInfo::createDocPropInfo( "Application name", "Generator", aStandardHelper
); // doesn't seem to exist - throw or return nothing ?
412 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyTimeLastPrinted
] = DocPropInfo::createDocPropInfo( "Last print date", "PrintDate", aStandardHelper
); // doesn't seem to exist - throw or return nothing ?
413 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyTimeCreated
] = DocPropInfo::createDocPropInfo( "Creation date", "CreationDate", aStandardHelper
);
414 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyTimeLastSaved
] = DocPropInfo::createDocPropInfo( "Last save time", "ModifyDate", aStandardHelper
);
415 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyVBATotalEdit
] = DocPropInfo::createDocPropInfo( "Total editing time", "EditingDuration", aStandardHelper
); // Not sure if this is correct
416 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyPages
] = DocPropInfo::createDocPropInfo( "Number of pages", "PageCount", aUsingStatsHelper
); // special handling required ?
417 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyWords
] = DocPropInfo::createDocPropInfo( "Number of words", "WordCount", aUsingStatsHelper
); // special handling require ?
418 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyCharacters
] = DocPropInfo::createDocPropInfo( "Number of characters", "CharacterCount", aUsingStatsHelper
); // special handling required ?
419 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertySecurity
] = DocPropInfo::createDocPropInfo( "Security", "", aStandardHelper
); // doesn't seem to exist
420 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyCategory
] = DocPropInfo::createDocPropInfo( "Category", "Category", aStandardHelper
); // hacked in
421 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyFormat
] = DocPropInfo::createDocPropInfo( "Format", "", aStandardHelper
); // doesn't seem to exist
422 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyManager
] = DocPropInfo::createDocPropInfo( "Manager", "Manager", aStandardHelper
); // hacked in
423 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyCompany
] = DocPropInfo::createDocPropInfo( "Company", "Company", aStandardHelper
); // hacked in
424 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyBytes
] = DocPropInfo::createDocPropInfo( "Number of bytes", "", aStandardHelper
); // doesn't seem to exist - size on disk exists ( for an already saved document ) perhaps it will do ( or we need something else )
425 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyLines
] = DocPropInfo::createDocPropInfo( "Number of lines", "LineCount", aUsingStatsHelper
); // special handling
426 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyParas
] = DocPropInfo::createDocPropInfo( "Number of paragraphs", "ParagraphCount", aUsingStatsHelper
); // special handling
427 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertySlides
] = DocPropInfo::createDocPropInfo( "Number of slides", "" , aStandardHelper
); // doesn't seem to exist
428 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyNotes
] = DocPropInfo::createDocPropInfo( "Number of notes", "", aStandardHelper
); // doesn't seem to exist
429 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyHiddenSlides
] = DocPropInfo::createDocPropInfo("Number of hidden Slides", "", aStandardHelper
); // doesn't seem to exist
430 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyMMClips
] = DocPropInfo::createDocPropInfo( "Number of multimedia clips", "", aStandardHelper
); // doesn't seem to exist
431 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyHyperlinkBase
] = DocPropInfo::createDocPropInfo( "Hyperlink base", "AutoloadURL", aStandardHelper
);
432 m_docPropInfoMap
[ word::WdBuiltInProperty::wdPropertyCharsWSpaces
] = DocPropInfo::createDocPropInfo( "Number of characters (with spaces)", "", aStandardHelper
); // doesn't seem to be supported
435 MSOIndexToOODocPropInfo
& getDocPropInfoMap() { return m_docPropInfoMap
; }
440 typedef InheritedHelperInterfaceWeakImpl
< ooo::vba::XDocumentProperty
> SwVbaDocumentProperty_BASE
;
444 class SwVbaBuiltInDocumentProperty
: public SwVbaDocumentProperty_BASE
447 DocPropInfo mPropInfo
;
449 SwVbaBuiltInDocumentProperty( const uno::Reference
< ov::XHelperInterface
>& xParent
, const uno::Reference
< uno::XComponentContext
>& xContext
, DocPropInfo rInfo
);
451 virtual void SAL_CALL
Delete( ) override
;
452 virtual OUString SAL_CALL
getName( ) override
;
453 virtual void SAL_CALL
setName( const OUString
& Name
) override
;
454 virtual ::sal_Int8 SAL_CALL
getType( ) override
;
455 virtual void SAL_CALL
setType( ::sal_Int8 Type
) override
;
456 virtual sal_Bool SAL_CALL
getLinkToContent( ) override
;
457 virtual void SAL_CALL
setLinkToContent( sal_Bool LinkToContent
) override
;
458 virtual uno::Any SAL_CALL
getValue( ) override
;
459 virtual void SAL_CALL
setValue( const uno::Any
& Value
) override
;
460 virtual OUString SAL_CALL
getLinkSource( ) override
;
461 virtual void SAL_CALL
setLinkSource( const OUString
& LinkSource
) override
;
463 virtual OUString SAL_CALL
getDefaultPropertyName( ) override
{ return u
"Value"_ustr
; }
465 virtual OUString
getServiceImplName() override
;
466 virtual uno::Sequence
<OUString
> getServiceNames() override
;
469 class SwVbaCustomDocumentProperty
: public SwVbaBuiltInDocumentProperty
473 SwVbaCustomDocumentProperty( const uno::Reference
< ov::XHelperInterface
>& xParent
, const uno::Reference
< uno::XComponentContext
>& xContext
, const DocPropInfo
& rInfo
);
475 virtual sal_Bool SAL_CALL
getLinkToContent( ) override
;
476 virtual void SAL_CALL
setLinkToContent( sal_Bool LinkToContent
) override
;
478 virtual OUString SAL_CALL
getLinkSource( ) override
;
479 virtual void SAL_CALL
setLinkSource( const OUString
& LinkSource
) override
;
480 virtual void SAL_CALL
Delete( ) override
;
481 virtual void SAL_CALL
setName( const OUString
& Name
) override
;
482 virtual void SAL_CALL
setType( ::sal_Int8 Type
) override
;
488 SwVbaCustomDocumentProperty::SwVbaCustomDocumentProperty( const uno::Reference
< ov::XHelperInterface
>& xParent
, const uno::Reference
< uno::XComponentContext
>& xContext
, const DocPropInfo
& rInfo
) : SwVbaBuiltInDocumentProperty( xParent
, xContext
, rInfo
)
493 SwVbaCustomDocumentProperty::getLinkToContent( )
495 // #FIXME we need to store the link content somewhere
500 SwVbaCustomDocumentProperty::setLinkToContent( sal_Bool
/*bLinkContent*/ )
505 SwVbaCustomDocumentProperty::getLinkSource( )
507 // #FIXME we need to store the link content somewhere
512 SwVbaCustomDocumentProperty::setLinkSource( const OUString
& /*rsLinkContent*/ )
514 // #FIXME we need to store the link source somewhere
518 SwVbaCustomDocumentProperty::setName( const OUString
& /*Name*/ )
520 // setName on existing property ?
522 // do we need to delete existing property and create a new one?
526 SwVbaCustomDocumentProperty::setType( ::sal_Int8
/*Type*/ )
528 // setType, do we need to do a conversion?
529 // #FIXME the underlying value needs to be changed to the new type
533 SwVbaCustomDocumentProperty::Delete( )
535 uno::Reference
< beans::XPropertyContainer
> xContainer(
536 mPropInfo
.getUserDefinedProperties(), uno::UNO_QUERY_THROW
);
537 xContainer
->removeProperty( getName() );
540 SwVbaBuiltInDocumentProperty::SwVbaBuiltInDocumentProperty( const uno::Reference
< ov::XHelperInterface
>& xParent
, const uno::Reference
< uno::XComponentContext
>& xContext
, DocPropInfo rInfo
) : SwVbaDocumentProperty_BASE( xParent
, xContext
), mPropInfo(std::move( rInfo
))
545 SwVbaBuiltInDocumentProperty::Delete( )
547 // not valid for Builtin
548 throw uno::RuntimeException();
552 SwVbaBuiltInDocumentProperty::getName( )
554 return mPropInfo
.msMSODesc
;
558 SwVbaBuiltInDocumentProperty::setName( const OUString
& )
560 // not valid for Builtin
561 throw uno::RuntimeException();
565 SwVbaBuiltInDocumentProperty::getType( )
567 return lcl_toMSOPropType( getValue().getValueType() );
571 SwVbaBuiltInDocumentProperty::setType( ::sal_Int8
/*Type*/ )
573 // not valid for Builtin
574 throw uno::RuntimeException();
578 SwVbaBuiltInDocumentProperty::getLinkToContent( )
580 return false; // built-in always false
584 SwVbaBuiltInDocumentProperty::setLinkToContent( sal_Bool
/*LinkToContent*/ )
586 // not valid for Builtin
587 throw uno::RuntimeException();
591 SwVbaBuiltInDocumentProperty::getValue( )
593 uno::Any aRet
= mPropInfo
.getValue();
594 if ( !aRet
.hasValue() )
595 throw uno::RuntimeException();
600 SwVbaBuiltInDocumentProperty::setValue( const uno::Any
& Value
)
602 mPropInfo
.setValue( Value
);
606 SwVbaBuiltInDocumentProperty::getLinkSource( )
608 // not valid for Builtin
609 throw uno::RuntimeException();
613 SwVbaBuiltInDocumentProperty::setLinkSource( const OUString
& /*LinkSource*/ )
615 // not valid for Builtin
616 throw uno::RuntimeException();
620 SwVbaBuiltInDocumentProperty::getServiceImplName()
622 return u
"SwVbaBuiltinDocumentProperty"_ustr
;
625 uno::Sequence
<OUString
>
626 SwVbaBuiltInDocumentProperty::getServiceNames()
628 static uno::Sequence
< OUString
> const aServiceNames
630 u
"ooo.vba.word.DocumentProperty"_ustr
632 return aServiceNames
;
634 typedef ::cppu::WeakImplHelper
< css::container::XIndexAccess
635 ,css::container::XNameAccess
636 ,css::container::XEnumerationAccess
637 > PropertiesImpl_BASE
;
639 typedef std::unordered_map
< sal_Int32
, uno::Reference
< XDocumentProperty
> > DocProps
;
643 class DocPropEnumeration
: public ::cppu::WeakImplHelper
< css::container::XEnumeration
>
646 DocProps::iterator mIt
;
649 explicit DocPropEnumeration( DocProps
&& rProps
) : mDocProps( std::move(rProps
) ), mIt( mDocProps
.begin() ) {}
650 virtual sal_Bool SAL_CALL
hasMoreElements( ) override
652 return mIt
!= mDocProps
.end();
654 virtual uno::Any SAL_CALL
nextElement( ) override
656 if ( !hasMoreElements() )
657 throw container::NoSuchElementException();
658 return uno::Any( mIt
++->second
);
664 typedef std::unordered_map
< OUString
, uno::Reference
< XDocumentProperty
> > DocPropsByName
;
668 class BuiltInPropertiesImpl
: public PropertiesImpl_BASE
672 rtl::Reference
< SwXTextDocument
> m_xModel
;
675 DocPropsByName mNamedDocProps
;
678 BuiltInPropertiesImpl( const uno::Reference
< XHelperInterface
>& xParent
, const uno::Reference
< uno::XComponentContext
>& xContext
, rtl::Reference
< SwXTextDocument
> xModel
) : m_xModel(std::move( xModel
))
680 BuiltInIndexHelper
builtIns( m_xModel
);
681 for ( sal_Int32 index
= word::WdBuiltInProperty::wdPropertyTitle
; index
<= word::WdBuiltInProperty::wdPropertyCharsWSpaces
; ++index
)
683 mDocProps
[ index
] = new SwVbaBuiltInDocumentProperty( xParent
, xContext
, builtIns
.getDocPropInfoMap()[ index
] );
684 mNamedDocProps
[ mDocProps
[ index
]->getName() ] = mDocProps
[ index
];
688 virtual ::sal_Int32 SAL_CALL
getCount( ) override
690 return mDocProps
.size();
692 virtual uno::Any SAL_CALL
getByIndex( ::sal_Int32 Index
) override
694 // correct the correct by the base class for 1 based indices
695 DocProps::iterator it
= mDocProps
.find( ++Index
);
696 if ( it
== mDocProps
.end() )
697 throw lang::IndexOutOfBoundsException();
698 return uno::Any( it
->second
);
700 virtual uno::Any SAL_CALL
getByName( const OUString
& aName
) override
702 if ( !hasByName( aName
) )
703 throw container::NoSuchElementException();
704 DocPropsByName::iterator it
= mNamedDocProps
.find( aName
);
705 return uno::Any( it
->second
);
708 virtual uno::Sequence
< OUString
> SAL_CALL
getElementNames( ) override
710 uno::Sequence
< OUString
> aNames( getCount() );
711 OUString
* pName
= aNames
.getArray();
712 for (const auto& rEntry
: mNamedDocProps
)
714 *pName
= rEntry
.first
;
720 virtual sal_Bool SAL_CALL
hasByName( const OUString
& aName
) override
722 DocPropsByName::iterator it
= mNamedDocProps
.find( aName
);
723 if ( it
== mNamedDocProps
.end() )
728 virtual uno::Type SAL_CALL
getElementType( ) override
730 return cppu::UnoType
<XDocumentProperty
>::get();
732 virtual sal_Bool SAL_CALL
hasElements( ) override
734 return !mDocProps
.empty();
736 virtual uno::Reference
< container::XEnumeration
> SAL_CALL
createEnumeration( ) override
738 return new DocPropEnumeration( std::unordered_map(mDocProps
) );
744 SwVbaBuiltinDocumentProperties::SwVbaBuiltinDocumentProperties(
745 const uno::Reference
< XHelperInterface
>& xParent
,
746 const uno::Reference
< uno::XComponentContext
>& xContext
,
747 const rtl::Reference
< SwXTextDocument
>& xModel
)
748 : SwVbaDocumentproperties_BASE( xParent
, xContext
, uno::Reference
< container::XIndexAccess
>( new BuiltInPropertiesImpl( xParent
, xContext
, xModel
) ) )
752 uno::Reference
< XDocumentProperty
> SAL_CALL
753 SwVbaBuiltinDocumentProperties::Add( const OUString
& /*Name*/, sal_Bool
/*LinkToContent*/, ::sal_Int8
/*Type*/, const uno::Any
& /*value*/, const uno::Any
& /*LinkSource*/ )
755 throw uno::RuntimeException( u
"not supported for Builtin properties"_ustr
);
758 // XEnumerationAccess
760 SwVbaBuiltinDocumentProperties::getElementType()
762 return cppu::UnoType
<XDocumentProperty
>::get();
765 uno::Reference
< container::XEnumeration
> SAL_CALL
766 SwVbaBuiltinDocumentProperties::createEnumeration()
768 uno::Reference
< container::XEnumerationAccess
> xEnumAccess( m_xIndexAccess
, uno::UNO_QUERY_THROW
);
769 return xEnumAccess
->createEnumeration();
772 // ScVbaCollectionBaseImpl
774 SwVbaBuiltinDocumentProperties::createCollectionObject( const uno::Any
& aSource
)
782 SwVbaBuiltinDocumentProperties::getServiceImplName()
784 return u
"SwVbaBuiltinDocumentProperties"_ustr
;
787 uno::Sequence
<OUString
>
788 SwVbaBuiltinDocumentProperties::getServiceNames()
790 static uno::Sequence
< OUString
> const aServiceNames
792 u
"ooo.vba.word.DocumentProperties"_ustr
794 return aServiceNames
;
799 class CustomPropertiesImpl
: public PropertiesImpl_BASE
801 uno::Reference
< XHelperInterface
> m_xParent
;
802 uno::Reference
< uno::XComponentContext
> m_xContext
;
803 rtl::Reference
< SwXTextDocument
> m_xModel
;
804 uno::Reference
< beans::XPropertySet
> mxUserDefinedProp
;
805 std::shared_ptr
< PropertGetSetHelper
> mpPropGetSetHelper
;
807 CustomPropertiesImpl( uno::Reference
< XHelperInterface
> xParent
,
808 uno::Reference
< uno::XComponentContext
> xContext
,
809 rtl::Reference
< SwXTextDocument
> xModel
)
810 : m_xParent(std::move( xParent
)),
811 m_xContext(std::move( xContext
)),
812 m_xModel(std::move( xModel
))
814 // suck in the document( custom ) properties
815 mpPropGetSetHelper
= std::make_shared
<CustomPropertyGetSetHelper
>( m_xModel
);
816 mxUserDefinedProp
.set(mpPropGetSetHelper
->getUserDefinedProperties(),
820 virtual ::sal_Int32 SAL_CALL
getCount( ) override
822 return mxUserDefinedProp
->getPropertySetInfo()->getProperties().getLength();
825 virtual uno::Any SAL_CALL
getByIndex( ::sal_Int32 Index
) override
827 uno::Sequence
< beans::Property
> aProps
= mxUserDefinedProp
->getPropertySetInfo()->getProperties();
828 if ( Index
>= aProps
.getLength() )
829 throw lang::IndexOutOfBoundsException();
830 // How to determine type e.g Date? ( com.sun.star.util.DateTime )
831 DocPropInfo aPropInfo
= DocPropInfo::createDocPropInfo( aProps
[ Index
].Name
, aProps
[ Index
].Name
, mpPropGetSetHelper
);
832 return uno::Any( uno::Reference
< XDocumentProperty
>( new SwVbaCustomDocumentProperty( m_xParent
, m_xContext
, aPropInfo
) ) );
835 virtual uno::Any SAL_CALL
getByName( const OUString
& aName
) override
837 if ( !hasByName( aName
) )
838 throw container::NoSuchElementException();
840 DocPropInfo aPropInfo
= DocPropInfo::createDocPropInfo( aName
, aName
, mpPropGetSetHelper
);
841 return uno::Any( uno::Reference
< XDocumentProperty
>( new SwVbaCustomDocumentProperty( m_xParent
, m_xContext
, aPropInfo
) ) );
844 virtual uno::Sequence
< OUString
> SAL_CALL
getElementNames( ) override
846 const uno::Sequence
< beans::Property
> aProps
= mxUserDefinedProp
->getPropertySetInfo()->getProperties();
847 uno::Sequence
< OUString
> aNames( aProps
.getLength() );
848 std::transform(aProps
.begin(), aProps
.end(), aNames
.getArray(),
849 [](const beans::Property
& rProp
) -> OUString
{ return rProp
.Name
; });
853 virtual sal_Bool SAL_CALL
hasByName( const OUString
& aName
) override
855 SAL_INFO("sw.vba", "hasByName(" << aName
<< ") returns " << mxUserDefinedProp
->getPropertySetInfo()->hasPropertyByName( aName
) );
856 return mxUserDefinedProp
->getPropertySetInfo()->hasPropertyByName( aName
);
860 virtual uno::Type SAL_CALL
getElementType( ) override
862 return cppu::UnoType
<XDocumentProperty
>::get();
865 virtual sal_Bool SAL_CALL
hasElements( ) override
867 return getCount() > 0;
870 virtual uno::Reference
< container::XEnumeration
> SAL_CALL
createEnumeration( ) override
872 // create a map of properties ( the key doesn't matter )
873 SAL_INFO("sw.vba", "Creating an enumeration");
875 sal_Int32 nElem
= getCount();
876 DocProps simpleDocPropSnapShot
;
877 for ( ; key
< nElem
; ++key
)
878 simpleDocPropSnapShot
[ key
].set( getByIndex( key
), uno::UNO_QUERY_THROW
);
879 SAL_INFO("sw.vba", "After creating the enumeration");
880 return new DocPropEnumeration( std::move(simpleDocPropSnapShot
) );
883 void addProp( const OUString
& Name
, const uno::Any
& Value
)
885 uno::Reference
< beans::XPropertyContainer
> xContainer( mxUserDefinedProp
, uno::UNO_QUERY_THROW
);
886 // TODO fixme, perform the necessary Type Value conversions
887 xContainer
->addProperty( Name
, sal_Int16(128), Value
);
894 SwVbaCustomDocumentProperties::SwVbaCustomDocumentProperties( const uno::Reference
< XHelperInterface
>& xParent
, const uno::Reference
< uno::XComponentContext
>& xContext
, const rtl::Reference
< SwXTextDocument
>& xModel
) : SwVbaBuiltinDocumentProperties( xParent
, xContext
, xModel
)
896 // replace the m_xIndexAccess implementation ( we need a virtual init )
897 m_xIndexAccess
.set( new CustomPropertiesImpl( xParent
, xContext
, xModel
) );
898 m_xNameAccess
.set( m_xIndexAccess
, uno::UNO_QUERY_THROW
);
901 uno::Reference
< XDocumentProperty
> SAL_CALL
902 SwVbaCustomDocumentProperties::Add( const OUString
& Name
, sal_Bool LinkToContent
, ::sal_Int8
/*Type*/, const uno::Any
& Value
, const uno::Any
& LinkSource
)
904 CustomPropertiesImpl
* pCustomProps
= dynamic_cast< CustomPropertiesImpl
* > ( m_xIndexAccess
.get() );
905 uno::Reference
< XDocumentProperty
> xDocProp
;
908 OUString sLinkSource
;
909 pCustomProps
->addProp( Name
, Value
);
911 xDocProp
.set( m_xNameAccess
->getByName( Name
), uno::UNO_QUERY_THROW
);
912 xDocProp
->setLinkToContent( LinkToContent
);
914 if ( LinkSource
>>= sLinkSource
)
915 xDocProp
->setLinkSource( sLinkSource
);
922 SwVbaCustomDocumentProperties::getServiceImplName()
924 return u
"SwVbaCustomDocumentProperties"_ustr
;
927 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */