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 .
20 #include <svl/eitem.hxx>
21 #include <tools/datetime.hxx>
22 #include <tools/duration.hxx>
23 #include <tools/debug.hxx>
24 #include <tools/urlobj.hxx>
26 #include <vcl/svapp.hxx>
27 #include <vcl/weld.hxx>
28 #include <vcl/weldutils.hxx>
29 #include <unotools/datetime.hxx>
30 #include <unotools/localedatawrapper.hxx>
31 #include <unotools/cmdoptions.hxx>
32 #include <comphelper/processfactory.hxx>
33 #include <comphelper/propertyvalue.hxx>
34 #include <comphelper/stl_types.hxx>
35 #include <comphelper/xmlsechelper.hxx>
36 #include <unotools/useroptions.hxx>
37 #include <svtools/ctrlbox.hxx>
38 #include <svtools/imagemgr.hxx>
39 #include <sal/log.hxx>
40 #include <osl/diagnose.h>
41 #include <osl/file.hxx>
42 #include <comphelper/lok.hxx>
43 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
44 #include <tools/json_writer.hxx>
48 #include <comphelper/sequence.hxx>
49 #include <comphelper/string.hxx>
50 #include <com/sun/star/security/DocumentSignatureInformation.hpp>
51 #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
52 #include <unotools/syslocale.hxx>
53 #include <rtl/math.hxx>
54 #include <com/sun/star/beans/PropertyAttribute.hpp>
55 #include <com/sun/star/beans/XPropertyContainer.hpp>
56 #include <com/sun/star/beans/XPropertySet.hpp>
57 #include <com/sun/star/util/DateTime.hpp>
58 #include <com/sun/star/util/Date.hpp>
59 #include <com/sun/star/util/DateTimeWithTimezone.hpp>
60 #include <com/sun/star/util/DateWithTimezone.hpp>
61 #include <com/sun/star/util/Duration.hpp>
62 #include <com/sun/star/document/XDocumentProperties2.hpp>
63 #include <com/sun/star/document/CmisProperty.hpp>
64 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
66 #include <vcl/timer.hxx>
67 #include <vcl/settings.hxx>
68 #include <sfx2/sfxresid.hxx>
69 #include <sfx2/frame.hxx>
70 #include <sfx2/filedlghelper.hxx>
71 #include <sfx2/dinfdlg.hxx>
72 #include <sfx2/sfxsids.hrc>
74 #include <sfx2/objsh.hxx>
75 #include <sfx2/docfile.hxx>
76 #include <vcl/abstdlg.hxx>
77 #include <sfx2/viewsh.hxx>
79 #include <documentfontsdialog.hxx>
80 #include <dinfdlg.hrc>
81 #include <sfx2/strings.hrc>
82 #include <strings.hxx>
83 #include <comphelper/diagnose_ex.hxx>
84 #include "securitypage.hxx"
88 using namespace ::com::sun::star
;
89 using namespace ::com::sun::star::uno
;
94 css::uno::Any m_aValue
;
96 CustomProperty( OUString sName
, css::uno::Any aValue
) :
97 m_sName(std::move( sName
)), m_aValue(std::move( aValue
)) {}
99 bool operator==(const CustomProperty
& rProp
) const
101 return m_sName
== rProp
.m_sName
&& m_aValue
== rProp
.m_aValue
;
105 SfxPoolItem
* SfxDocumentInfoItem::CreateDefault() { return new SfxDocumentInfoItem
; }
109 OUString
CreateSizeText( sal_Int64 nSize
)
111 OUString aUnitStr
= " " + SfxResId(STR_BYTES
);
112 sal_Int64 nSize1
= nSize
;
113 sal_Int64 nSize2
= nSize1
;
114 sal_Int64 nMega
= 1024 * 1024;
115 sal_Int64 nGiga
= nMega
* 1024;
116 double fSize
= nSize
;
119 if ( nSize1
>= 10000 && nSize1
< nMega
)
122 aUnitStr
= " " + SfxResId(STR_KB
);
126 else if ( nSize1
>= nMega
&& nSize1
< nGiga
)
129 aUnitStr
= " " + SfxResId(STR_MB
);
133 else if ( nSize1
>= nGiga
)
136 aUnitStr
= " " + SfxResId(STR_GB
);
140 const SvtSysLocale aSysLocale
;
141 const LocaleDataWrapper
& rLocaleWrapper
= aSysLocale
.GetLocaleData();
142 OUString aSizeStr
= rLocaleWrapper
.getNum( nSize1
, 0 ) + aUnitStr
;
143 if ( nSize1
< nSize2
)
145 aSizeStr
= ::rtl::math::doubleToUString( fSize
,
146 rtl_math_StringFormat_F
, nDec
,
147 rLocaleWrapper
.getNumDecimalSep()[0] )
150 + rLocaleWrapper
.getNum( nSize2
, 0 )
152 + SfxResId(STR_BYTES
)
158 OUString
ConvertDateTime_Impl( std::u16string_view rName
,
159 const util::DateTime
& uDT
, const LocaleDataWrapper
& rWrapper
)
163 static constexpr OUString
aDelim( u
", "_ustr
);
164 OUString aStr
= rWrapper
.getDate( aD
)
166 + rWrapper
.getTime( aT
);
167 std::u16string_view aAuthor
= comphelper::string::stripStart(rName
, ' ');
168 if (!aAuthor
.empty())
170 aStr
+= aDelim
+ aAuthor
;
178 SfxDocumentInfoItem::SfxDocumentInfoItem()
180 , m_isAutoloadEnabled(false)
182 , m_EditingDuration(0)
184 , m_bHasTemplate( true )
185 , m_bDeleteUserData( false )
186 , m_bUseUserData( true )
187 , m_bUseThumbnailSave( true )
191 SfxDocumentInfoItem::SfxDocumentInfoItem( const OUString
& rFile
,
192 const uno::Reference
<document::XDocumentProperties
>& i_xDocProps
,
193 const uno::Sequence
<document::CmisProperty
>& i_cmisProps
,
194 bool bIs
, bool _bIs
, sal_Int64 _nFileSize
)
195 : SfxStringItem( SID_DOCINFO
, rFile
, SfxItemType::SfxDocumentInfoItemType
)
196 , m_AutoloadDelay( i_xDocProps
->getAutoloadSecs() )
197 , m_AutoloadURL( i_xDocProps
->getAutoloadURL() )
198 , m_isAutoloadEnabled( (m_AutoloadDelay
> 0) || !m_AutoloadURL
.isEmpty() )
199 , m_DefaultTarget( i_xDocProps
->getDefaultTarget() )
200 , m_TemplateName( i_xDocProps
->getTemplateName() )
201 , m_Author( i_xDocProps
->getAuthor() )
202 , m_CreationDate( i_xDocProps
->getCreationDate() )
203 , m_ModifiedBy( i_xDocProps
->getModifiedBy() )
204 , m_ModificationDate( i_xDocProps
->getModificationDate() )
205 , m_PrintedBy( i_xDocProps
->getPrintedBy() )
206 , m_PrintDate( i_xDocProps
->getPrintDate() )
207 , m_EditingCycles( i_xDocProps
->getEditingCycles() )
208 , m_EditingDuration( i_xDocProps
->getEditingDuration() )
209 , m_Description( i_xDocProps
->getDescription() )
210 , m_Keywords( ::comphelper::string::convertCommaSeparated(
211 i_xDocProps
->getKeywords()) )
212 , m_Subject( i_xDocProps
->getSubject() )
213 , m_Title( i_xDocProps
->getTitle() )
214 , m_nFileSize( _nFileSize
)
215 , m_bHasTemplate( true )
216 , m_bDeleteUserData( false )
217 , m_bUseUserData( bIs
)
218 , m_bUseThumbnailSave( _bIs
)
220 Reference
< document::XDocumentProperties2
> xDocProps2(i_xDocProps
, UNO_QUERY
);
221 m_Contributor
= ::comphelper::string::convertCommaSeparated(xDocProps2
->getContributor());
222 m_Coverage
= xDocProps2
->getCoverage();
223 m_Identifier
= xDocProps2
->getIdentifier();
224 m_Publisher
= ::comphelper::string::convertCommaSeparated(xDocProps2
->getPublisher());
225 m_Relation
= ::comphelper::string::convertCommaSeparated(xDocProps2
->getRelation());
226 m_Rights
= xDocProps2
->getRights();
227 m_Source
= xDocProps2
->getSource();
228 m_Type
= xDocProps2
->getType();
232 Reference
< beans::XPropertyContainer
> xContainer
= i_xDocProps
->getUserDefinedProperties();
233 if ( xContainer
.is() )
235 Reference
< beans::XPropertySet
> xSet( xContainer
, UNO_QUERY
);
236 const Sequence
< beans::Property
> lProps
= xSet
->getPropertySetInfo()->getProperties();
237 for ( const beans::Property
& rProp
: lProps
)
239 // "fix" property? => not a custom property => ignore it!
240 if (!(rProp
.Attributes
& css::beans::PropertyAttribute::REMOVABLE
))
242 SAL_WARN( "sfx.dialog", "non-removable user-defined property?");
246 uno::Any aValue
= xSet
->getPropertyValue(rProp
.Name
);
247 AddCustomProperty( rProp
.Name
, aValue
);
251 // get CMIS properties
252 m_aCmisProperties
= i_cmisProps
;
254 catch ( Exception
& ) {}
258 SfxDocumentInfoItem::SfxDocumentInfoItem( const SfxDocumentInfoItem
& rItem
)
259 : SfxStringItem( rItem
)
260 , m_AutoloadDelay( rItem
.getAutoloadDelay() )
261 , m_AutoloadURL( rItem
.getAutoloadURL() )
262 , m_isAutoloadEnabled( rItem
.isAutoloadEnabled() )
263 , m_DefaultTarget( rItem
.getDefaultTarget() )
264 , m_TemplateName( rItem
.getTemplateName() )
265 , m_Author( rItem
.getAuthor() )
266 , m_CreationDate( rItem
.getCreationDate() )
267 , m_ModifiedBy( rItem
.getModifiedBy() )
268 , m_ModificationDate( rItem
.getModificationDate() )
269 , m_PrintedBy( rItem
.getPrintedBy() )
270 , m_PrintDate( rItem
.getPrintDate() )
271 , m_EditingCycles( rItem
.getEditingCycles() )
272 , m_EditingDuration( rItem
.getEditingDuration() )
273 , m_Description( rItem
.getDescription() )
274 , m_Keywords( rItem
.getKeywords() )
275 , m_Contributor(rItem
.getContributor())
276 , m_Coverage(rItem
.getCoverage())
277 , m_Identifier(rItem
.getIdentifier())
278 , m_Publisher(rItem
.getPublisher())
279 , m_Relation(rItem
.getRelation())
280 , m_Rights(rItem
.getRights())
281 , m_Source(rItem
.getSource())
282 , m_Type(rItem
.getType())
283 , m_Subject( rItem
.getSubject() )
284 , m_Title( rItem
.getTitle() )
285 , m_nFileSize ( rItem
.m_nFileSize
)
286 , m_bHasTemplate( rItem
.m_bHasTemplate
)
287 , m_bDeleteUserData( rItem
.m_bDeleteUserData
)
288 , m_bUseUserData( rItem
.m_bUseUserData
)
289 , m_bUseThumbnailSave( rItem
.m_bUseThumbnailSave
)
291 for (auto const & pOtherProp
: rItem
.m_aCustomProperties
)
293 AddCustomProperty( pOtherProp
->m_sName
, pOtherProp
->m_aValue
);
296 m_aCmisProperties
= rItem
.m_aCmisProperties
;
299 SfxDocumentInfoItem::~SfxDocumentInfoItem()
301 ClearCustomProperties();
304 SfxDocumentInfoItem
* SfxDocumentInfoItem::Clone( SfxItemPool
* ) const
306 return new SfxDocumentInfoItem( *this );
309 bool SfxDocumentInfoItem::operator==( const SfxPoolItem
& rItem
) const
311 if (!SfxStringItem::operator==(rItem
))
313 const SfxDocumentInfoItem
& rInfoItem(static_cast<const SfxDocumentInfoItem
&>(rItem
));
316 m_AutoloadDelay
== rInfoItem
.m_AutoloadDelay
&&
317 m_AutoloadURL
== rInfoItem
.m_AutoloadURL
&&
318 m_isAutoloadEnabled
== rInfoItem
.m_isAutoloadEnabled
&&
319 m_DefaultTarget
== rInfoItem
.m_DefaultTarget
&&
320 m_Author
== rInfoItem
.m_Author
&&
321 m_CreationDate
== rInfoItem
.m_CreationDate
&&
322 m_ModifiedBy
== rInfoItem
.m_ModifiedBy
&&
323 m_ModificationDate
== rInfoItem
.m_ModificationDate
&&
324 m_PrintedBy
== rInfoItem
.m_PrintedBy
&&
325 m_PrintDate
== rInfoItem
.m_PrintDate
&&
326 m_EditingCycles
== rInfoItem
.m_EditingCycles
&&
327 m_EditingDuration
== rInfoItem
.m_EditingDuration
&&
328 m_Description
== rInfoItem
.m_Description
&&
329 m_Keywords
== rInfoItem
.m_Keywords
&&
330 m_Contributor
== rInfoItem
.m_Contributor
&&
331 m_Coverage
== rInfoItem
.m_Coverage
&&
332 m_Identifier
== rInfoItem
.m_Identifier
&&
333 m_Publisher
== rInfoItem
.m_Publisher
&&
334 m_Relation
== rInfoItem
.m_Relation
&&
335 m_Rights
== rInfoItem
.m_Rights
&&
336 m_Source
== rInfoItem
.m_Source
&&
337 m_Type
== rInfoItem
.m_Type
&&
338 m_Subject
== rInfoItem
.m_Subject
&&
339 m_Title
== rInfoItem
.m_Title
&&
340 comphelper::ContainerUniquePtrEquals(m_aCustomProperties
, rInfoItem
.m_aCustomProperties
) &&
341 m_aCmisProperties
.getLength() == rInfoItem
.m_aCmisProperties
.getLength();
345 void SfxDocumentInfoItem::resetUserData(const OUString
& i_rAuthor
)
347 m_Author
= i_rAuthor
;
348 DateTime
now( DateTime::SYSTEM
);
349 m_CreationDate
= now
.GetUNODateTime();
350 m_ModifiedBy
= OUString();
351 m_PrintedBy
= OUString();
352 m_ModificationDate
= util::DateTime();
353 m_PrintDate
= util::DateTime();
354 m_EditingDuration
= 0;
359 void SfxDocumentInfoItem::UpdateDocumentInfo(
360 const uno::Reference
<document::XDocumentProperties
>& i_xDocProps
,
361 bool i_bDoNotUpdateUserDefined
) const
363 if (isAutoloadEnabled()) {
364 i_xDocProps
->setAutoloadSecs(getAutoloadDelay());
365 i_xDocProps
->setAutoloadURL(getAutoloadURL());
367 i_xDocProps
->setAutoloadSecs(0);
368 i_xDocProps
->setAutoloadURL(OUString());
370 i_xDocProps
->setDefaultTarget(getDefaultTarget());
371 i_xDocProps
->setAuthor(getAuthor());
372 i_xDocProps
->setCreationDate(getCreationDate());
373 i_xDocProps
->setModifiedBy(getModifiedBy());
374 i_xDocProps
->setModificationDate(getModificationDate());
375 i_xDocProps
->setPrintedBy(getPrintedBy());
376 i_xDocProps
->setPrintDate(getPrintDate());
377 i_xDocProps
->setEditingCycles(getEditingCycles());
378 i_xDocProps
->setEditingDuration(getEditingDuration());
379 i_xDocProps
->setDescription(getDescription());
380 i_xDocProps
->setKeywords(
381 ::comphelper::string::convertCommaSeparated(getKeywords()));
383 Reference
<document::XDocumentProperties2
> xDocProps2(i_xDocProps
, UNO_QUERY
);
384 xDocProps2
->setContributor(::comphelper::string::convertCommaSeparated(getContributor()));
385 xDocProps2
->setCoverage(getCoverage());
386 xDocProps2
->setIdentifier(getIdentifier());
387 xDocProps2
->setPublisher(::comphelper::string::convertCommaSeparated(getPublisher()));
388 xDocProps2
->setRelation(::comphelper::string::convertCommaSeparated(getRelation()));
389 xDocProps2
->setRights(getRights());
390 xDocProps2
->setSource(getSource());
391 xDocProps2
->setType(getType());
392 xDocProps2
->setSubject(getSubject());
393 xDocProps2
->setTitle(getTitle());
395 // this is necessary in case of replaying a recorded macro:
396 // in this case, the macro may contain the 4 old user-defined DocumentInfo
397 // fields, but not any of the DocumentInfo properties;
398 // as a consequence, most of the UserDefined properties of the
399 // DocumentProperties would be summarily deleted here, which does not
400 // seem like a good idea.
401 if (i_bDoNotUpdateUserDefined
)
406 Reference
< beans::XPropertyContainer
> xContainer
= i_xDocProps
->getUserDefinedProperties();
407 Reference
< beans::XPropertySet
> xSet( xContainer
, UNO_QUERY
);
408 Reference
< beans::XPropertySetInfo
> xSetInfo
= xSet
->getPropertySetInfo();
409 const Sequence
< beans::Property
> lProps
= xSetInfo
->getProperties();
410 for ( const beans::Property
& rProp
: lProps
)
412 if (rProp
.Attributes
& css::beans::PropertyAttribute::REMOVABLE
)
414 xContainer
->removeProperty( rProp
.Name
);
418 for (auto const & pProp
: m_aCustomProperties
)
422 xContainer
->addProperty( pProp
->m_sName
,
423 beans::PropertyAttribute::REMOVABLE
, pProp
->m_aValue
);
425 catch ( Exception
const & )
427 TOOLS_WARN_EXCEPTION( "sfx.dialog", "SfxDocumentInfoItem::updateDocumentInfo(): exception while adding custom properties" );
431 catch ( Exception
const & )
433 TOOLS_WARN_EXCEPTION( "sfx.dialog", "SfxDocumentInfoItem::updateDocumentInfo(): exception while removing custom properties" );
438 void SfxDocumentInfoItem::SetDeleteUserData( bool bSet
)
440 m_bDeleteUserData
= bSet
;
444 void SfxDocumentInfoItem::SetUseUserData( bool bSet
)
446 m_bUseUserData
= bSet
;
449 void SfxDocumentInfoItem::SetUseThumbnailSave( bool bSet
)
451 m_bUseThumbnailSave
= bSet
;
454 std::vector
< std::unique_ptr
<CustomProperty
> > SfxDocumentInfoItem::GetCustomProperties() const
456 std::vector
< std::unique_ptr
<CustomProperty
> > aRet
;
457 for (auto const & pOtherProp
: m_aCustomProperties
)
459 std::unique_ptr
<CustomProperty
> pProp(new CustomProperty( pOtherProp
->m_sName
,
460 pOtherProp
->m_aValue
));
461 aRet
.push_back( std::move(pProp
) );
467 void SfxDocumentInfoItem::ClearCustomProperties()
469 m_aCustomProperties
.clear();
472 void SfxDocumentInfoItem::AddCustomProperty( const OUString
& sName
, const Any
& rValue
)
474 std::unique_ptr
<CustomProperty
> pProp(new CustomProperty( sName
, rValue
));
475 m_aCustomProperties
.push_back( std::move(pProp
) );
479 void SfxDocumentInfoItem::SetCmisProperties( const Sequence
< document::CmisProperty
>& cmisProps
)
481 m_aCmisProperties
= cmisProps
;
484 bool SfxDocumentInfoItem::QueryValue( Any
& rVal
, sal_uInt8 nMemberId
) const
487 sal_Int32 nValue
= 0;
490 bool bIsString
= false;
491 nMemberId
&= ~CONVERT_TWIPS
;
494 case MID_DOCINFO_USEUSERDATA
:
495 bValue
= IsUseUserData();
497 case MID_DOCINFO_USETHUMBNAILSAVE
:
498 bValue
= IsUseThumbnailSave();
500 case MID_DOCINFO_DELETEUSERDATA
:
501 bValue
= m_bDeleteUserData
;
503 case MID_DOCINFO_AUTOLOADENABLED
:
504 bValue
= isAutoloadEnabled();
506 case MID_DOCINFO_AUTOLOADSECS
:
508 nValue
= getAutoloadDelay();
510 case MID_DOCINFO_AUTOLOADURL
:
512 aValue
= getAutoloadURL();
514 case MID_DOCINFO_DEFAULTTARGET
:
516 aValue
= getDefaultTarget();
518 case MID_DOCINFO_DESCRIPTION
:
520 aValue
= getDescription();
522 case MID_DOCINFO_KEYWORDS
:
524 aValue
= getKeywords();
526 case MID_DOCINFO_SUBJECT
:
528 aValue
= getSubject();
530 case MID_DOCINFO_TITLE
:
535 OSL_FAIL("Wrong MemberId!");
548 bool SfxDocumentInfoItem::PutValue( const Any
& rVal
, sal_uInt8 nMemberId
)
554 nMemberId
&= ~CONVERT_TWIPS
;
557 case MID_DOCINFO_USEUSERDATA
:
558 bRet
= (rVal
>>= bValue
);
560 SetUseUserData( bValue
);
562 case MID_DOCINFO_USETHUMBNAILSAVE
:
563 bRet
= (rVal
>>=bValue
);
565 SetUseThumbnailSave( bValue
);
567 case MID_DOCINFO_DELETEUSERDATA
:
568 // QUESTION: deleting user data was done here; seems to be superfluous!
569 bRet
= (rVal
>>= bValue
);
571 SetDeleteUserData( bValue
);
573 case MID_DOCINFO_AUTOLOADENABLED
:
574 bRet
= (rVal
>>= bValue
);
576 m_isAutoloadEnabled
= bValue
;
578 case MID_DOCINFO_AUTOLOADSECS
:
579 bRet
= (rVal
>>= nValue
);
581 m_AutoloadDelay
= nValue
;
583 case MID_DOCINFO_AUTOLOADURL
:
584 bRet
= (rVal
>>= aValue
);
586 m_AutoloadURL
= aValue
;
588 case MID_DOCINFO_DEFAULTTARGET
:
589 bRet
= (rVal
>>= aValue
);
591 m_DefaultTarget
= aValue
;
593 case MID_DOCINFO_DESCRIPTION
:
594 bRet
= (rVal
>>= aValue
);
596 setDescription(aValue
);
598 case MID_DOCINFO_KEYWORDS
:
599 bRet
= (rVal
>>= aValue
);
603 case MID_DOCINFO_SUBJECT
:
604 bRet
= (rVal
>>= aValue
);
608 case MID_DOCINFO_TITLE
:
609 bRet
= (rVal
>>= aValue
);
614 OSL_FAIL("Wrong MemberId!");
621 SfxDocumentDescPage::SfxDocumentDescPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rItemSet
)
622 : SfxTabPage(pPage
, pController
, u
"sfx/ui/descriptioninfopage.ui"_ustr
, u
"DescriptionInfoPage"_ustr
, &rItemSet
)
623 , m_pInfoItem(nullptr)
624 , m_xTitleEd(m_xBuilder
->weld_entry(u
"title"_ustr
))
625 , m_xThemaEd(m_xBuilder
->weld_entry(u
"subject"_ustr
))
626 , m_xKeywordsEd(m_xBuilder
->weld_entry(u
"keywords"_ustr
))
627 , m_xContributorEd(m_xBuilder
->weld_entry(u
"contributor"_ustr
))
628 , m_xCoverageEd(m_xBuilder
->weld_entry(u
"coverage"_ustr
))
629 , m_xIdentifierEd(m_xBuilder
->weld_entry(u
"identifier"_ustr
))
630 , m_xPublisherEd(m_xBuilder
->weld_entry(u
"publisher"_ustr
))
631 , m_xRelationEd(m_xBuilder
->weld_entry(u
"relation"_ustr
))
632 , m_xRightsEd(m_xBuilder
->weld_entry(u
"rights"_ustr
))
633 , m_xSourceEd(m_xBuilder
->weld_entry(u
"source"_ustr
))
634 , m_xTypeEd(m_xBuilder
->weld_entry(u
"type"_ustr
))
635 , m_xCommentEd(m_xBuilder
->weld_text_view(u
"comments"_ustr
))
637 m_xCommentEd
->set_size_request(m_xKeywordsEd
->get_preferred_size().Width(),
638 m_xCommentEd
->get_height_rows(16));
641 SfxDocumentDescPage::~SfxDocumentDescPage()
645 std::unique_ptr
<SfxTabPage
> SfxDocumentDescPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
*rItemSet
)
647 return std::make_unique
<SfxDocumentDescPage
>(pPage
, pController
, *rItemSet
);
650 bool SfxDocumentDescPage::FillItemSet(SfxItemSet
*rSet
)
652 // Test whether a change is present
653 const bool bTitleMod
= m_xTitleEd
->get_value_changed_from_saved();
654 const bool bThemeMod
= m_xThemaEd
->get_value_changed_from_saved();
655 const bool bKeywordsMod
= m_xKeywordsEd
->get_value_changed_from_saved();
656 const bool bContributorMod
= m_xContributorEd
->get_value_changed_from_saved();
657 const bool bCoverageMod
= m_xCoverageEd
->get_value_changed_from_saved();
658 const bool bIdentifierMod
= m_xIdentifierEd
->get_value_changed_from_saved();
659 const bool bPublisherMod
= m_xPublisherEd
->get_value_changed_from_saved();
660 const bool bRelationMod
= m_xRelationEd
->get_value_changed_from_saved();
661 const bool bRightsMod
= m_xRightsEd
->get_value_changed_from_saved();
662 const bool bSourceMod
= m_xSourceEd
->get_value_changed_from_saved();
663 const bool bTypeMod
= m_xTypeEd
->get_value_changed_from_saved();
664 const bool bCommentMod
= m_xCommentEd
->get_value_changed_from_saved();
665 if (!(bTitleMod
|| bThemeMod
|| bKeywordsMod
666 || bContributorMod
|| bCoverageMod
|| bIdentifierMod
|| bPublisherMod
|| bRelationMod
667 || bRightsMod
|| bSourceMod
|| bTypeMod
|| bCommentMod
))
672 // Generating the output data
673 const SfxDocumentInfoItem
* pItem
= nullptr;
674 SfxDocumentInfoItem
* pInfo
= nullptr;
675 const SfxItemSet
* pExSet
= GetDialogExampleSet();
677 if ( pExSet
&& !(pItem
= pExSet
->GetItemIfSet( SID_DOCINFO
)) )
680 pInfo
= new SfxDocumentInfoItem( *pItem
);
684 SAL_WARN( "sfx.dialog", "SfxDocumentDescPage::FillItemSet(): no item found" );
690 pInfo
->setTitle( m_xTitleEd
->get_text() );
694 pInfo
->setSubject( m_xThemaEd
->get_text() );
698 pInfo
->setKeywords( m_xKeywordsEd
->get_text() );
702 pInfo
->setContributor(m_xContributorEd
->get_text());
706 pInfo
->setCoverage(m_xCoverageEd
->get_text());
710 pInfo
->setIdentifier(m_xIdentifierEd
->get_text());
714 pInfo
->setPublisher(m_xPublisherEd
->get_text());
718 pInfo
->setRelation(m_xRelationEd
->get_text());
722 pInfo
->setRights(m_xRightsEd
->get_text());
726 pInfo
->setSource(m_xSourceEd
->get_text());
730 pInfo
->setType(m_xTypeEd
->get_text());
734 pInfo
->setDescription( m_xCommentEd
->get_text() );
737 // ptr compare OK, pInfo was created above as temporary data holder
738 if ( !areSfxPoolItemPtrsEqual(pInfo
, m_pInfoItem
) )
746 void SfxDocumentDescPage::Reset(const SfxItemSet
*rSet
)
748 m_pInfoItem
= const_cast<SfxDocumentInfoItem
*>(&rSet
->Get(SID_DOCINFO
));
750 m_xTitleEd
->set_text(m_pInfoItem
->getTitle());
751 m_xThemaEd
->set_text(m_pInfoItem
->getSubject());
752 m_xKeywordsEd
->set_text(m_pInfoItem
->getKeywords());
753 m_xContributorEd
->set_text(m_pInfoItem
->getContributor());
754 m_xCoverageEd
->set_text(m_pInfoItem
->getCoverage());
755 m_xIdentifierEd
->set_text(m_pInfoItem
->getIdentifier());
756 m_xPublisherEd
->set_text(m_pInfoItem
->getPublisher());
757 m_xRelationEd
->set_text(m_pInfoItem
->getRelation());
758 m_xRightsEd
->set_text(m_pInfoItem
->getRights());
759 m_xSourceEd
->set_text(m_pInfoItem
->getSource());
760 m_xTypeEd
->set_text(m_pInfoItem
->getType());
761 m_xCommentEd
->set_text(m_pInfoItem
->getDescription());
763 m_xTitleEd
->save_value();
764 m_xThemaEd
->save_value();
765 m_xKeywordsEd
->save_value();
766 m_xContributorEd
->save_value();
767 m_xCoverageEd
->save_value();
768 m_xIdentifierEd
->save_value();
769 m_xPublisherEd
->save_value();
770 m_xRelationEd
->save_value();
771 m_xRightsEd
->save_value();
772 m_xSourceEd
->save_value();
773 m_xTypeEd
->save_value();
774 m_xCommentEd
->save_value();
776 const SfxBoolItem
* pROItem
= SfxItemSet::GetItem
<SfxBoolItem
>(rSet
, SID_DOC_READONLY
, false);
777 if (pROItem
&& pROItem
->GetValue())
779 m_xTitleEd
->set_editable(false);
780 m_xThemaEd
->set_editable(false);
781 m_xKeywordsEd
->set_editable(false);
782 m_xContributorEd
->set_editable(false);
783 m_xCoverageEd
->set_editable(false);
784 m_xIdentifierEd
->set_editable(false);
785 m_xPublisherEd
->set_editable(false);
786 m_xRelationEd
->set_editable(false);
787 m_xRightsEd
->set_editable(false);
788 m_xSourceEd
->set_editable(false);
789 m_xTypeEd
->set_editable(false);
790 m_xCommentEd
->set_editable(false);
794 SfxDocumentPage::SfxDocumentPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rItemSet
)
795 : SfxTabPage(pPage
, pController
, u
"sfx/ui/documentinfopage.ui"_ustr
, u
"DocumentInfoPage"_ustr
, &rItemSet
)
796 , bEnableUseUserData( false )
797 , bHandleDelete( false )
798 , m_xBmp(m_xBuilder
->weld_image(u
"icon"_ustr
))
799 , m_xNameED(m_xBuilder
->weld_label(u
"nameed"_ustr
))
800 , m_xChangePassBtn(m_xBuilder
->weld_button(u
"changepass"_ustr
))
801 , m_xShowTypeFT(m_xBuilder
->weld_label(u
"showtype"_ustr
))
802 , m_xFileValEd(m_xBuilder
->weld_link_button(u
"showlocation"_ustr
))
803 , m_xShowSizeFT(m_xBuilder
->weld_label(u
"showsize"_ustr
))
804 , m_xCreateValFt(m_xBuilder
->weld_label(u
"showcreate"_ustr
))
805 , m_xChangeValFt(m_xBuilder
->weld_label(u
"showmodify"_ustr
))
806 , m_xSignedValFt(m_xBuilder
->weld_label(u
"showsigned"_ustr
))
807 , m_xSignatureBtn(m_xBuilder
->weld_button(u
"signature"_ustr
))
808 , m_xPrintValFt(m_xBuilder
->weld_label(u
"showprint"_ustr
))
809 , m_xTimeLogValFt(m_xBuilder
->weld_label(u
"showedittime"_ustr
))
810 , m_xDocNoValFt(m_xBuilder
->weld_label(u
"showrevision"_ustr
))
811 , m_xUseUserDataCB(m_xBuilder
->weld_check_button(u
"userdatacb"_ustr
))
812 , m_xDeleteBtn(m_xBuilder
->weld_button(u
"reset"_ustr
))
813 , m_xUseThumbnailSaveCB(m_xBuilder
->weld_check_button(u
"thumbnailsavecb"_ustr
))
814 , m_xTemplFt(m_xBuilder
->weld_label(u
"templateft"_ustr
))
815 , m_xTemplValFt(m_xBuilder
->weld_label(u
"showtemplate"_ustr
))
816 , m_xImagePreferredDpiCheckButton(m_xBuilder
->weld_check_button(u
"image-preferred-dpi-checkbutton"_ustr
))
817 , m_xImagePreferredDpiComboBox(m_xBuilder
->weld_combo_box(u
"image-preferred-dpi-combobox"_ustr
))
819 m_xUseUserDataCB
->set_accessible_description(SfxResId(STR_A11Y_DESC_USERDATA
));
821 m_aUnknownSize
= m_xShowSizeFT
->get_label();
822 m_xShowSizeFT
->set_label(OUString());
824 m_aMultiSignedStr
= m_xSignedValFt
->get_label();
825 m_xSignedValFt
->set_label(OUString());
826 m_xImagePreferredDpiComboBox
->set_entry_width_chars(5); // "width in chars" in Glade not effective
828 ImplUpdateSignatures();
829 ImplCheckPasswordState();
830 m_xChangePassBtn
->connect_clicked( LINK( this, SfxDocumentPage
, ChangePassHdl
) );
831 m_xSignatureBtn
->connect_clicked( LINK( this, SfxDocumentPage
, SignatureHdl
) );
832 if (comphelper::LibreOfficeKit::isActive())
833 m_xSignatureBtn
->hide();
834 m_xDeleteBtn
->connect_clicked( LINK( this, SfxDocumentPage
, DeleteHdl
) );
835 m_xImagePreferredDpiCheckButton
->connect_toggled(LINK(this, SfxDocumentPage
, ImagePreferredDPICheckBoxClicked
));
837 // [i96288] Check if the document signature command is enabled
838 // on the main list enable/disable the pushbutton accordingly
839 SvtCommandOptions aCmdOptions
;
840 if ( aCmdOptions
.LookupDisabled( u
"Signature"_ustr
) )
841 m_xSignatureBtn
->set_sensitive(false);
844 SfxDocumentPage::~SfxDocumentPage()
846 if (m_xPasswordDialog
)
848 m_xPasswordDialog
->Response(RET_CANCEL
);
849 m_xPasswordDialog
.clear();
853 IMPL_LINK_NOARG(SfxDocumentPage
, DeleteHdl
, weld::Button
&, void)
856 if (bEnableUseUserData
&& m_xUseUserDataCB
->get_active())
857 aName
= SvtUserOptions().GetFullName();
858 const LocaleDataWrapper
& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
859 DateTime
now( DateTime::SYSTEM
);
860 util::DateTime
uDT( now
.GetUNODateTime() );
861 m_xCreateValFt
->set_label( ConvertDateTime_Impl( aName
, uDT
, rLocaleWrapper
) );
862 m_xChangeValFt
->set_label( u
""_ustr
);
863 m_xPrintValFt
->set_label( u
""_ustr
);
864 m_xTimeLogValFt
->set_label( rLocaleWrapper
.getDuration( tools::Duration() ) );
865 m_xDocNoValFt
->set_label(OUString('1'));
866 bHandleDelete
= true;
869 IMPL_LINK_NOARG(SfxDocumentPage
, SignatureHdl
, weld::Button
&, void)
871 SfxObjectShell
* pDoc
= SfxObjectShell::Current();
874 pDoc
->SignDocumentContent(GetFrameWeld(), [this] (bool /*bHaveWeSigned*/) {
875 ImplUpdateSignatures();
880 IMPL_LINK_NOARG(SfxDocumentPage
, ImagePreferredDPICheckBoxClicked
, weld::Toggleable
&, void)
882 bool bEnabled
= m_xImagePreferredDpiCheckButton
->get_state() == TRISTATE_TRUE
;
883 m_xImagePreferredDpiComboBox
->set_sensitive(bEnabled
);
886 IMPL_LINK_NOARG(SfxDocumentPage
, ChangePassHdl
, weld::Button
&, void)
888 SfxObjectShell
* pShell
= SfxObjectShell::Current();
893 SfxItemSet
& rMedSet
= pShell
->GetMedium()->GetItemSet();
894 std::shared_ptr
<const SfxFilter
> pFilter
= pShell
->GetMedium()->GetFilter();
897 if (comphelper::LibreOfficeKit::isActive())
899 // MS Types support max len of 15 characters while OOXML is "unlimited"
900 const sal_uInt16 maxPwdLen
= sfx2::IsMSType(pFilter
) && !sfx2::IsOOXML(pFilter
) ? 15 : 0;
901 // handle the pwd dialog asynchronously
902 VclAbstractDialogFactory
* pFact
= VclAbstractDialogFactory::Create();
903 m_xPasswordDialog
= pFact
->CreatePasswordToOpenModifyDialog(GetFrameWeld(), maxPwdLen
, false);
904 m_xPasswordDialog
->AllowEmpty(); // needed to remove password
905 m_xPasswordDialog
->StartExecuteAsync([this, pFilter
=std::move(pFilter
), &rMedSet
, pShell
](sal_Int32 nResult
)
907 if (nResult
== RET_OK
)
909 sfx2::SetPassword(pFilter
, &rMedSet
, m_xPasswordDialog
->GetPasswordToOpen(),
910 m_xPasswordDialog
->GetPasswordToOpen(), true);
911 tools::JsonWriter payloadJson
;
912 payloadJson
.put("password", m_xPasswordDialog
->GetPasswordToOpen());
913 payloadJson
.put("isToModify", false);
915 SfxViewShell
*pViewShell
= SfxViewShell::Current();
917 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_DOCUMENT_PASSWORD_RESET
, payloadJson
.finishAndGetAsOString());
919 pShell
->SetModified();
921 m_xPasswordDialog
->disposeOnce();
924 sfx2::RequestPassword(pFilter
, OUString(), &rMedSet
, GetFrameWeld()->GetXWindow());
925 pShell
->SetModified();
931 void SfxDocumentPage::ImplUpdateSignatures()
933 SfxObjectShell
* pDoc
= SfxObjectShell::Current();
937 SfxMedium
* pMedium
= pDoc
->GetMedium();
938 if ( !pMedium
|| pMedium
->GetName().isEmpty() || !pMedium
->GetStorage().is() )
941 Reference
< security::XDocumentDigitalSignatures
> xD
;
944 xD
= security::DocumentDigitalSignatures::createDefault(comphelper::getProcessComponentContext());
945 xD
->setParentWindow(GetDialogController()->getDialog()->GetXWindow());
947 catch ( const css::uno::DeploymentException
& )
951 Sequence
< security::DocumentSignatureInformation
> aInfos
;
954 aInfos
= xD
->verifyDocumentContentSignatures( pMedium
->GetZipStorageToSign_Impl(),
955 uno::Reference
< io::XInputStream
>() );
956 if ( aInfos
.getLength() > 1 )
957 s
= m_aMultiSignedStr
;
958 else if ( aInfos
.getLength() == 1 )
960 const security::DocumentSignatureInformation
& rInfo
= aInfos
[ 0 ];
961 s
= utl::GetDateTimeString( rInfo
.SignatureDate
, rInfo
.SignatureTime
) + ", " +
962 comphelper::xmlsec::GetContentPart(rInfo
.Signer
->getSubjectName(), rInfo
.Signer
->getCertificateKind());
964 m_xSignedValFt
->set_label(s
);
967 void SfxDocumentPage::ImplCheckPasswordState()
969 SfxObjectShell
* pShell
= SfxObjectShell::Current();
974 const SfxUnoAnyItem
* pEncryptionDataItem
= pShell
->GetMedium()->GetItemSet().GetItem(SID_ENCRYPTIONDATA
, false);
975 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
976 if (pEncryptionDataItem
)
977 pEncryptionDataItem
->GetValue() >>= aEncryptionData
;
981 if (!aEncryptionData
.hasElements())
983 m_xChangePassBtn
->set_sensitive(true);
987 m_xChangePassBtn
->set_sensitive(comphelper::LibreOfficeKit::isActive());
990 std::unique_ptr
<SfxTabPage
> SfxDocumentPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
* rItemSet
)
992 return std::make_unique
<SfxDocumentPage
>(pPage
, pController
, *rItemSet
);
995 void SfxDocumentPage::EnableUseUserData()
997 bEnableUseUserData
= true;
998 m_xUseUserDataCB
->show();
999 m_xDeleteBtn
->show();
1002 bool SfxDocumentPage::FillItemSet( SfxItemSet
* rSet
)
1006 if ( !bHandleDelete
&& bEnableUseUserData
&&
1007 m_xUseUserDataCB
->get_state_changed_from_saved() )
1009 const SfxItemSet
* pExpSet
= GetDialogExampleSet();
1010 const SfxDocumentInfoItem
* pInfoItem
;
1012 if ( pExpSet
&& (pInfoItem
= pExpSet
->GetItemIfSet( SID_DOCINFO
) ) )
1014 bool bUseData
= ( TRISTATE_TRUE
== m_xUseUserDataCB
->get_state() );
1015 const_cast<SfxDocumentInfoItem
*>(pInfoItem
)->SetUseUserData( bUseData
);
1016 rSet
->Put( *pInfoItem
);
1021 if ( bHandleDelete
)
1023 const SfxItemSet
* pExpSet
= GetDialogExampleSet();
1024 const SfxDocumentInfoItem
* pInfoItem
;
1025 if ( pExpSet
&& (pInfoItem
= pExpSet
->GetItemIfSet( SID_DOCINFO
)) )
1027 bool bUseAuthor
= bEnableUseUserData
&& m_xUseUserDataCB
->get_active();
1028 SfxDocumentInfoItem
newItem( *pInfoItem
);
1029 newItem
.resetUserData( bUseAuthor
1030 ? SvtUserOptions().GetFullName()
1032 const_cast<SfxDocumentInfoItem
*>(pInfoItem
)->SetUseUserData( TRISTATE_TRUE
== m_xUseUserDataCB
->get_state() );
1033 newItem
.SetUseUserData( TRISTATE_TRUE
== m_xUseUserDataCB
->get_state() );
1035 newItem
.SetDeleteUserData( true );
1036 rSet
->Put( newItem
);
1041 if ( m_xUseThumbnailSaveCB
->get_state_changed_from_saved() )
1043 const SfxItemSet
* pExpSet
= GetDialogExampleSet();
1044 const SfxDocumentInfoItem
* pInfoItem
;
1046 if ( pExpSet
&& (pInfoItem
= pExpSet
->GetItemIfSet( SID_DOCINFO
)) )
1048 bool bUseThumbnail
= ( TRISTATE_TRUE
== m_xUseThumbnailSaveCB
->get_state() );
1049 const_cast<SfxDocumentInfoItem
*>(pInfoItem
)->SetUseThumbnailSave( bUseThumbnail
);
1050 rSet
->Put( *pInfoItem
);
1055 SfxObjectShell
* pDocSh
= SfxObjectShell::Current();
1058 uno::Reference
<lang::XMultiServiceFactory
> xFac(pDocSh
->GetModel(), uno::UNO_QUERY
);
1061 uno::Reference
<beans::XPropertySet
> xProps(xFac
->createInstance(u
"com.sun.star.document.Settings"_ustr
), uno::UNO_QUERY
);
1064 sal_Int32 nImagePreferredDPI
= 0;
1065 if (m_xImagePreferredDpiCheckButton
->get_state() == TRISTATE_TRUE
)
1067 OUString aImagePreferredDPIString
= m_xImagePreferredDpiComboBox
->get_active_text();
1068 nImagePreferredDPI
= aImagePreferredDPIString
.toInt32();
1070 xProps
->setPropertyValue(u
"ImagePreferredDPI"_ustr
, uno::Any(nImagePreferredDPI
));
1078 void SfxDocumentPage::Reset( const SfxItemSet
* rSet
)
1080 // Determine the document information
1081 const SfxDocumentInfoItem
& rInfoItem
= rSet
->Get(SID_DOCINFO
);
1084 if (rInfoItem
.HasTemplate())
1086 const OUString
& rName
= rInfoItem
.getTemplateName();
1087 if (rName
.getLength() > SAL_MAX_INT16
) // tdf#122780 pick some ~arbitrary max size
1088 m_xTemplValFt
->set_label(rName
.copy(0, SAL_MAX_INT16
));
1090 m_xTemplValFt
->set_label(rName
);
1095 m_xTemplValFt
->hide();
1098 // determine file name
1099 OUString
aFile( rInfoItem
.GetValue() );
1100 OUString
aFactory( aFile
);
1101 if ( aFile
.getLength() > 2 && aFile
[0] == '[' )
1103 sal_Int32 nPos
= aFile
.indexOf( ']' );
1104 aFactory
= aFile
.copy( 1, nPos
-1 );
1105 aFile
= aFile
.copy( nPos
+1 );
1109 INetURLObject
aURL(aFile
);
1110 OUString aName
= aURL
.GetLastName(INetURLObject::DecodeMechanism::WithCharset
);
1111 if ( aName
.isEmpty() || aURL
.GetProtocol() == INetProtocol::PrivSoffice
)
1112 aName
= SfxResId( STR_NONAME
);
1113 m_xNameED
->set_label( aName
);
1115 // determine context symbol
1116 aURL
.SetSmartProtocol( INetProtocol::File
);
1117 aURL
.SetSmartURL( aFactory
);
1118 const OUString aMainURL
= aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
1119 OUString aImage
= SvFileInformationManager::GetImageId( aURL
, true );
1120 m_xBmp
->set_from_icon_name(aImage
);
1122 // determine size and type
1123 OUString
aSizeText( m_aUnknownSize
);
1124 // we might already know the size as an optional argument passed to .uno:SetDocumentProperties
1125 sal_Int64 nSize
= rInfoItem
.getFileSize();
1126 // otherwise, for some protocols we can reliably query for it
1127 if (nSize
== -1 && (aURL
.GetProtocol() == INetProtocol::File
|| aURL
.isAnyKnownWebDAVScheme()))
1128 nSize
= SfxContentHelper::GetSize( aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) );
1130 aSizeText
= CreateSizeText( nSize
);
1131 m_xShowSizeFT
->set_label( aSizeText
);
1133 OUString aDescription
= SvFileInformationManager::GetDescription( INetURLObject(aMainURL
) );
1134 if ( aDescription
.isEmpty() )
1135 aDescription
= SfxResId( STR_SFX_NEWOFFICEDOC
);
1136 m_xShowTypeFT
->set_label( aDescription
);
1138 // determine location
1139 // online we don't know file location so we just set it as the name
1140 if (comphelper::LibreOfficeKit::isActive())
1142 m_xFileValEd
->set_label(aName
);
1143 m_xFileValEd
->set_uri(aName
);
1145 // Disable setting/changing password on text files.
1146 // Perhaps this needs to be done for both Online and Desktop.
1147 OUString
sExtension(INetURLObject(aMainURL
).getExtension());
1148 if (!sExtension
.isEmpty())
1150 sExtension
= sExtension
.toAsciiLowerCase();
1151 if (sExtension
== "txt" || sExtension
== "csv")
1152 m_xChangePassBtn
->set_sensitive(false);
1157 aURL
.SetSmartURL( aFile
);
1158 if ( aURL
.GetProtocol() == INetProtocol::File
)
1160 INetURLObject
aPath(std::move(aURL
));
1161 aPath
.setFinalSlash();
1162 aPath
.removeSegment();
1163 // we know it's a folder -> don't need the final slash, but it's better for WB_PATHELLIPSIS
1164 aPath
.removeFinalSlash();
1165 OUString
aText( aPath
.PathToFileName() ); //! (pb) MaxLen?
1166 m_xFileValEd
->set_label(aText
);
1168 osl::FileBase::getFileURLFromSystemPath(aText
, aURLStr
);
1169 m_xFileValEd
->set_uri(aURLStr
);
1171 else if (aURL
.GetProtocol() != INetProtocol::PrivSoffice
)
1173 m_xFileValEd
->set_label(aURL
.GetPartBeforeLastName());
1174 m_xFileValEd
->set_uri(m_xFileValEd
->get_label());
1179 // handle access data
1180 bool bUseUserData
= rInfoItem
.IsUseUserData();
1181 const LocaleDataWrapper
& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
1182 m_xCreateValFt
->set_label( ConvertDateTime_Impl( rInfoItem
.getAuthor(),
1183 rInfoItem
.getCreationDate(), rLocaleWrapper
) );
1184 util::DateTime
aTime( rInfoItem
.getModificationDate() );
1185 if ( aTime
.Month
> 0 )
1186 m_xChangeValFt
->set_label( ConvertDateTime_Impl(
1187 rInfoItem
.getModifiedBy(), aTime
, rLocaleWrapper
) );
1188 aTime
= rInfoItem
.getPrintDate();
1189 if ( aTime
.Month
> 0 )
1190 m_xPrintValFt
->set_label( ConvertDateTime_Impl( rInfoItem
.getPrintedBy(),
1191 aTime
, rLocaleWrapper
) );
1192 const tools::Long nTime
= rInfoItem
.getEditingDuration();
1195 assert(SAL_MIN_INT32
<= nTime
/86400 && nTime
/86400 <= SAL_MAX_INT32
);
1196 const tools::Duration
aD( static_cast<sal_Int32
>(nTime
)/86400,
1197 (nTime
%86400)/3600, (nTime
%3600)/60, nTime
%60, 0);
1198 m_xTimeLogValFt
->set_label( rLocaleWrapper
.getDuration( aD
) );
1199 m_xDocNoValFt
->set_label( OUString::number(
1200 rInfoItem
.getEditingCycles() ) );
1203 bool bUseThumbnailSave
= rInfoItem
.IsUseThumbnailSave();
1205 // Check for cmis properties where otherwise unavailable
1206 if ( rInfoItem
.isCmisDocument( ) )
1208 const uno::Sequence
< document::CmisProperty
>& aCmisProps
= rInfoItem
.GetCmisProperties();
1209 for ( const auto& rCmisProp
: aCmisProps
)
1211 if ( rCmisProp
.Id
== "cmis:contentStreamLength" &&
1212 aSizeText
== m_aUnknownSize
)
1214 Sequence
< sal_Int64
> seqValue
;
1215 rCmisProp
.Value
>>= seqValue
;
1216 SvNumberFormatter
aNumberFormatter( ::comphelper::getProcessComponentContext(),
1217 Application::GetSettings().GetLanguageTag().getLanguageType() );
1218 sal_uInt32 nIndex
= aNumberFormatter
.GetFormatIndex( NF_NUMBER_SYSTEM
);
1219 if ( seqValue
.hasElements() )
1221 OUString sValue
= aNumberFormatter
.GetInputLineString( seqValue
[0], nIndex
);
1222 m_xShowSizeFT
->set_label( CreateSizeText( sValue
.toInt64( ) ) );
1227 OUString emptyDate
= ConvertDateTime_Impl( u
"", uDT
, rLocaleWrapper
);
1228 if ( rCmisProp
.Id
== "cmis:creationDate" &&
1229 (m_xCreateValFt
->get_label() == emptyDate
||
1230 m_xCreateValFt
->get_label().isEmpty()))
1232 Sequence
< util::DateTime
> seqValue
;
1233 rCmisProp
.Value
>>= seqValue
;
1234 if ( seqValue
.hasElements() )
1236 m_xCreateValFt
->set_label( ConvertDateTime_Impl( u
"", seqValue
[0], rLocaleWrapper
) );
1239 if ( rCmisProp
.Id
== "cmis:lastModificationDate" &&
1240 (m_xChangeValFt
->get_label() == emptyDate
||
1241 m_xChangeValFt
->get_label().isEmpty()))
1243 Sequence
< util::DateTime
> seqValue
;
1244 rCmisProp
.Value
>>= seqValue
;
1245 if ( seqValue
.hasElements() )
1247 m_xChangeValFt
->set_label( ConvertDateTime_Impl( u
"", seqValue
[0], rLocaleWrapper
) );
1253 m_xUseUserDataCB
->set_active(bUseUserData
);
1254 m_xUseUserDataCB
->save_state();
1255 m_xUseUserDataCB
->set_sensitive( bEnableUseUserData
);
1256 bHandleDelete
= false;
1257 m_xDeleteBtn
->set_sensitive( bEnableUseUserData
);
1258 m_xUseThumbnailSaveCB
->set_active(bUseThumbnailSave
);
1259 m_xUseThumbnailSaveCB
->save_state();
1261 SfxObjectShell
* pDocSh
= SfxObjectShell::Current();
1262 sal_Int32 nImagePreferredDPI
= 0;
1267 uno::Reference
< lang::XMultiServiceFactory
> xFac( pDocSh
->GetModel(), uno::UNO_QUERY
);
1270 uno::Reference
< beans::XPropertySet
> xProps( xFac
->createInstance(u
"com.sun.star.document.Settings"_ustr
), uno::UNO_QUERY
);
1272 xProps
->getPropertyValue(u
"ImagePreferredDPI"_ustr
) >>= nImagePreferredDPI
;
1275 catch( uno::Exception
& )
1279 if (nImagePreferredDPI
> 0)
1281 m_xImagePreferredDpiCheckButton
->set_state(TRISTATE_TRUE
);
1282 m_xImagePreferredDpiComboBox
->set_sensitive(true);
1283 m_xImagePreferredDpiComboBox
->set_entry_text(OUString::number(nImagePreferredDPI
));
1287 m_xImagePreferredDpiCheckButton
->set_state(TRISTATE_FALSE
);
1288 m_xImagePreferredDpiComboBox
->set_sensitive(false);
1289 m_xImagePreferredDpiComboBox
->set_entry_text(u
""_ustr
);
1294 SfxDocumentInfoDialog::SfxDocumentInfoDialog(weld::Window
* pParent
, const SfxItemSet
& rItemSet
)
1295 : SfxTabDialogController(pParent
, u
"sfx/ui/documentpropertiesdialog.ui"_ustr
,
1296 u
"DocumentPropertiesDialog"_ustr
, &rItemSet
)
1298 const SfxDocumentInfoItem
& rInfoItem
= rItemSet
.Get( SID_DOCINFO
);
1301 const SfxStringItem
* pURLItem
= rItemSet
.GetItem
<SfxStringItem
>(SID_BASEURL
, false);
1302 DBG_ASSERT( pURLItem
, "No BaseURL provided for InternetTabPage!" );
1305 // Determine the Titles
1306 OUString
aTitle(m_xDialog
->get_title());
1307 const SfxStringItem
* pItem
= rItemSet
.GetItemIfSet( SID_EXPLORER_PROPS_START
, false );
1311 const OUString
& aFile( rInfoItem
.GetValue() );
1314 aURL
.SetSmartProtocol( INetProtocol::File
);
1315 aURL
.SetSmartURL( aFile
);
1316 if ( INetProtocol::PrivSoffice
!= aURL
.GetProtocol() )
1318 OUString
aLastName( aURL
.GetLastName() );
1319 if ( !aLastName
.isEmpty() )
1320 aTitle
= aTitle
.replaceFirst("%1", aLastName
);
1322 aTitle
= aTitle
.replaceFirst("%1", aFile
);
1325 aTitle
= aTitle
.replaceFirst("%1", SfxResId( STR_NONAME
));
1329 aTitle
= aTitle
.replaceFirst("%1", pItem
->GetValue());
1331 m_xDialog
->set_title(aTitle
);
1334 AddTabPage(u
"general"_ustr
, SfxDocumentPage::Create
, nullptr);
1335 AddTabPage(u
"description"_ustr
, SfxDocumentDescPage::Create
, nullptr);
1337 AddTabPage(u
"customprops"_ustr
, SfxCustomPropertiesPage::Create
, nullptr);
1339 if (rInfoItem
.isCmisDocument())
1340 AddTabPage(u
"cmisprops"_ustr
, SfxCmisPropertiesPage::Create
, nullptr);
1342 RemoveTabPage(u
"cmisprops"_ustr
);
1343 // Disable security page for online as not fully asynced yet
1344 if (!comphelper::LibreOfficeKit::isActive())
1345 AddTabPage(u
"security"_ustr
, SfxSecurityPage::Create
, nullptr);
1347 RemoveTabPage(u
"security"_ustr
);
1350 void SfxDocumentInfoDialog::PageCreated(const OUString
& rId
, SfxTabPage
&rPage
)
1352 if (rId
== "general")
1353 static_cast<SfxDocumentPage
&>(rPage
).EnableUseUserData();
1356 void SfxDocumentInfoDialog::AddFontTabPage()
1358 AddTabPage(u
"font"_ustr
, SfxResId(STR_FONT_TABPAGE
), SfxDocumentFontsPage::Create
);
1361 // class CustomPropertiesYesNoButton -------------------------------------
1363 CustomPropertiesYesNoButton::CustomPropertiesYesNoButton(std::unique_ptr
<weld::Widget
> xTopLevel
,
1364 std::unique_ptr
<weld::RadioButton
> xYesButton
,
1365 std::unique_ptr
<weld::RadioButton
> xNoButton
)
1366 : m_xTopLevel(std::move(xTopLevel
))
1367 , m_xYesButton(std::move(xYesButton
))
1368 , m_xNoButton(std::move(xNoButton
))
1373 CustomPropertiesYesNoButton::~CustomPropertiesYesNoButton()
1378 DurationDialog_Impl::DurationDialog_Impl(weld::Widget
* pParent
, const util::Duration
& rDuration
)
1379 : GenericDialogController(pParent
, u
"sfx/ui/editdurationdialog.ui"_ustr
, u
"EditDurationDialog"_ustr
)
1380 , m_xNegativeCB(m_xBuilder
->weld_check_button(u
"negative"_ustr
))
1381 , m_xYearNF(m_xBuilder
->weld_spin_button(u
"years"_ustr
))
1382 , m_xMonthNF(m_xBuilder
->weld_spin_button(u
"months"_ustr
))
1383 , m_xDayNF(m_xBuilder
->weld_spin_button(u
"days"_ustr
))
1384 , m_xHourNF(m_xBuilder
->weld_spin_button(u
"hours"_ustr
))
1385 , m_xMinuteNF(m_xBuilder
->weld_spin_button(u
"minutes"_ustr
))
1386 , m_xSecondNF(m_xBuilder
->weld_spin_button(u
"seconds"_ustr
))
1387 , m_xMSecondNF(m_xBuilder
->weld_spin_button(u
"milliseconds"_ustr
))
1389 m_xNegativeCB
->set_active(rDuration
.Negative
);
1390 m_xYearNF
->set_value(rDuration
.Years
);
1391 m_xMonthNF
->set_value(rDuration
.Months
);
1392 m_xDayNF
->set_value(rDuration
.Days
);
1393 m_xHourNF
->set_value(rDuration
.Hours
);
1394 m_xMinuteNF
->set_value(rDuration
.Minutes
);
1395 m_xSecondNF
->set_value(rDuration
.Seconds
);
1396 m_xMSecondNF
->set_value(rDuration
.NanoSeconds
);
1399 util::Duration
DurationDialog_Impl::GetDuration() const
1401 util::Duration aRet
;
1402 aRet
.Negative
= m_xNegativeCB
->get_active();
1403 aRet
.Years
= m_xYearNF
->get_value();
1404 aRet
.Months
= m_xMonthNF
->get_value();
1405 aRet
.Days
= m_xDayNF
->get_value();
1406 aRet
.Hours
= m_xHourNF
->get_value();
1407 aRet
.Minutes
= m_xMinuteNF
->get_value();
1408 aRet
.Seconds
= m_xSecondNF
->get_value();
1409 aRet
.NanoSeconds
= m_xMSecondNF
->get_value();
1413 CustomPropertiesDurationField::CustomPropertiesDurationField(std::unique_ptr
<weld::Entry
> xEntry
,
1414 std::unique_ptr
<weld::Button
> xEditButton
)
1415 : m_xEntry(std::move(xEntry
))
1416 , m_xEditButton(std::move(xEditButton
))
1418 m_xEditButton
->connect_clicked(LINK(this, CustomPropertiesDurationField
, ClickHdl
));
1419 SetDuration( util::Duration(false, 0, 0, 0, 0, 0, 0, 0) );
1422 void CustomPropertiesDurationField::set_visible(bool bVisible
)
1424 m_xEntry
->set_visible(bVisible
);
1425 m_xEditButton
->set_visible(bVisible
);
1428 void CustomPropertiesDurationField::SetDuration( const util::Duration
& rDuration
)
1430 m_aDuration
= rDuration
;
1431 OUString sText
= (rDuration
.Negative
? OUString('-') : OUString('+')) +
1432 SfxResId(SFX_ST_DURATION_FORMAT
);
1433 sText
= sText
.replaceFirst( "%1", OUString::number( rDuration
.Years
) );
1434 sText
= sText
.replaceFirst( "%2", OUString::number( rDuration
.Months
) );
1435 sText
= sText
.replaceFirst( "%3", OUString::number( rDuration
.Days
) );
1436 sText
= sText
.replaceFirst( "%4", OUString::number( rDuration
.Hours
) );
1437 sText
= sText
.replaceFirst( "%5", OUString::number( rDuration
.Minutes
) );
1438 sText
= sText
.replaceFirst( "%6", OUString::number( rDuration
.Seconds
) );
1439 m_xEntry
->set_text(sText
);
1442 IMPL_LINK(CustomPropertiesDurationField
, ClickHdl
, weld::Button
&, rButton
, void)
1444 m_xDurationDialog
= std::make_shared
<DurationDialog_Impl
>(&rButton
, GetDuration());
1445 weld::DialogController::runAsync(m_xDurationDialog
, [&](sal_Int32 response
)
1447 if (response
== RET_OK
)
1449 SetDuration(m_xDurationDialog
->GetDuration());
1454 CustomPropertiesDurationField::~CustomPropertiesDurationField()
1456 if (m_xDurationDialog
)
1457 m_xDurationDialog
->response(RET_CANCEL
);
1462 void fillNameBox(weld::ComboBox
& rNameBox
)
1464 for (size_t i
= 0; i
< SAL_N_ELEMENTS(SFX_CB_PROPERTY_STRINGARRAY
); ++i
)
1465 rNameBox
.append_text(SfxResId(SFX_CB_PROPERTY_STRINGARRAY
[i
]));
1466 Size
aSize(rNameBox
.get_preferred_size());
1467 rNameBox
.set_size_request(aSize
.Width(), aSize
.Height());
1470 void fillTypeBox(weld::ComboBox
& rTypeBox
)
1472 for (size_t i
= 0; i
< SAL_N_ELEMENTS(SFX_LB_PROPERTY_STRINGARRAY
); ++i
)
1474 OUString
sId(OUString::number(SFX_LB_PROPERTY_STRINGARRAY
[i
].second
));
1475 rTypeBox
.append(sId
, SfxResId(SFX_LB_PROPERTY_STRINGARRAY
[i
].first
));
1477 rTypeBox
.set_active(0);
1478 Size
aSize(rTypeBox
.get_preferred_size());
1479 rTypeBox
.set_size_request(aSize
.Width(), aSize
.Height());
1483 // struct CustomPropertyLine ---------------------------------------------
1484 CustomPropertyLine::CustomPropertyLine(CustomPropertiesWindow
* pParent
, weld::Widget
* pContainer
)
1485 : m_pParent(pParent
)
1486 , m_xBuilder(Application::CreateBuilder(pContainer
, u
"sfx/ui/linefragment.ui"_ustr
))
1487 , m_xLine(m_xBuilder
->weld_container(u
"lineentry"_ustr
))
1488 , m_xNameBox(m_xBuilder
->weld_combo_box(u
"namebox"_ustr
))
1489 , m_xTypeBox(m_xBuilder
->weld_combo_box(u
"typebox"_ustr
))
1490 , m_xValueEdit(m_xBuilder
->weld_entry(u
"valueedit"_ustr
))
1491 , m_xDateTimeBox(m_xBuilder
->weld_widget(u
"datetimebox"_ustr
))
1492 , m_xDateField(new CustomPropertiesDateField(new SvtCalendarBox(m_xBuilder
->weld_menu_button(u
"date"_ustr
))))
1493 , m_xTimeField(new CustomPropertiesTimeField(m_xBuilder
->weld_formatted_spin_button(u
"time"_ustr
)))
1494 , m_xDurationBox(m_xBuilder
->weld_widget(u
"durationbox"_ustr
))
1495 , m_xDurationField(new CustomPropertiesDurationField(m_xBuilder
->weld_entry(u
"duration"_ustr
),
1496 m_xBuilder
->weld_button(u
"durationbutton"_ustr
)))
1497 , m_xYesNoButton(new CustomPropertiesYesNoButton(m_xBuilder
->weld_widget(u
"yesno"_ustr
),
1498 m_xBuilder
->weld_radio_button(u
"yes"_ustr
),
1499 m_xBuilder
->weld_radio_button(u
"no"_ustr
)))
1500 , m_xRemoveButton(m_xBuilder
->weld_button(u
"remove"_ustr
))
1501 , m_bTypeLostFocus( false )
1503 fillNameBox(*m_xNameBox
);
1504 fillTypeBox(*m_xTypeBox
);
1506 m_xTypeBox
->connect_changed(LINK(this, CustomPropertyLine
, TypeHdl
));
1507 m_xRemoveButton
->connect_clicked(LINK(this, CustomPropertyLine
, RemoveHdl
));
1508 m_xValueEdit
->connect_focus_out(LINK(this, CustomPropertyLine
, EditLoseFocusHdl
));
1509 //add lose focus handlers of date/time fields
1510 m_xTypeBox
->connect_focus_out(LINK(this, CustomPropertyLine
, BoxLoseFocusHdl
));
1513 void CustomPropertyLine::Clear()
1515 m_xNameBox
->set_active(-1);
1516 m_xValueEdit
->set_text(OUString());
1520 void CustomPropertyLine::Hide()
1525 CustomPropertiesWindow::CustomPropertiesWindow(weld::Container
& rParent
, weld::Label
& rHeaderAccName
,
1526 weld::Label
& rHeaderAccType
, weld::Label
& rHeaderAccValue
)
1530 , m_pCurrentLine(nullptr)
1531 , m_aNumberFormatter(::comphelper::getProcessComponentContext(),
1532 Application::GetSettings().GetLanguageTag().getLanguageType())
1533 , m_aEditLoseFocusIdle("sfx2 CustomPropertiesWindow loseFocusIdle")
1534 , m_aBoxLoseFocusIdle("sfx2 CustomPropertiesWindow m_aBoxLoseFocusIdle")
1536 , m_rHeaderAccName(rHeaderAccName
)
1537 , m_rHeaderAccType(rHeaderAccType
)
1538 , m_rHeaderAccValue(rHeaderAccValue
)
1540 m_aEditLoseFocusIdle
.SetPriority( TaskPriority::LOWEST
);
1541 m_aEditLoseFocusIdle
.SetInvokeHandler( LINK( this, CustomPropertiesWindow
, EditTimeoutHdl
) );
1542 m_aBoxLoseFocusIdle
.SetPriority( TaskPriority::LOWEST
);
1543 m_aBoxLoseFocusIdle
.SetInvokeHandler( LINK( this, CustomPropertiesWindow
, BoxTimeoutHdl
) );
1546 CustomPropertiesWindow::~CustomPropertiesWindow()
1548 m_aEditLoseFocusIdle
.Stop();
1549 m_aBoxLoseFocusIdle
.Stop();
1551 m_pCurrentLine
= nullptr;
1554 void CustomPropertyLine::DoTypeHdl(const weld::ComboBox
& rBox
)
1556 auto nType
= rBox
.get_active_id().toInt32();
1557 m_xValueEdit
->set_visible( (Custom_Type_Text
== nType
) || (Custom_Type_Number
== nType
) );
1558 m_xDateTimeBox
->set_visible( (Custom_Type_Date
== nType
) || (Custom_Type_Datetime
== nType
) );
1559 m_xDateField
->set_visible( (Custom_Type_Date
== nType
) || (Custom_Type_Datetime
== nType
) );
1560 m_xTimeField
->set_visible( Custom_Type_Datetime
== nType
);
1561 m_xDurationBox
->set_visible( Custom_Type_Duration
== nType
);
1562 m_xDurationField
->set_visible( Custom_Type_Duration
== nType
);
1563 m_xYesNoButton
->set_visible( Custom_Type_Boolean
== nType
);
1566 IMPL_LINK(CustomPropertyLine
, TypeHdl
, weld::ComboBox
&, rBox
, void)
1571 void CustomPropertiesWindow::Remove(const CustomPropertyLine
* pLine
)
1573 StoreCustomProperties();
1575 auto pFound
= std::find_if( m_aCustomPropertiesLines
.begin(), m_aCustomPropertiesLines
.end(),
1576 [&] (const std::unique_ptr
<CustomPropertyLine
>& p
) { return p
.get() == pLine
; });
1577 if ( pFound
!= m_aCustomPropertiesLines
.end() )
1579 sal_uInt32 nLineNumber
= pFound
- m_aCustomPropertiesLines
.begin();
1580 sal_uInt32 nDataModelIndex
= GetCurrentDataModelPosition() + nLineNumber
;
1581 m_aCustomProperties
.erase(m_aCustomProperties
.begin() + nDataModelIndex
);
1583 ReloadLinesContent();
1586 m_aRemovedHdl
.Call(nullptr);
1589 IMPL_LINK_NOARG(CustomPropertyLine
, RemoveHdl
, weld::Button
&, void)
1591 m_pParent
->Remove(this);
1594 void CustomPropertiesWindow::EditLoseFocus(CustomPropertyLine
* pLine
)
1596 m_pCurrentLine
= pLine
;
1597 m_aEditLoseFocusIdle
.Start();
1600 IMPL_LINK_NOARG(CustomPropertyLine
, EditLoseFocusHdl
, weld::Widget
&, void)
1602 if (!m_bTypeLostFocus
)
1603 m_pParent
->EditLoseFocus(this);
1605 m_bTypeLostFocus
= false;
1608 void CustomPropertiesWindow::BoxLoseFocus(CustomPropertyLine
* pLine
)
1610 m_pCurrentLine
= pLine
;
1611 m_aBoxLoseFocusIdle
.Start();
1614 IMPL_LINK_NOARG(CustomPropertyLine
, BoxLoseFocusHdl
, weld::Widget
&, void)
1616 m_pParent
->BoxLoseFocus(this);
1619 IMPL_LINK_NOARG(CustomPropertiesWindow
, EditTimeoutHdl
, Timer
*, void)
1621 ValidateLine( m_pCurrentLine
, false );
1624 IMPL_LINK_NOARG(CustomPropertiesWindow
, BoxTimeoutHdl
, Timer
*, void)
1626 ValidateLine( m_pCurrentLine
, true );
1629 bool CustomPropertiesWindow::IsLineValid( CustomPropertyLine
* pLine
) const
1631 bool bIsValid
= true;
1632 pLine
->m_bTypeLostFocus
= false;
1633 auto nType
= pLine
->m_xTypeBox
->get_active_id().toInt32();
1634 OUString sValue
= pLine
->m_xValueEdit
->get_text();
1635 if ( sValue
.isEmpty() )
1638 sal_uInt32 nIndex
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
1639 if ( Custom_Type_Number
== nType
)
1640 // tdf#116214 Scientific format allows to use also standard numbers
1641 nIndex
= const_cast< SvNumberFormatter
& >(
1642 m_aNumberFormatter
).GetFormatIndex( NF_SCIENTIFIC_000E00
);
1643 else if ( Custom_Type_Date
== nType
)
1644 nIndex
= const_cast< SvNumberFormatter
& >(
1645 m_aNumberFormatter
).GetFormatIndex( NF_DATE_SYS_DDMMYYYY
);
1647 if ( nIndex
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
1649 sal_uInt32 nTemp
= nIndex
;
1650 double fDummy
= 0.0;
1651 bIsValid
= const_cast< SvNumberFormatter
& >(
1652 m_aNumberFormatter
).IsNumberFormat( sValue
, nIndex
, fDummy
);
1653 if ( bIsValid
&& nTemp
!= nIndex
)
1654 // sValue is a number but the format doesn't match the index
1661 void CustomPropertiesWindow::ValidateLine( CustomPropertyLine
* pLine
, bool bIsFromTypeBox
)
1663 if (pLine
&& !IsLineValid(pLine
))
1665 if ( bIsFromTypeBox
) // LoseFocus of TypeBox
1666 pLine
->m_bTypeLostFocus
= true;
1667 std::unique_ptr
<weld::MessageDialog
> xMessageBox(Application::CreateMessageDialog(&m_rBody
,
1668 VclMessageType::Question
, VclButtonsType::OkCancel
, SfxResId(STR_SFX_QUERY_WRONG_TYPE
)));
1669 if (xMessageBox
->run() == RET_OK
)
1670 pLine
->m_xTypeBox
->set_active_id(OUString::number(Custom_Type_Text
));
1672 pLine
->m_xValueEdit
->grab_focus();
1676 void CustomPropertiesWindow::SetVisibleLineCount(sal_uInt32 nCount
)
1678 while (GetExistingLineCount() < nCount
)
1684 void CustomPropertiesWindow::AddLine(const OUString
& sName
, Any
const & rAny
)
1686 m_aCustomProperties
.push_back(std::unique_ptr
<CustomProperty
>(new CustomProperty(sName
, rAny
)));
1687 ReloadLinesContent();
1690 void CustomPropertiesWindow::CreateNewLine()
1692 CustomPropertyLine
* pNewLine
= new CustomPropertyLine(this, &m_rBody
);
1693 pNewLine
->m_xNameBox
->set_accessible_relation_labeled_by(&m_rHeaderAccName
);
1694 pNewLine
->m_xNameBox
->set_accessible_name(m_rHeaderAccName
.get_label());
1695 pNewLine
->m_xTypeBox
->set_accessible_relation_labeled_by(&m_rHeaderAccType
);
1696 pNewLine
->m_xTypeBox
->set_accessible_name(m_rHeaderAccType
.get_label());
1697 pNewLine
->m_xValueEdit
->set_accessible_relation_labeled_by(&m_rHeaderAccValue
);
1698 pNewLine
->m_xValueEdit
->set_accessible_name(m_rHeaderAccValue
.get_label());
1700 m_aCustomPropertiesLines
.emplace_back( pNewLine
);
1702 // this breaks online's jsdialogbuilder
1703 if (!comphelper::LibreOfficeKit::isActive()){
1704 // for ui-testing. Distinguish the elements in the lines
1705 sal_uInt16 nSize
= m_aCustomPropertiesLines
.size();
1706 pNewLine
->m_xNameBox
->set_buildable_name(
1707 pNewLine
->m_xNameBox
->get_buildable_name() + OUString::number(nSize
));
1708 pNewLine
->m_xTypeBox
->set_buildable_name(
1709 pNewLine
->m_xTypeBox
->get_buildable_name() + OUString::number(nSize
));
1710 pNewLine
->m_xValueEdit
->set_buildable_name(
1711 pNewLine
->m_xValueEdit
->get_buildable_name() + OUString::number(nSize
));
1712 pNewLine
->m_xRemoveButton
->set_buildable_name(
1713 pNewLine
->m_xRemoveButton
->get_buildable_name() + OUString::number(nSize
));
1716 pNewLine
->DoTypeHdl(*pNewLine
->m_xTypeBox
);
1719 bool CustomPropertiesWindow::AreAllLinesValid() const
1722 for ( std::unique_ptr
<CustomPropertyLine
> const & pLine
: m_aCustomPropertiesLines
)
1724 if ( !IsLineValid( pLine
.get() ) )
1734 void CustomPropertiesWindow::ClearAllLines()
1736 for (auto& pLine
: m_aCustomPropertiesLines
)
1740 m_pCurrentLine
= nullptr;
1741 m_aCustomProperties
.clear();
1745 void CustomPropertiesWindow::DoScroll( sal_Int32 nNewPos
)
1747 StoreCustomProperties();
1748 m_nScrollPos
+= nNewPos
;
1749 ReloadLinesContent();
1752 Sequence
< beans::PropertyValue
> CustomPropertiesWindow::GetCustomProperties()
1754 StoreCustomProperties();
1756 Sequence
< beans::PropertyValue
> aPropertiesSeq(GetTotalLineCount());
1758 m_aCustomProperties
.begin(), m_aCustomProperties
.end(), aPropertiesSeq
.getArray(),
1759 [](const auto& el
) { return comphelper::makePropertyValue(el
->m_sName
, el
->m_aValue
); });
1761 return aPropertiesSeq
;
1764 CustomPropertiesTimeField::CustomPropertiesTimeField(std::unique_ptr
<weld::FormattedSpinButton
> xTimeField
)
1765 : m_xTimeField(std::move(xTimeField
))
1766 , m_xFormatter(new weld::TimeFormatter(*m_xTimeField
))
1769 m_xFormatter
->SetExtFormat(ExtTimeFieldFormat::LongDuration
);
1770 m_xFormatter
->EnableEmptyField(false);
1773 tools::Time
CustomPropertiesTimeField::get_value() const
1775 return m_xFormatter
->GetTime();
1778 void CustomPropertiesTimeField::set_value(const tools::Time
& rTime
)
1780 m_xFormatter
->SetTime(rTime
);
1783 CustomPropertiesTimeField::~CustomPropertiesTimeField()
1787 CustomPropertiesDateField::CustomPropertiesDateField(SvtCalendarBox
* pDateField
)
1788 : m_xDateField(pDateField
)
1790 DateTime
aDateTime(DateTime::SYSTEM
);
1791 m_xDateField
->set_date(aDateTime
);
1794 void CustomPropertiesDateField::set_visible(bool bVisible
)
1796 m_xDateField
->set_visible(bVisible
);
1799 Date
CustomPropertiesDateField::get_date() const
1801 return m_xDateField
->get_date();
1804 void CustomPropertiesDateField::set_date(const Date
& rDate
)
1806 m_xDateField
->set_date(rDate
);
1809 CustomPropertiesDateField::~CustomPropertiesDateField()
1813 void CustomPropertiesWindow::StoreCustomProperties()
1815 sal_uInt32 nDataModelPos
= GetCurrentDataModelPosition();
1817 for (sal_uInt32 i
= 0; nDataModelPos
+ i
< GetTotalLineCount() && i
< GetExistingLineCount(); i
++)
1819 CustomPropertyLine
* pLine
= m_aCustomPropertiesLines
[i
].get();
1821 OUString sPropertyName
= pLine
->m_xNameBox
->get_active_text();
1822 if (!sPropertyName
.isEmpty())
1824 m_aCustomProperties
[nDataModelPos
+ i
]->m_sName
= sPropertyName
;
1825 auto nType
= pLine
->m_xTypeBox
->get_active_id().toInt32();
1826 if (Custom_Type_Number
== nType
)
1829 sal_uInt32 nIndex
= m_aNumberFormatter
.GetFormatIndex(NF_NUMBER_SYSTEM
);
1830 bool bIsNum
= m_aNumberFormatter
.
1831 IsNumberFormat(pLine
->m_xValueEdit
->get_text(), nIndex
, nValue
);
1833 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= nValue
;
1835 else if (Custom_Type_Boolean
== nType
)
1837 bool bValue
= pLine
->m_xYesNoButton
->IsYesChecked();
1838 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= bValue
;
1840 else if (Custom_Type_Datetime
== nType
)
1842 Date aTmpDate
= pLine
->m_xDateField
->get_date();
1843 tools::Time aTmpTime
= pLine
->m_xTimeField
->get_value();
1844 util::DateTime
const aDateTime(aTmpTime
.GetNanoSec(),
1845 aTmpTime
.GetSec(), aTmpTime
.GetMin(), aTmpTime
.GetHour(),
1846 aTmpDate
.GetDay(), aTmpDate
.GetMonth(), aTmpDate
.GetYear(),
1847 pLine
->m_xTimeField
->m_isUTC
);
1848 if (pLine
->m_xDateField
->m_TZ
)
1850 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= util::DateTimeWithTimezone(
1851 aDateTime
, *pLine
->m_xDateField
->m_TZ
);
1855 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= aDateTime
;
1858 else if (Custom_Type_Date
== nType
)
1860 Date aTmpDate
= pLine
->m_xDateField
->get_date();
1861 util::Date
const aDate(aTmpDate
.GetDay(), aTmpDate
.GetMonth(),
1862 aTmpDate
.GetYear());
1863 if (pLine
->m_xDateField
->m_TZ
)
1865 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= util::DateWithTimezone(
1866 aDate
, *pLine
->m_xDateField
->m_TZ
);
1870 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= aDate
;
1873 else if (Custom_Type_Duration
== nType
)
1875 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= pLine
->m_xDurationField
->GetDuration();
1879 OUString
sValue(pLine
->m_xValueEdit
->get_text());
1880 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= sValue
;
1886 void CustomPropertiesWindow::SetCustomProperties(std::vector
< std::unique_ptr
<CustomProperty
> >&& rProperties
)
1888 m_aCustomProperties
= std::move(rProperties
);
1889 ReloadLinesContent();
1892 void CustomPropertiesWindow::ReloadLinesContent()
1894 double nTmpValue
= 0;
1895 bool bTmpValue
= false;
1897 util::DateTime aTmpDateTime
;
1898 util::Date aTmpDate
;
1899 util::DateTimeWithTimezone aTmpDateTimeTZ
;
1900 util::DateWithTimezone aTmpDateTZ
;
1901 util::Duration aTmpDuration
;
1902 SvtSysLocale aSysLocale
;
1903 const LocaleDataWrapper
& rLocaleWrapper
= aSysLocale
.GetLocaleData();
1904 CustomProperties nType
= Custom_Type_Unknown
;
1907 sal_uInt32 nDataModelPos
= GetCurrentDataModelPosition();
1910 for (; nDataModelPos
+ i
< GetTotalLineCount() && i
< GetExistingLineCount(); i
++)
1912 const OUString
& rName
= m_aCustomProperties
[nDataModelPos
+ i
]->m_sName
;
1913 const css::uno::Any
& rAny
= m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
;
1915 CustomPropertyLine
* pLine
= m_aCustomPropertiesLines
[i
].get();
1918 pLine
->m_xNameBox
->set_entry_text(rName
);
1919 pLine
->m_xLine
->show();
1921 if (!rAny
.hasValue())
1923 pLine
->m_xValueEdit
->set_text(OUString());
1925 else if (rAny
>>= nTmpValue
)
1927 sal_uInt32 nIndex
= m_aNumberFormatter
.GetFormatIndex(NF_NUMBER_SYSTEM
);
1928 sValue
= m_aNumberFormatter
.GetInputLineString(nTmpValue
, nIndex
);
1929 pLine
->m_xValueEdit
->set_text(sValue
);
1930 nType
= Custom_Type_Number
;
1932 else if (rAny
>>= bTmpValue
)
1934 sValue
= (bTmpValue
? rLocaleWrapper
.getTrueWord() : rLocaleWrapper
.getFalseWord());
1935 nType
= Custom_Type_Boolean
;
1937 else if (rAny
>>= sTmpValue
)
1939 pLine
->m_xValueEdit
->set_text(sTmpValue
);
1940 nType
= Custom_Type_Text
;
1942 else if (rAny
>>= aTmpDate
)
1944 pLine
->m_xDateField
->set_date(Date(aTmpDate
));
1945 nType
= Custom_Type_Date
;
1947 else if (rAny
>>= aTmpDateTime
)
1949 pLine
->m_xDateField
->set_date(Date(aTmpDateTime
));
1950 pLine
->m_xTimeField
->set_value(tools::Time(aTmpDateTime
));
1951 pLine
->m_xTimeField
->m_isUTC
= aTmpDateTime
.IsUTC
;
1952 nType
= Custom_Type_Datetime
;
1954 else if (rAny
>>= aTmpDateTZ
)
1956 pLine
->m_xDateField
->set_date(Date(aTmpDateTZ
.DateInTZ
.Day
,
1957 aTmpDateTZ
.DateInTZ
.Month
, aTmpDateTZ
.DateInTZ
.Year
));
1958 pLine
->m_xDateField
->m_TZ
= aTmpDateTZ
.Timezone
;
1959 nType
= Custom_Type_Date
;
1962 else if (rAny
>>= aTmpDateTimeTZ
)
1964 util::DateTime
const& rDT(aTmpDateTimeTZ
.DateTimeInTZ
);
1965 pLine
->m_xDateField
->set_date(Date(rDT
));
1966 pLine
->m_xTimeField
->set_value(tools::Time(rDT
));
1967 pLine
->m_xTimeField
->m_isUTC
= rDT
.IsUTC
;
1968 pLine
->m_xDateField
->m_TZ
= aTmpDateTimeTZ
.Timezone
;
1969 nType
= Custom_Type_Datetime
;
1971 else if (rAny
>>= aTmpDuration
)
1973 nType
= Custom_Type_Duration
;
1974 pLine
->m_xDurationField
->SetDuration(aTmpDuration
);
1977 if (Custom_Type_Boolean
== nType
)
1980 pLine
->m_xYesNoButton
->CheckYes();
1982 pLine
->m_xYesNoButton
->CheckNo();
1984 pLine
->m_xTypeBox
->set_active_id(OUString::number(nType
));
1986 pLine
->DoTypeHdl(*pLine
->m_xTypeBox
);
1989 // tdf#132667 - grab focus on the last inserted property
1990 if (i
> 0 && m_aCustomProperties
[nDataModelPos
+ i
- 1]->m_sName
.isEmpty())
1992 CustomPropertyLine
* pLine
= m_aCustomPropertiesLines
[i
- 1].get();
1993 pLine
->m_xNameBox
->grab_focus();
1996 while (nDataModelPos
+ i
>= GetTotalLineCount() && i
< GetExistingLineCount())
1998 CustomPropertyLine
* pLine
= m_aCustomPropertiesLines
[i
].get();
2004 CustomPropertiesControl::CustomPropertiesControl()
2009 void CustomPropertiesControl::Init(weld::Builder
& rBuilder
)
2011 m_xBox
= rBuilder
.weld_widget(u
"box"_ustr
);
2012 m_xBody
= rBuilder
.weld_container(u
"properties"_ustr
);
2014 m_xName
= rBuilder
.weld_label(u
"name"_ustr
);
2015 m_xType
= rBuilder
.weld_label(u
"type"_ustr
);
2016 m_xValue
= rBuilder
.weld_label(u
"value"_ustr
);
2017 m_xVertScroll
= rBuilder
.weld_scrolled_window(u
"scroll"_ustr
, true);
2018 m_xPropertiesWin
.reset(new CustomPropertiesWindow(*m_xBody
, *m_xName
, *m_xType
, *m_xValue
));
2020 m_xBox
->set_stack_background();
2021 m_xVertScroll
->show();
2023 std::unique_ptr
<CustomPropertyLine
> xNewLine(new CustomPropertyLine(m_xPropertiesWin
.get(), m_xBody
.get()));
2024 Size
aLineSize(xNewLine
->m_xLine
->get_preferred_size());
2025 m_xPropertiesWin
->SetLineHeight(aLineSize
.Height() + 6);
2026 m_xBody
->set_size_request(aLineSize
.Width() + 6, -1);
2027 auto nHeight
= aLineSize
.Height() * 8;
2028 m_xVertScroll
->set_size_request(-1, nHeight
+ 6);
2030 m_xPropertiesWin
->SetHeight(nHeight
);
2031 m_xVertScroll
->connect_size_allocate(LINK(this, CustomPropertiesControl
, ResizeHdl
));
2033 m_xName
->set_size_request(xNewLine
->m_xNameBox
->get_preferred_size().Width(), -1);
2034 m_xType
->set_size_request(xNewLine
->m_xTypeBox
->get_preferred_size().Width(), -1);
2035 m_xValue
->set_size_request(xNewLine
->m_xValueEdit
->get_preferred_size().Width(), -1);
2037 m_xBody
->move(xNewLine
->m_xLine
.get(), nullptr);
2040 m_xPropertiesWin
->SetRemovedHdl( LINK( this, CustomPropertiesControl
, RemovedHdl
) );
2042 m_xVertScroll
->vadjustment_set_lower(0);
2043 m_xVertScroll
->vadjustment_set_upper(0);
2044 m_xVertScroll
->vadjustment_set_page_size(0xFFFF);
2046 Link
<weld::ScrolledWindow
&,void> aScrollLink
= LINK( this, CustomPropertiesControl
, ScrollHdl
);
2047 m_xVertScroll
->connect_vadjustment_changed(aScrollLink
);
2049 ResizeHdl(Size(-1, nHeight
));
2052 IMPL_LINK(CustomPropertiesControl
, ResizeHdl
, const Size
&, rSize
, void)
2054 int nHeight
= rSize
.Height() - 6;
2055 if (nHeight
== m_xPropertiesWin
->GetHeight())
2057 m_xPropertiesWin
->SetHeight(nHeight
);
2058 sal_Int32 nScrollOffset
= m_xPropertiesWin
->GetLineHeight();
2059 sal_Int32 nVisibleEntries
= nHeight
/ nScrollOffset
;
2060 m_xPropertiesWin
->SetVisibleLineCount( nVisibleEntries
);
2061 m_xVertScroll
->vadjustment_set_page_increment( nVisibleEntries
- 1 );
2062 m_xVertScroll
->vadjustment_set_page_size( nVisibleEntries
);
2063 m_xPropertiesWin
->ReloadLinesContent();
2066 CustomPropertiesControl::~CustomPropertiesControl()
2070 IMPL_LINK( CustomPropertiesControl
, ScrollHdl
, weld::ScrolledWindow
&, rScrollBar
, void )
2072 sal_Int32 nOffset
= m_xPropertiesWin
->GetLineHeight();
2073 int nThumbPos
= rScrollBar
.vadjustment_get_value();
2074 nOffset
*= ( m_nThumbPos
- nThumbPos
);
2075 m_nThumbPos
= nThumbPos
;
2076 m_xPropertiesWin
->DoScroll( nOffset
);
2079 IMPL_LINK_NOARG(CustomPropertiesControl
, RemovedHdl
, void*, void)
2081 auto nLineCount
= m_xPropertiesWin
->GetTotalLineCount();
2082 m_xVertScroll
->vadjustment_set_upper(nLineCount
+ 1);
2083 if (m_xPropertiesWin
->GetTotalLineCount() > m_xPropertiesWin
->GetExistingLineCount())
2085 m_xVertScroll
->vadjustment_set_value(nLineCount
- 1);
2086 ScrollHdl(*m_xVertScroll
);
2090 void CustomPropertiesControl::AddLine( Any
const & rAny
)
2092 m_xPropertiesWin
->AddLine( OUString(), rAny
);
2093 auto nLineCount
= m_xPropertiesWin
->GetTotalLineCount();
2094 m_xVertScroll
->vadjustment_set_upper(nLineCount
+ 1);
2095 if (m_xPropertiesWin
->GetHeight() < nLineCount
* m_xPropertiesWin
->GetLineHeight())
2097 m_xVertScroll
->vadjustment_set_value(nLineCount
+ 1);
2098 ScrollHdl(*m_xVertScroll
);
2102 void CustomPropertiesControl::SetCustomProperties(std::vector
< std::unique_ptr
<CustomProperty
> >&& rProperties
)
2104 m_xPropertiesWin
->SetCustomProperties(std::move(rProperties
));
2105 auto nLineCount
= m_xPropertiesWin
->GetTotalLineCount();
2106 m_xVertScroll
->vadjustment_set_upper(nLineCount
+ 1);
2109 // class SfxCustomPropertiesPage -----------------------------------------
2110 SfxCustomPropertiesPage::SfxCustomPropertiesPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rItemSet
)
2111 : SfxTabPage(pPage
, pController
, u
"sfx/ui/custominfopage.ui"_ustr
, u
"CustomInfoPage"_ustr
, &rItemSet
)
2112 , m_xPropertiesCtrl(new CustomPropertiesControl
)
2113 , m_xAdd(m_xBuilder
->weld_button(u
"add"_ustr
))
2115 m_xPropertiesCtrl
->Init(*m_xBuilder
);
2116 m_xAdd
->connect_clicked(LINK(this, SfxCustomPropertiesPage
, AddHdl
));
2119 SfxCustomPropertiesPage::~SfxCustomPropertiesPage()
2121 m_xPropertiesCtrl
.reset();
2124 IMPL_LINK_NOARG(SfxCustomPropertiesPage
, AddHdl
, weld::Button
&, void)
2126 // tdf#115853: reload current lines before adding a brand new one
2127 // indeed the info are deleted by ClearCustomProperties
2128 // each time SfxDocumentInfoItem destructor is called
2129 SfxDocumentInfoItem pInfo
;
2130 const Sequence
< beans::PropertyValue
> aPropertySeq
= m_xPropertiesCtrl
->GetCustomProperties();
2131 for ( const auto& rProperty
: aPropertySeq
)
2133 if ( !rProperty
.Name
.isEmpty() )
2135 pInfo
.AddCustomProperty( rProperty
.Name
, rProperty
.Value
);
2140 m_xPropertiesCtrl
->AddLine(aAny
);
2143 bool SfxCustomPropertiesPage::FillItemSet( SfxItemSet
* rSet
)
2145 const SfxDocumentInfoItem
* pItem
= nullptr;
2146 SfxDocumentInfoItem
* pInfo
= nullptr;
2147 bool bMustDelete
= false;
2149 if (const SfxItemSet
* pItemSet
= GetDialogExampleSet())
2151 pItem
= pItemSet
->GetItemIfSet(SID_DOCINFO
);
2153 pInfo
= const_cast<SfxDocumentInfoItem
*>(&rSet
->Get( SID_DOCINFO
));
2157 pInfo
= new SfxDocumentInfoItem( *pItem
);
2163 // If it's a CMIS document, we can't save custom properties
2164 if ( pInfo
->isCmisDocument( ) )
2171 pInfo
->ClearCustomProperties();
2172 const Sequence
< beans::PropertyValue
> aPropertySeq
= m_xPropertiesCtrl
->GetCustomProperties();
2173 for ( const auto& rProperty
: aPropertySeq
)
2175 if ( !rProperty
.Name
.isEmpty() )
2176 pInfo
->AddCustomProperty( rProperty
.Name
, rProperty
.Value
);
2189 void SfxCustomPropertiesPage::Reset( const SfxItemSet
* rItemSet
)
2191 m_xPropertiesCtrl
->ClearAllLines();
2192 const SfxDocumentInfoItem
& rInfoItem
= rItemSet
->Get(SID_DOCINFO
);
2193 std::vector
< std::unique_ptr
<CustomProperty
> > aCustomProps
= rInfoItem
.GetCustomProperties();
2194 // tdf#123919 - sort custom document properties
2195 auto const sort
= comphelper::string::NaturalStringSorter(
2196 comphelper::getProcessComponentContext(),
2197 Application::GetSettings().GetLanguageTag().getLocale());
2198 std::sort(aCustomProps
.begin(), aCustomProps
.end(),
2199 [&sort
](const std::unique_ptr
<CustomProperty
>& rLHS
,
2200 const std::unique_ptr
<CustomProperty
>& rRHS
) {
2201 return sort
.compare(rLHS
->m_sName
, rRHS
->m_sName
) < 0;
2203 m_xPropertiesCtrl
->SetCustomProperties(std::move(aCustomProps
));
2206 DeactivateRC
SfxCustomPropertiesPage::DeactivatePage( SfxItemSet
* /*pSet*/ )
2208 DeactivateRC nRet
= DeactivateRC::LeavePage
;
2209 if ( !m_xPropertiesCtrl
->AreAllLinesValid() )
2210 nRet
= DeactivateRC::KeepPage
;
2214 std::unique_ptr
<SfxTabPage
> SfxCustomPropertiesPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
* rItemSet
)
2216 return std::make_unique
<SfxCustomPropertiesPage
>(pPage
, pController
, *rItemSet
);
2219 CmisValue::CmisValue(weld::Widget
* pParent
, const OUString
& aStr
)
2220 : m_xBuilder(Application::CreateBuilder(pParent
, u
"sfx/ui/cmisline.ui"_ustr
))
2221 , m_xFrame(m_xBuilder
->weld_frame(u
"CmisFrame"_ustr
))
2222 , m_xValueEdit(m_xBuilder
->weld_entry(u
"value"_ustr
))
2224 m_xValueEdit
->show();
2225 m_xValueEdit
->set_text(aStr
);
2228 CmisDateTime::CmisDateTime(weld::Widget
* pParent
, const util::DateTime
& aDateTime
)
2229 : m_xBuilder(Application::CreateBuilder(pParent
, u
"sfx/ui/cmisline.ui"_ustr
))
2230 , m_xFrame(m_xBuilder
->weld_frame(u
"CmisFrame"_ustr
))
2231 , m_xDateField(new SvtCalendarBox(m_xBuilder
->weld_menu_button(u
"date"_ustr
)))
2232 , m_xTimeField(m_xBuilder
->weld_formatted_spin_button(u
"time"_ustr
))
2233 , m_xFormatter(new weld::TimeFormatter(*m_xTimeField
))
2235 m_xFormatter
->SetExtFormat(ExtTimeFieldFormat::LongDuration
);
2236 m_xFormatter
->EnableEmptyField(false);
2238 m_xDateField
->show();
2239 m_xTimeField
->show();
2240 m_xDateField
->set_date(Date(aDateTime
));
2241 m_xFormatter
->SetTime(tools::Time(aDateTime
));
2244 CmisYesNo::CmisYesNo(weld::Widget
* pParent
, bool bValue
)
2245 : m_xBuilder(Application::CreateBuilder(pParent
, u
"sfx/ui/cmisline.ui"_ustr
))
2246 , m_xFrame(m_xBuilder
->weld_frame(u
"CmisFrame"_ustr
))
2247 , m_xYesButton(m_xBuilder
->weld_radio_button(u
"yes"_ustr
))
2248 , m_xNoButton(m_xBuilder
->weld_radio_button(u
"no"_ustr
))
2250 m_xYesButton
->show();
2251 m_xNoButton
->show();
2253 m_xYesButton
->set_active(true);
2255 m_xNoButton
->set_active(true);
2258 // struct CmisPropertyLine ---------------------------------------------
2259 CmisPropertyLine::CmisPropertyLine(weld::Widget
* pParent
)
2260 : m_xBuilder(Application::CreateBuilder(pParent
, u
"sfx/ui/cmisline.ui"_ustr
))
2261 , m_sType(CMIS_TYPE_STRING
)
2262 , m_bUpdatable(false)
2263 , m_bRequired(false)
2264 , m_bMultiValued(false)
2265 , m_bOpenChoice(false)
2266 , m_xFrame(m_xBuilder
->weld_frame(u
"CmisFrame"_ustr
))
2267 , m_xName(m_xBuilder
->weld_label(u
"name"_ustr
))
2268 , m_xType(m_xBuilder
->weld_label(u
"type"_ustr
))
2270 m_xFrame
->set_sensitive(true);
2273 CmisPropertyLine::~CmisPropertyLine( )
2277 // class CmisPropertiesWindow -----------------------------------------
2279 CmisPropertiesWindow::CmisPropertiesWindow(std::unique_ptr
<weld::Container
> xParent
)
2280 : m_xBox(std::move(xParent
))
2281 , m_aNumberFormatter(::comphelper::getProcessComponentContext(),
2282 Application::GetSettings().GetLanguageTag().getLanguageType())
2286 CmisPropertiesWindow::~CmisPropertiesWindow()
2290 void CmisPropertiesWindow::ClearAllLines()
2292 m_aCmisPropertiesLines
.clear();
2295 void CmisPropertiesWindow::AddLine( const OUString
& sId
, const OUString
& sName
,
2296 const OUString
& sType
, const bool bUpdatable
,
2297 const bool bRequired
, const bool bMultiValued
,
2298 const bool bOpenChoice
, Any
& /*aChoices*/, Any
const & rAny
)
2300 std::unique_ptr
<CmisPropertyLine
> pNewLine(new CmisPropertyLine(m_xBox
.get()));
2302 pNewLine
->m_sId
= sId
;
2303 pNewLine
->m_sType
= sType
;
2304 pNewLine
->m_bUpdatable
= bUpdatable
;
2305 pNewLine
->m_bRequired
= bRequired
;
2306 pNewLine
->m_bMultiValued
= bMultiValued
;
2307 pNewLine
->m_bOpenChoice
= bOpenChoice
;
2309 if ( sType
== CMIS_TYPE_INTEGER
)
2311 Sequence
< sal_Int64
> seqValue
;
2313 sal_uInt32 nIndex
= m_aNumberFormatter
.GetFormatIndex( NF_NUMBER_SYSTEM
);
2314 for (const auto& rValue
: seqValue
)
2316 OUString sValue
= m_aNumberFormatter
.GetInputLineString( rValue
, nIndex
);
2317 std::unique_ptr
<CmisValue
> pValue(new CmisValue(m_xBox
.get(), sValue
));
2318 pValue
->m_xValueEdit
->set_editable(bUpdatable
);
2319 pNewLine
->m_aValues
.push_back( std::move(pValue
) );
2322 else if ( sType
== CMIS_TYPE_DECIMAL
)
2324 Sequence
< double > seqValue
;
2326 sal_uInt32 nIndex
= m_aNumberFormatter
.GetFormatIndex( NF_NUMBER_SYSTEM
);
2327 for (const auto& rValue
: seqValue
)
2329 OUString sValue
= m_aNumberFormatter
.GetInputLineString( rValue
, nIndex
);
2330 std::unique_ptr
<CmisValue
> pValue(new CmisValue(m_xBox
.get(), sValue
));
2331 pValue
->m_xValueEdit
->set_editable(bUpdatable
);
2332 pNewLine
->m_aValues
.push_back( std::move(pValue
) );
2336 else if ( sType
== CMIS_TYPE_BOOL
)
2338 Sequence
<sal_Bool
> seqValue
;
2340 for (const auto& rValue
: seqValue
)
2342 std::unique_ptr
<CmisYesNo
> pYesNo(new CmisYesNo(m_xBox
.get(), rValue
));
2343 pYesNo
->m_xYesButton
->set_sensitive( bUpdatable
);
2344 pYesNo
->m_xNoButton
->set_sensitive( bUpdatable
);
2345 pNewLine
->m_aYesNos
.push_back( std::move(pYesNo
) );
2348 else if ( sType
== CMIS_TYPE_STRING
)
2350 Sequence
< OUString
> seqValue
;
2352 for (const auto& rValue
: seqValue
)
2354 std::unique_ptr
<CmisValue
> pValue(new CmisValue(m_xBox
.get(), rValue
));
2355 pValue
->m_xValueEdit
->set_editable(bUpdatable
);
2356 pNewLine
->m_aValues
.push_back( std::move(pValue
) );
2359 else if ( sType
== CMIS_TYPE_DATETIME
)
2361 Sequence
< util::DateTime
> seqValue
;
2363 for (const auto& rValue
: seqValue
)
2365 std::unique_ptr
<CmisDateTime
> pDateTime(new CmisDateTime(m_xBox
.get(), rValue
));
2366 pDateTime
->m_xDateField
->set_sensitive(bUpdatable
);
2367 pDateTime
->m_xTimeField
->set_sensitive(bUpdatable
);
2368 pNewLine
->m_aDateTimes
.push_back( std::move(pDateTime
) );
2371 pNewLine
->m_xName
->set_label( sName
);
2372 pNewLine
->m_xName
->show();
2373 pNewLine
->m_xType
->set_label( sType
);
2374 pNewLine
->m_xType
->show();
2376 m_aCmisPropertiesLines
.push_back( std::move(pNewLine
) );
2379 Sequence
< document::CmisProperty
> CmisPropertiesWindow::GetCmisProperties() const
2381 Sequence
< document::CmisProperty
> aPropertiesSeq( m_aCmisPropertiesLines
.size() );
2382 auto aPropertiesSeqRange
= asNonConstRange(aPropertiesSeq
);
2384 for ( auto& rxLine
: m_aCmisPropertiesLines
)
2386 CmisPropertyLine
* pLine
= rxLine
.get();
2388 aPropertiesSeqRange
[i
].Id
= pLine
->m_sId
;
2389 aPropertiesSeqRange
[i
].Type
= pLine
->m_sType
;
2390 aPropertiesSeqRange
[i
].Updatable
= pLine
->m_bUpdatable
;
2391 aPropertiesSeqRange
[i
].Required
= pLine
->m_bRequired
;
2392 aPropertiesSeqRange
[i
].OpenChoice
= pLine
->m_bOpenChoice
;
2393 aPropertiesSeqRange
[i
].MultiValued
= pLine
->m_bMultiValued
;
2395 OUString sPropertyName
= pLine
->m_xName
->get_label();
2396 if ( !sPropertyName
.isEmpty() )
2398 aPropertiesSeqRange
[i
].Name
= sPropertyName
;
2399 OUString sType
= pLine
->m_xType
->get_label();
2400 if ( CMIS_TYPE_DECIMAL
== sType
)
2402 sal_uInt32 nIndex
= const_cast< SvNumberFormatter
& >(
2403 m_aNumberFormatter
).GetFormatIndex( NF_NUMBER_SYSTEM
);
2404 Sequence
< double > seqValue( pLine
->m_aValues
.size( ) );
2405 auto seqValueRange
= asNonConstRange(seqValue
);
2407 for ( const auto& rxValue
: pLine
->m_aValues
)
2409 double dValue
= 0.0;
2410 OUString
sValue( rxValue
->m_xValueEdit
->get_text() );
2411 bool bIsNum
= const_cast< SvNumberFormatter
& >( m_aNumberFormatter
).
2412 IsNumberFormat( sValue
, nIndex
, dValue
);
2414 seqValueRange
[k
] = dValue
;
2417 aPropertiesSeqRange
[i
].Value
<<= seqValue
;
2419 else if ( CMIS_TYPE_INTEGER
== sType
)
2421 sal_uInt32 nIndex
= const_cast< SvNumberFormatter
& >(
2422 m_aNumberFormatter
).GetFormatIndex( NF_NUMBER_SYSTEM
);
2423 Sequence
< sal_Int64
> seqValue( pLine
->m_aValues
.size( ) );
2424 auto seqValueRange
= asNonConstRange(seqValue
);
2426 for ( const auto& rxValue
: pLine
->m_aValues
)
2429 OUString
sValue( rxValue
->m_xValueEdit
->get_text() );
2430 bool bIsNum
= const_cast< SvNumberFormatter
& >( m_aNumberFormatter
).
2431 IsNumberFormat( sValue
, nIndex
, dValue
);
2433 seqValueRange
[k
] = static_cast<sal_Int64
>(dValue
);
2436 aPropertiesSeqRange
[i
].Value
<<= seqValue
;
2438 else if ( CMIS_TYPE_BOOL
== sType
)
2440 Sequence
<sal_Bool
> seqValue( pLine
->m_aYesNos
.size( ) );
2441 sal_Bool
* pseqValue
= seqValue
.getArray();
2443 for ( const auto& rxYesNo
: pLine
->m_aYesNos
)
2445 bool bValue
= rxYesNo
->m_xYesButton
->get_active();
2446 pseqValue
[k
] = bValue
;
2449 aPropertiesSeqRange
[i
].Value
<<= seqValue
;
2452 else if ( CMIS_TYPE_DATETIME
== sType
)
2454 Sequence
< util::DateTime
> seqValue( pLine
->m_aDateTimes
.size( ) );
2455 auto seqValueRange
= asNonConstRange(seqValue
);
2457 for ( const auto& rxDateTime
: pLine
->m_aDateTimes
)
2459 Date aTmpDate
= rxDateTime
->m_xDateField
->get_date();
2460 tools::Time aTmpTime
= rxDateTime
->m_xFormatter
->GetTime();
2461 util::DateTime
aDateTime( aTmpTime
.GetNanoSec(), aTmpTime
.GetSec(),
2462 aTmpTime
.GetMin(), aTmpTime
.GetHour(),
2463 aTmpDate
.GetDay(), aTmpDate
.GetMonth(),
2464 aTmpDate
.GetYear(), true );
2465 seqValueRange
[k
] = aDateTime
;
2468 aPropertiesSeqRange
[i
].Value
<<= seqValue
;
2472 Sequence
< OUString
> seqValue( pLine
->m_aValues
.size( ) );
2473 auto seqValueRange
= asNonConstRange(seqValue
);
2475 for ( const auto& rxValue
: pLine
->m_aValues
)
2477 seqValueRange
[k
] = rxValue
->m_xValueEdit
->get_text();
2480 aPropertiesSeqRange
[i
].Value
<<= seqValue
;
2486 return aPropertiesSeq
;
2489 CmisPropertiesControl::CmisPropertiesControl(weld::Builder
& rBuilder
)
2490 : m_aPropertiesWin(rBuilder
.weld_container(u
"CmisWindow"_ustr
))
2491 , m_xScrolledWindow(rBuilder
.weld_scrolled_window(u
"CmisScroll"_ustr
))
2493 // set height to something small and force it to take the size
2494 // dictated by the other pages
2495 m_xScrolledWindow
->set_size_request(-1, 42);
2498 void CmisPropertiesControl::ClearAllLines()
2500 m_aPropertiesWin
.ClearAllLines();
2503 void CmisPropertiesControl::AddLine( const OUString
& sId
, const OUString
& sName
,
2504 const OUString
& sType
, const bool bUpdatable
,
2505 const bool bRequired
, const bool bMultiValued
,
2506 const bool bOpenChoice
, Any
& aChoices
, Any
const & rAny
2509 m_aPropertiesWin
.AddLine( sId
, sName
, sType
, bUpdatable
, bRequired
, bMultiValued
,
2510 bOpenChoice
, aChoices
, rAny
);
2513 // class SfxCmisPropertiesPage -----------------------------------------
2514 SfxCmisPropertiesPage::SfxCmisPropertiesPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rItemSet
)
2515 : SfxTabPage(pPage
, pController
, u
"sfx/ui/cmisinfopage.ui"_ustr
, u
"CmisInfoPage"_ustr
, &rItemSet
)
2516 , m_xPropertiesCtrl(new CmisPropertiesControl(*m_xBuilder
))
2520 SfxCmisPropertiesPage::~SfxCmisPropertiesPage()
2522 m_xPropertiesCtrl
.reset();
2525 bool SfxCmisPropertiesPage::FillItemSet( SfxItemSet
* rSet
)
2527 const SfxDocumentInfoItem
* pItem
= nullptr;
2528 SfxDocumentInfoItem
* pInfo
= nullptr;
2529 bool bMustDelete
= false;
2531 if (const SfxItemSet
* pItemSet
= GetDialogExampleSet())
2533 pItem
= pItemSet
->GetItemIfSet(SID_DOCINFO
);
2535 pInfo
= const_cast<SfxDocumentInfoItem
*>(&rSet
->Get( SID_DOCINFO
));
2539 pInfo
= new SfxDocumentInfoItem( *pItem
);
2543 sal_Int32 modifiedNum
= 0;
2546 Sequence
< document::CmisProperty
> aOldProps
= pInfo
->GetCmisProperties( );
2547 Sequence
< document::CmisProperty
> aNewProps
= m_xPropertiesCtrl
->GetCmisProperties();
2549 std::vector
< document::CmisProperty
> changedProps
;
2550 for ( sal_Int32 i
= 0; i
< aNewProps
.getLength( ); ++i
)
2552 if ( aOldProps
[i
].Updatable
&& !aNewProps
[i
].Id
.isEmpty( ) )
2554 if ( aOldProps
[i
].Type
== CMIS_TYPE_DATETIME
)
2556 Sequence
< util::DateTime
> oldValue
;
2557 aOldProps
[i
].Value
>>= oldValue
;
2558 // We only edit hours and minutes
2559 // don't compare NanoSeconds and Seconds
2560 for ( auto& rDateTime
: asNonConstRange(oldValue
) )
2562 rDateTime
.NanoSeconds
= 0;
2563 rDateTime
.Seconds
= 0;
2565 Sequence
< util::DateTime
> newValue
;
2566 aNewProps
[i
].Value
>>= newValue
;
2567 if ( oldValue
!= newValue
)
2570 changedProps
.push_back( aNewProps
[i
] );
2573 else if ( aOldProps
[i
].Value
!= aNewProps
[i
].Value
)
2576 changedProps
.push_back( aNewProps
[i
] );
2580 Sequence
< document::CmisProperty
> aModifiedProps( comphelper::containerToSequence(changedProps
) );
2581 pInfo
->SetCmisProperties( aModifiedProps
);
2582 rSet
->Put( *pInfo
);
2590 void SfxCmisPropertiesPage::Reset( const SfxItemSet
* rItemSet
)
2592 m_xPropertiesCtrl
->ClearAllLines();
2593 const SfxDocumentInfoItem
& rInfoItem
= rItemSet
->Get(SID_DOCINFO
);
2594 uno::Sequence
< document::CmisProperty
> aCmisProps
= rInfoItem
.GetCmisProperties();
2595 for ( auto& rCmisProp
: asNonConstRange(aCmisProps
) )
2597 m_xPropertiesCtrl
->AddLine(rCmisProp
.Id
,
2600 rCmisProp
.Updatable
,
2602 rCmisProp
.MultiValued
,
2603 rCmisProp
.OpenChoice
,
2609 DeactivateRC
SfxCmisPropertiesPage::DeactivatePage( SfxItemSet
* /*pSet*/ )
2611 return DeactivateRC::LeavePage
;
2614 std::unique_ptr
<SfxTabPage
> SfxCmisPropertiesPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
* rItemSet
)
2616 return std::make_unique
<SfxCmisPropertiesPage
>(pPage
, pController
, *rItemSet
);
2619 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */