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/debug.hxx>
23 #include <tools/urlobj.hxx>
25 #include <vcl/svapp.hxx>
26 #include <vcl/weld.hxx>
27 #include <vcl/weldutils.hxx>
28 #include <unotools/datetime.hxx>
29 #include <unotools/localedatawrapper.hxx>
30 #include <unotools/cmdoptions.hxx>
31 #include <comphelper/processfactory.hxx>
32 #include <comphelper/propertyvalue.hxx>
33 #include <comphelper/stl_types.hxx>
34 #include <comphelper/xmlsechelper.hxx>
35 #include <unotools/useroptions.hxx>
36 #include <svtools/ctrlbox.hxx>
37 #include <svtools/imagemgr.hxx>
38 #include <sal/log.hxx>
39 #include <osl/diagnose.h>
40 #include <osl/file.hxx>
41 #include <comphelper/lok.hxx>
45 #include <comphelper/sequence.hxx>
46 #include <comphelper/string.hxx>
47 #include <com/sun/star/security/DocumentSignatureInformation.hpp>
48 #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
49 #include <unotools/syslocale.hxx>
50 #include <rtl/math.hxx>
51 #include <com/sun/star/beans/PropertyAttribute.hpp>
52 #include <com/sun/star/beans/XPropertyContainer.hpp>
53 #include <com/sun/star/beans/XPropertySet.hpp>
54 #include <com/sun/star/util/DateTime.hpp>
55 #include <com/sun/star/util/Date.hpp>
56 #include <com/sun/star/util/DateTimeWithTimezone.hpp>
57 #include <com/sun/star/util/DateWithTimezone.hpp>
58 #include <com/sun/star/util/Duration.hpp>
59 #include <com/sun/star/document/XDocumentProperties.hpp>
60 #include <com/sun/star/document/CmisProperty.hpp>
61 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
63 #include <vcl/timer.hxx>
64 #include <vcl/settings.hxx>
65 #include <sfx2/sfxresid.hxx>
66 #include <sfx2/frame.hxx>
67 #include <sfx2/filedlghelper.hxx>
68 #include <sfx2/dinfdlg.hxx>
69 #include <sfx2/sfxsids.hrc>
71 #include <sfx2/objsh.hxx>
72 #include <sfx2/docfile.hxx>
73 #include <vcl/abstdlg.hxx>
75 #include <documentfontsdialog.hxx>
76 #include <dinfdlg.hrc>
77 #include <sfx2/strings.hrc>
78 #include <strings.hxx>
79 #include <comphelper/diagnose_ex.hxx>
80 #include "securitypage.hxx"
84 using namespace ::com::sun::star
;
85 using namespace ::com::sun::star::uno
;
90 css::uno::Any m_aValue
;
92 CustomProperty( OUString sName
, css::uno::Any aValue
) :
93 m_sName(std::move( sName
)), m_aValue(std::move( aValue
)) {}
95 bool operator==(const CustomProperty
& rProp
) const
97 return m_sName
== rProp
.m_sName
&& m_aValue
== rProp
.m_aValue
;
101 SfxPoolItem
* SfxDocumentInfoItem::CreateDefault() { return new SfxDocumentInfoItem
; }
105 OUString
CreateSizeText( sal_Int64 nSize
)
107 OUString aUnitStr
= " " + SfxResId(STR_BYTES
);
108 sal_Int64 nSize1
= nSize
;
109 sal_Int64 nSize2
= nSize1
;
110 sal_Int64 nMega
= 1024 * 1024;
111 sal_Int64 nGiga
= nMega
* 1024;
112 double fSize
= nSize
;
115 if ( nSize1
>= 10000 && nSize1
< nMega
)
118 aUnitStr
= " " + SfxResId(STR_KB
);
122 else if ( nSize1
>= nMega
&& nSize1
< nGiga
)
125 aUnitStr
= " " + SfxResId(STR_MB
);
129 else if ( nSize1
>= nGiga
)
132 aUnitStr
= " " + SfxResId(STR_GB
);
136 const SvtSysLocale aSysLocale
;
137 const LocaleDataWrapper
& rLocaleWrapper
= aSysLocale
.GetLocaleData();
138 OUString aSizeStr
= rLocaleWrapper
.getNum( nSize1
, 0 ) + aUnitStr
;
139 if ( nSize1
< nSize2
)
141 aSizeStr
= ::rtl::math::doubleToUString( fSize
,
142 rtl_math_StringFormat_F
, nDec
,
143 rLocaleWrapper
.getNumDecimalSep()[0] )
146 + rLocaleWrapper
.getNum( nSize2
, 0 )
148 + SfxResId(STR_BYTES
)
154 OUString
ConvertDateTime_Impl( std::u16string_view rName
,
155 const util::DateTime
& uDT
, const LocaleDataWrapper
& rWrapper
)
159 static const OUStringLiteral
aDelim( u
", " );
160 OUString aStr
= rWrapper
.getDate( aD
)
162 + rWrapper
.getTime( aT
);
163 std::u16string_view aAuthor
= comphelper::string::stripStart(rName
, ' ');
164 if (!aAuthor
.empty())
166 aStr
+= aDelim
+ aAuthor
;
174 SfxDocumentInfoItem::SfxDocumentInfoItem()
176 , m_isAutoloadEnabled(false)
178 , m_EditingDuration(0)
179 , m_bHasTemplate( true )
180 , m_bDeleteUserData( false )
181 , m_bUseUserData( true )
182 , m_bUseThumbnailSave( true )
186 SfxDocumentInfoItem::SfxDocumentInfoItem( const OUString
& rFile
,
187 const uno::Reference
<document::XDocumentProperties
>& i_xDocProps
,
188 const uno::Sequence
<document::CmisProperty
>& i_cmisProps
,
189 bool bIs
, bool _bIs
)
190 : SfxStringItem( SID_DOCINFO
, rFile
)
191 , m_AutoloadDelay( i_xDocProps
->getAutoloadSecs() )
192 , m_AutoloadURL( i_xDocProps
->getAutoloadURL() )
193 , m_isAutoloadEnabled( (m_AutoloadDelay
> 0) || !m_AutoloadURL
.isEmpty() )
194 , m_DefaultTarget( i_xDocProps
->getDefaultTarget() )
195 , m_TemplateName( i_xDocProps
->getTemplateName() )
196 , m_Author( i_xDocProps
->getAuthor() )
197 , m_CreationDate( i_xDocProps
->getCreationDate() )
198 , m_ModifiedBy( i_xDocProps
->getModifiedBy() )
199 , m_ModificationDate( i_xDocProps
->getModificationDate() )
200 , m_PrintedBy( i_xDocProps
->getPrintedBy() )
201 , m_PrintDate( i_xDocProps
->getPrintDate() )
202 , m_EditingCycles( i_xDocProps
->getEditingCycles() )
203 , m_EditingDuration( i_xDocProps
->getEditingDuration() )
204 , m_Description( i_xDocProps
->getDescription() )
205 , m_Keywords( ::comphelper::string::convertCommaSeparated(
206 i_xDocProps
->getKeywords()) )
207 , m_Subject( i_xDocProps
->getSubject() )
208 , m_Title( i_xDocProps
->getTitle() )
209 , m_bHasTemplate( true )
210 , m_bDeleteUserData( false )
211 , m_bUseUserData( bIs
)
212 , m_bUseThumbnailSave( _bIs
)
216 Reference
< beans::XPropertyContainer
> xContainer
= i_xDocProps
->getUserDefinedProperties();
217 if ( xContainer
.is() )
219 Reference
< beans::XPropertySet
> xSet( xContainer
, UNO_QUERY
);
220 const Sequence
< beans::Property
> lProps
= xSet
->getPropertySetInfo()->getProperties();
221 for ( const beans::Property
& rProp
: lProps
)
223 // "fix" property? => not a custom property => ignore it!
224 if (!(rProp
.Attributes
& css::beans::PropertyAttribute::REMOVABLE
))
226 SAL_WARN( "sfx.dialog", "non-removable user-defined property?");
230 uno::Any aValue
= xSet
->getPropertyValue(rProp
.Name
);
231 AddCustomProperty( rProp
.Name
, aValue
);
235 // get CMIS properties
236 m_aCmisProperties
= i_cmisProps
;
238 catch ( Exception
& ) {}
242 SfxDocumentInfoItem::SfxDocumentInfoItem( const SfxDocumentInfoItem
& rItem
)
243 : SfxStringItem( rItem
)
244 , m_AutoloadDelay( rItem
.getAutoloadDelay() )
245 , m_AutoloadURL( rItem
.getAutoloadURL() )
246 , m_isAutoloadEnabled( rItem
.isAutoloadEnabled() )
247 , m_DefaultTarget( rItem
.getDefaultTarget() )
248 , m_TemplateName( rItem
.getTemplateName() )
249 , m_Author( rItem
.getAuthor() )
250 , m_CreationDate( rItem
.getCreationDate() )
251 , m_ModifiedBy( rItem
.getModifiedBy() )
252 , m_ModificationDate( rItem
.getModificationDate() )
253 , m_PrintedBy( rItem
.getPrintedBy() )
254 , m_PrintDate( rItem
.getPrintDate() )
255 , m_EditingCycles( rItem
.getEditingCycles() )
256 , m_EditingDuration( rItem
.getEditingDuration() )
257 , m_Description( rItem
.getDescription() )
258 , m_Keywords( rItem
.getKeywords() )
259 , m_Subject( rItem
.getSubject() )
260 , m_Title( rItem
.getTitle() )
261 , m_bHasTemplate( rItem
.m_bHasTemplate
)
262 , m_bDeleteUserData( rItem
.m_bDeleteUserData
)
263 , m_bUseUserData( rItem
.m_bUseUserData
)
264 , m_bUseThumbnailSave( rItem
.m_bUseThumbnailSave
)
266 for (auto const & pOtherProp
: rItem
.m_aCustomProperties
)
268 AddCustomProperty( pOtherProp
->m_sName
, pOtherProp
->m_aValue
);
271 m_aCmisProperties
= rItem
.m_aCmisProperties
;
274 SfxDocumentInfoItem::~SfxDocumentInfoItem()
276 ClearCustomProperties();
279 SfxDocumentInfoItem
* SfxDocumentInfoItem::Clone( SfxItemPool
* ) const
281 return new SfxDocumentInfoItem( *this );
284 bool SfxDocumentInfoItem::operator==( const SfxPoolItem
& rItem
) const
286 if (!SfxStringItem::operator==(rItem
))
288 const SfxDocumentInfoItem
& rInfoItem(static_cast<const SfxDocumentInfoItem
&>(rItem
));
291 m_AutoloadDelay
== rInfoItem
.m_AutoloadDelay
&&
292 m_AutoloadURL
== rInfoItem
.m_AutoloadURL
&&
293 m_isAutoloadEnabled
== rInfoItem
.m_isAutoloadEnabled
&&
294 m_DefaultTarget
== rInfoItem
.m_DefaultTarget
&&
295 m_Author
== rInfoItem
.m_Author
&&
296 m_CreationDate
== rInfoItem
.m_CreationDate
&&
297 m_ModifiedBy
== rInfoItem
.m_ModifiedBy
&&
298 m_ModificationDate
== rInfoItem
.m_ModificationDate
&&
299 m_PrintedBy
== rInfoItem
.m_PrintedBy
&&
300 m_PrintDate
== rInfoItem
.m_PrintDate
&&
301 m_EditingCycles
== rInfoItem
.m_EditingCycles
&&
302 m_EditingDuration
== rInfoItem
.m_EditingDuration
&&
303 m_Description
== rInfoItem
.m_Description
&&
304 m_Keywords
== rInfoItem
.m_Keywords
&&
305 m_Subject
== rInfoItem
.m_Subject
&&
306 m_Title
== rInfoItem
.m_Title
&&
307 comphelper::ContainerUniquePtrEquals(m_aCustomProperties
, rInfoItem
.m_aCustomProperties
) &&
308 m_aCmisProperties
.getLength() == rInfoItem
.m_aCmisProperties
.getLength();
312 void SfxDocumentInfoItem::resetUserData(const OUString
& i_rAuthor
)
314 m_Author
= i_rAuthor
;
315 DateTime
now( DateTime::SYSTEM
);
316 m_CreationDate
= now
.GetUNODateTime();
317 m_ModifiedBy
= OUString();
318 m_PrintedBy
= OUString();
319 m_ModificationDate
= util::DateTime();
320 m_PrintDate
= util::DateTime();
321 m_EditingDuration
= 0;
326 void SfxDocumentInfoItem::UpdateDocumentInfo(
327 const uno::Reference
<document::XDocumentProperties
>& i_xDocProps
,
328 bool i_bDoNotUpdateUserDefined
) const
330 if (isAutoloadEnabled()) {
331 i_xDocProps
->setAutoloadSecs(getAutoloadDelay());
332 i_xDocProps
->setAutoloadURL(getAutoloadURL());
334 i_xDocProps
->setAutoloadSecs(0);
335 i_xDocProps
->setAutoloadURL(OUString());
337 i_xDocProps
->setDefaultTarget(getDefaultTarget());
338 i_xDocProps
->setAuthor(getAuthor());
339 i_xDocProps
->setCreationDate(getCreationDate());
340 i_xDocProps
->setModifiedBy(getModifiedBy());
341 i_xDocProps
->setModificationDate(getModificationDate());
342 i_xDocProps
->setPrintedBy(getPrintedBy());
343 i_xDocProps
->setPrintDate(getPrintDate());
344 i_xDocProps
->setEditingCycles(getEditingCycles());
345 i_xDocProps
->setEditingDuration(getEditingDuration());
346 i_xDocProps
->setDescription(getDescription());
347 i_xDocProps
->setKeywords(
348 ::comphelper::string::convertCommaSeparated(getKeywords()));
349 i_xDocProps
->setSubject(getSubject());
350 i_xDocProps
->setTitle(getTitle());
352 // this is necessary in case of replaying a recorded macro:
353 // in this case, the macro may contain the 4 old user-defined DocumentInfo
354 // fields, but not any of the DocumentInfo properties;
355 // as a consequence, most of the UserDefined properties of the
356 // DocumentProperties would be summarily deleted here, which does not
357 // seem like a good idea.
358 if (i_bDoNotUpdateUserDefined
)
363 Reference
< beans::XPropertyContainer
> xContainer
= i_xDocProps
->getUserDefinedProperties();
364 Reference
< beans::XPropertySet
> xSet( xContainer
, UNO_QUERY
);
365 Reference
< beans::XPropertySetInfo
> xSetInfo
= xSet
->getPropertySetInfo();
366 const Sequence
< beans::Property
> lProps
= xSetInfo
->getProperties();
367 for ( const beans::Property
& rProp
: lProps
)
369 if (rProp
.Attributes
& css::beans::PropertyAttribute::REMOVABLE
)
371 xContainer
->removeProperty( rProp
.Name
);
375 for (auto const & pProp
: m_aCustomProperties
)
379 xContainer
->addProperty( pProp
->m_sName
,
380 beans::PropertyAttribute::REMOVABLE
, pProp
->m_aValue
);
382 catch ( Exception
const & )
384 TOOLS_WARN_EXCEPTION( "sfx.dialog", "SfxDocumentInfoItem::updateDocumentInfo(): exception while adding custom properties" );
388 catch ( Exception
const & )
390 TOOLS_WARN_EXCEPTION( "sfx.dialog", "SfxDocumentInfoItem::updateDocumentInfo(): exception while removing custom properties" );
395 void SfxDocumentInfoItem::SetDeleteUserData( bool bSet
)
397 m_bDeleteUserData
= bSet
;
401 void SfxDocumentInfoItem::SetUseUserData( bool bSet
)
403 m_bUseUserData
= bSet
;
406 void SfxDocumentInfoItem::SetUseThumbnailSave( bool bSet
)
408 m_bUseThumbnailSave
= bSet
;
411 std::vector
< std::unique_ptr
<CustomProperty
> > SfxDocumentInfoItem::GetCustomProperties() const
413 std::vector
< std::unique_ptr
<CustomProperty
> > aRet
;
414 for (auto const & pOtherProp
: m_aCustomProperties
)
416 std::unique_ptr
<CustomProperty
> pProp(new CustomProperty( pOtherProp
->m_sName
,
417 pOtherProp
->m_aValue
));
418 aRet
.push_back( std::move(pProp
) );
424 void SfxDocumentInfoItem::ClearCustomProperties()
426 m_aCustomProperties
.clear();
429 void SfxDocumentInfoItem::AddCustomProperty( const OUString
& sName
, const Any
& rValue
)
431 std::unique_ptr
<CustomProperty
> pProp(new CustomProperty( sName
, rValue
));
432 m_aCustomProperties
.push_back( std::move(pProp
) );
436 void SfxDocumentInfoItem::SetCmisProperties( const Sequence
< document::CmisProperty
>& cmisProps
)
438 m_aCmisProperties
= cmisProps
;
441 bool SfxDocumentInfoItem::QueryValue( Any
& rVal
, sal_uInt8 nMemberId
) const
444 sal_Int32 nValue
= 0;
447 bool bIsString
= false;
448 nMemberId
&= ~CONVERT_TWIPS
;
451 case MID_DOCINFO_USEUSERDATA
:
452 bValue
= IsUseUserData();
454 case MID_DOCINFO_USETHUMBNAILSAVE
:
455 bValue
= IsUseThumbnailSave();
457 case MID_DOCINFO_DELETEUSERDATA
:
458 bValue
= m_bDeleteUserData
;
460 case MID_DOCINFO_AUTOLOADENABLED
:
461 bValue
= isAutoloadEnabled();
463 case MID_DOCINFO_AUTOLOADSECS
:
465 nValue
= getAutoloadDelay();
467 case MID_DOCINFO_AUTOLOADURL
:
469 aValue
= getAutoloadURL();
471 case MID_DOCINFO_DEFAULTTARGET
:
473 aValue
= getDefaultTarget();
475 case MID_DOCINFO_DESCRIPTION
:
477 aValue
= getDescription();
479 case MID_DOCINFO_KEYWORDS
:
481 aValue
= getKeywords();
483 case MID_DOCINFO_SUBJECT
:
485 aValue
= getSubject();
487 case MID_DOCINFO_TITLE
:
492 OSL_FAIL("Wrong MemberId!");
505 bool SfxDocumentInfoItem::PutValue( const Any
& rVal
, sal_uInt8 nMemberId
)
511 nMemberId
&= ~CONVERT_TWIPS
;
514 case MID_DOCINFO_USEUSERDATA
:
515 bRet
= (rVal
>>= bValue
);
517 SetUseUserData( bValue
);
519 case MID_DOCINFO_USETHUMBNAILSAVE
:
520 bRet
= (rVal
>>=bValue
);
522 SetUseThumbnailSave( bValue
);
524 case MID_DOCINFO_DELETEUSERDATA
:
525 // QUESTION: deleting user data was done here; seems to be superfluous!
526 bRet
= (rVal
>>= bValue
);
528 SetDeleteUserData( bValue
);
530 case MID_DOCINFO_AUTOLOADENABLED
:
531 bRet
= (rVal
>>= bValue
);
533 m_isAutoloadEnabled
= bValue
;
535 case MID_DOCINFO_AUTOLOADSECS
:
536 bRet
= (rVal
>>= nValue
);
538 m_AutoloadDelay
= nValue
;
540 case MID_DOCINFO_AUTOLOADURL
:
541 bRet
= (rVal
>>= aValue
);
543 m_AutoloadURL
= aValue
;
545 case MID_DOCINFO_DEFAULTTARGET
:
546 bRet
= (rVal
>>= aValue
);
548 m_DefaultTarget
= aValue
;
550 case MID_DOCINFO_DESCRIPTION
:
551 bRet
= (rVal
>>= aValue
);
553 setDescription(aValue
);
555 case MID_DOCINFO_KEYWORDS
:
556 bRet
= (rVal
>>= aValue
);
560 case MID_DOCINFO_SUBJECT
:
561 bRet
= (rVal
>>= aValue
);
565 case MID_DOCINFO_TITLE
:
566 bRet
= (rVal
>>= aValue
);
571 OSL_FAIL("Wrong MemberId!");
578 SfxDocumentDescPage::SfxDocumentDescPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rItemSet
)
579 : SfxTabPage(pPage
, pController
, "sfx/ui/descriptioninfopage.ui", "DescriptionInfoPage", &rItemSet
)
580 , m_pInfoItem(nullptr)
581 , m_xTitleEd(m_xBuilder
->weld_entry("title"))
582 , m_xThemaEd(m_xBuilder
->weld_entry("subject"))
583 , m_xKeywordsEd(m_xBuilder
->weld_entry("keywords"))
584 , m_xCommentEd(m_xBuilder
->weld_text_view("comments"))
586 m_xCommentEd
->set_size_request(m_xKeywordsEd
->get_preferred_size().Width(),
587 m_xCommentEd
->get_height_rows(16));
590 SfxDocumentDescPage::~SfxDocumentDescPage()
594 std::unique_ptr
<SfxTabPage
> SfxDocumentDescPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
*rItemSet
)
596 return std::make_unique
<SfxDocumentDescPage
>(pPage
, pController
, *rItemSet
);
599 bool SfxDocumentDescPage::FillItemSet(SfxItemSet
*rSet
)
601 // Test whether a change is present
602 const bool bTitleMod
= m_xTitleEd
->get_value_changed_from_saved();
603 const bool bThemeMod
= m_xThemaEd
->get_value_changed_from_saved();
604 const bool bKeywordsMod
= m_xKeywordsEd
->get_value_changed_from_saved();
605 const bool bCommentMod
= m_xCommentEd
->get_value_changed_from_saved();
606 if ( !( bTitleMod
|| bThemeMod
|| bKeywordsMod
|| bCommentMod
) )
611 // Generating the output data
612 const SfxDocumentInfoItem
* pItem
= nullptr;
613 SfxDocumentInfoItem
* pInfo
= nullptr;
614 const SfxItemSet
* pExSet
= GetDialogExampleSet();
616 if ( pExSet
&& !(pItem
= pExSet
->GetItemIfSet( SID_DOCINFO
)) )
619 pInfo
= new SfxDocumentInfoItem( *pItem
);
623 SAL_WARN( "sfx.dialog", "SfxDocumentDescPage::FillItemSet(): no item found" );
629 pInfo
->setTitle( m_xTitleEd
->get_text() );
633 pInfo
->setSubject( m_xThemaEd
->get_text() );
637 pInfo
->setKeywords( m_xKeywordsEd
->get_text() );
641 pInfo
->setDescription( m_xCommentEd
->get_text() );
644 if ( pInfo
!= m_pInfoItem
)
652 void SfxDocumentDescPage::Reset(const SfxItemSet
*rSet
)
654 m_pInfoItem
= const_cast<SfxDocumentInfoItem
*>(&rSet
->Get(SID_DOCINFO
));
656 m_xTitleEd
->set_text(m_pInfoItem
->getTitle());
657 m_xThemaEd
->set_text(m_pInfoItem
->getSubject());
658 m_xKeywordsEd
->set_text(m_pInfoItem
->getKeywords());
659 m_xCommentEd
->set_text(m_pInfoItem
->getDescription());
661 m_xTitleEd
->save_value();
662 m_xThemaEd
->save_value();
663 m_xKeywordsEd
->save_value();
664 m_xCommentEd
->save_value();
666 const SfxBoolItem
* pROItem
= SfxItemSet::GetItem
<SfxBoolItem
>(rSet
, SID_DOC_READONLY
, false);
667 if (pROItem
&& pROItem
->GetValue())
669 m_xTitleEd
->set_editable(false);
670 m_xThemaEd
->set_editable(false);
671 m_xKeywordsEd
->set_editable(false);
672 m_xCommentEd
->set_editable(false);
676 SfxDocumentPage::SfxDocumentPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rItemSet
)
677 : SfxTabPage(pPage
, pController
, "sfx/ui/documentinfopage.ui", "DocumentInfoPage", &rItemSet
)
678 , bEnableUseUserData( false )
679 , bHandleDelete( false )
680 , m_xBmp(m_xBuilder
->weld_image("icon"))
681 , m_xNameED(m_xBuilder
->weld_label("nameed"))
682 , m_xChangePassBtn(m_xBuilder
->weld_button("changepass"))
683 , m_xShowTypeFT(m_xBuilder
->weld_label("showtype"))
684 , m_xFileValEd(m_xBuilder
->weld_link_button("showlocation"))
685 , m_xShowSizeFT(m_xBuilder
->weld_label("showsize"))
686 , m_xCreateValFt(m_xBuilder
->weld_label("showcreate"))
687 , m_xChangeValFt(m_xBuilder
->weld_label("showmodify"))
688 , m_xSignedValFt(m_xBuilder
->weld_label("showsigned"))
689 , m_xSignatureBtn(m_xBuilder
->weld_button("signature"))
690 , m_xPrintValFt(m_xBuilder
->weld_label("showprint"))
691 , m_xTimeLogValFt(m_xBuilder
->weld_label("showedittime"))
692 , m_xDocNoValFt(m_xBuilder
->weld_label("showrevision"))
693 , m_xUseUserDataCB(m_xBuilder
->weld_check_button("userdatacb"))
694 , m_xDeleteBtn(m_xBuilder
->weld_button("reset"))
695 , m_xUseThumbnailSaveCB(m_xBuilder
->weld_check_button("thumbnailsavecb"))
696 , m_xTemplFt(m_xBuilder
->weld_label("templateft"))
697 , m_xTemplValFt(m_xBuilder
->weld_label("showtemplate"))
698 , m_xImagePreferredDpiCheckButton(m_xBuilder
->weld_check_button("image-preferred-dpi-checkbutton"))
699 , m_xImagePreferredDpiComboBox(m_xBuilder
->weld_combo_box("image-preferred-dpi-combobox"))
701 m_xUseUserDataCB
->set_accessible_description(SfxResId(STR_A11Y_DESC_USERDATA
));
703 m_aUnknownSize
= m_xShowSizeFT
->get_label();
704 m_xShowSizeFT
->set_label(OUString());
706 m_aMultiSignedStr
= m_xSignedValFt
->get_label();
707 m_xSignedValFt
->set_label(OUString());
709 ImplUpdateSignatures();
710 ImplCheckPasswordState();
711 m_xChangePassBtn
->connect_clicked( LINK( this, SfxDocumentPage
, ChangePassHdl
) );
712 m_xSignatureBtn
->connect_clicked( LINK( this, SfxDocumentPage
, SignatureHdl
) );
713 if (comphelper::LibreOfficeKit::isActive())
714 m_xSignatureBtn
->hide();
715 m_xDeleteBtn
->connect_clicked( LINK( this, SfxDocumentPage
, DeleteHdl
) );
716 m_xImagePreferredDpiCheckButton
->connect_toggled(LINK(this, SfxDocumentPage
, ImagePreferredDPICheckBoxClicked
));
718 // [i96288] Check if the document signature command is enabled
719 // on the main list enable/disable the pushbutton accordingly
720 SvtCommandOptions aCmdOptions
;
721 if ( aCmdOptions
.LookupDisabled( "Signature" ) )
722 m_xSignatureBtn
->set_sensitive(false);
725 SfxDocumentPage::~SfxDocumentPage()
727 if (m_xPasswordDialog
)
729 m_xPasswordDialog
->Response(RET_CANCEL
);
730 m_xPasswordDialog
.clear();
734 IMPL_LINK_NOARG(SfxDocumentPage
, DeleteHdl
, weld::Button
&, void)
737 if (bEnableUseUserData
&& m_xUseUserDataCB
->get_active())
738 aName
= SvtUserOptions().GetFullName();
739 const LocaleDataWrapper
& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
740 DateTime
now( DateTime::SYSTEM
);
741 util::DateTime
uDT( now
.GetUNODateTime() );
742 m_xCreateValFt
->set_label( ConvertDateTime_Impl( aName
, uDT
, rLocaleWrapper
) );
743 m_xChangeValFt
->set_label( "" );
744 m_xPrintValFt
->set_label( "" );
745 const tools::Time
aTime( 0 );
746 m_xTimeLogValFt
->set_label( rLocaleWrapper
.getDuration( aTime
) );
747 m_xDocNoValFt
->set_label(OUString('1'));
748 bHandleDelete
= true;
751 IMPL_LINK_NOARG(SfxDocumentPage
, SignatureHdl
, weld::Button
&, void)
753 SfxObjectShell
* pDoc
= SfxObjectShell::Current();
756 pDoc
->SignDocumentContent(GetFrameWeld());
758 ImplUpdateSignatures();
762 IMPL_LINK_NOARG(SfxDocumentPage
, ImagePreferredDPICheckBoxClicked
, weld::Toggleable
&, void)
764 bool bEnabled
= m_xImagePreferredDpiCheckButton
->get_state() == TRISTATE_TRUE
;
765 m_xImagePreferredDpiComboBox
->set_sensitive(bEnabled
);
768 IMPL_LINK_NOARG(SfxDocumentPage
, ChangePassHdl
, weld::Button
&, void)
770 SfxObjectShell
* pShell
= SfxObjectShell::Current();
775 SfxItemSet
* pMedSet
= pShell
->GetMedium()->GetItemSet();
778 std::shared_ptr
<const SfxFilter
> pFilter
= pShell
->GetMedium()->GetFilter();
781 if (comphelper::LibreOfficeKit::isActive())
783 // MS Types support max len of 15 characters while OOXML is "unlimited"
784 const sal_uInt16 maxPwdLen
= sfx2::IsMSType(pFilter
) && !sfx2::IsOOXML(pFilter
) ? 15 : 0;
785 // handle the pwd dialog asynchronously
786 VclAbstractDialogFactory
* pFact
= VclAbstractDialogFactory::Create();
787 m_xPasswordDialog
= pFact
->CreatePasswordToOpenModifyDialog(GetFrameWeld(), maxPwdLen
, false);
788 m_xPasswordDialog
->AllowEmpty(); // needed to remove password
789 m_xPasswordDialog
->StartExecuteAsync([this, pFilter
, pMedSet
, pShell
](sal_Int32 nResult
)
791 if (nResult
== RET_OK
)
793 sfx2::SetPassword(pFilter
, pMedSet
, m_xPasswordDialog
->GetPasswordToOpen(),
794 m_xPasswordDialog
->GetPasswordToOpen(), true);
795 pShell
->SetModified();
797 m_xPasswordDialog
->disposeOnce();
800 sfx2::RequestPassword(pFilter
, OUString(), pMedSet
, GetFrameWeld()->GetXWindow());
801 pShell
->SetModified();
807 void SfxDocumentPage::ImplUpdateSignatures()
809 SfxObjectShell
* pDoc
= SfxObjectShell::Current();
813 SfxMedium
* pMedium
= pDoc
->GetMedium();
814 if ( !pMedium
|| pMedium
->GetName().isEmpty() || !pMedium
->GetStorage().is() )
817 Reference
< security::XDocumentDigitalSignatures
> xD
;
820 xD
= security::DocumentDigitalSignatures::createDefault(comphelper::getProcessComponentContext());
821 xD
->setParentWindow(GetDialogController()->getDialog()->GetXWindow());
823 catch ( const css::uno::DeploymentException
& )
827 Sequence
< security::DocumentSignatureInformation
> aInfos
;
830 aInfos
= xD
->verifyDocumentContentSignatures( pMedium
->GetZipStorageToSign_Impl(),
831 uno::Reference
< io::XInputStream
>() );
832 if ( aInfos
.getLength() > 1 )
833 s
= m_aMultiSignedStr
;
834 else if ( aInfos
.getLength() == 1 )
836 const security::DocumentSignatureInformation
& rInfo
= aInfos
[ 0 ];
837 s
= utl::GetDateTimeString( rInfo
.SignatureDate
, rInfo
.SignatureTime
) + ", " +
838 comphelper::xmlsec::GetContentPart(rInfo
.Signer
->getSubjectName(), rInfo
.Signer
->getCertificateKind());
840 m_xSignedValFt
->set_label(s
);
843 void SfxDocumentPage::ImplCheckPasswordState()
845 SfxObjectShell
* pShell
= SfxObjectShell::Current();
850 SfxItemSet
* pMedSet
= pShell
->GetMedium()->GetItemSet();
853 const SfxUnoAnyItem
* pEncryptionDataItem
= SfxItemSet::GetItem
<SfxUnoAnyItem
>(pMedSet
, SID_ENCRYPTIONDATA
, false);
854 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
855 if (pEncryptionDataItem
)
856 pEncryptionDataItem
->GetValue() >>= aEncryptionData
;
860 if (!aEncryptionData
.hasElements())
862 m_xChangePassBtn
->set_sensitive(true);
866 m_xChangePassBtn
->set_sensitive(comphelper::LibreOfficeKit::isActive());
869 std::unique_ptr
<SfxTabPage
> SfxDocumentPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
* rItemSet
)
871 return std::make_unique
<SfxDocumentPage
>(pPage
, pController
, *rItemSet
);
874 void SfxDocumentPage::EnableUseUserData()
876 bEnableUseUserData
= true;
877 m_xUseUserDataCB
->show();
878 m_xDeleteBtn
->show();
881 bool SfxDocumentPage::FillItemSet( SfxItemSet
* rSet
)
885 if ( !bHandleDelete
&& bEnableUseUserData
&&
886 m_xUseUserDataCB
->get_state_changed_from_saved() )
888 const SfxItemSet
* pExpSet
= GetDialogExampleSet();
889 const SfxDocumentInfoItem
* pInfoItem
;
891 if ( pExpSet
&& (pInfoItem
= pExpSet
->GetItemIfSet( SID_DOCINFO
) ) )
893 bool bUseData
= ( TRISTATE_TRUE
== m_xUseUserDataCB
->get_state() );
894 const_cast<SfxDocumentInfoItem
*>(pInfoItem
)->SetUseUserData( bUseData
);
895 rSet
->Put( *pInfoItem
);
902 const SfxItemSet
* pExpSet
= GetDialogExampleSet();
903 const SfxDocumentInfoItem
* pInfoItem
;
904 if ( pExpSet
&& (pInfoItem
= pExpSet
->GetItemIfSet( SID_DOCINFO
)) )
906 bool bUseAuthor
= bEnableUseUserData
&& m_xUseUserDataCB
->get_active();
907 SfxDocumentInfoItem
newItem( *pInfoItem
);
908 newItem
.resetUserData( bUseAuthor
909 ? SvtUserOptions().GetFullName()
911 const_cast<SfxDocumentInfoItem
*>(pInfoItem
)->SetUseUserData( TRISTATE_TRUE
== m_xUseUserDataCB
->get_state() );
912 newItem
.SetUseUserData( TRISTATE_TRUE
== m_xUseUserDataCB
->get_state() );
914 newItem
.SetDeleteUserData( true );
915 rSet
->Put( newItem
);
920 if ( m_xUseThumbnailSaveCB
->get_state_changed_from_saved() )
922 const SfxItemSet
* pExpSet
= GetDialogExampleSet();
923 const SfxDocumentInfoItem
* pInfoItem
;
925 if ( pExpSet
&& (pInfoItem
= pExpSet
->GetItemIfSet( SID_DOCINFO
)) )
927 bool bUseThumbnail
= ( TRISTATE_TRUE
== m_xUseThumbnailSaveCB
->get_state() );
928 const_cast<SfxDocumentInfoItem
*>(pInfoItem
)->SetUseThumbnailSave( bUseThumbnail
);
929 rSet
->Put( *pInfoItem
);
934 SfxObjectShell
* pDocSh
= SfxObjectShell::Current();
937 uno::Reference
<lang::XMultiServiceFactory
> xFac(pDocSh
->GetModel(), uno::UNO_QUERY
);
940 uno::Reference
<beans::XPropertySet
> xProps(xFac
->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY
);
943 sal_Int32 nImagePreferredDPI
= 0;
944 if (m_xImagePreferredDpiCheckButton
->get_state() == TRISTATE_TRUE
)
946 OUString aImagePreferredDPIString
= m_xImagePreferredDpiComboBox
->get_active_text();
947 nImagePreferredDPI
= aImagePreferredDPIString
.toInt32();
949 xProps
->setPropertyValue("ImagePreferredDPI", uno::Any(nImagePreferredDPI
));
957 void SfxDocumentPage::Reset( const SfxItemSet
* rSet
)
959 // Determine the document information
960 const SfxDocumentInfoItem
& rInfoItem
= rSet
->Get(SID_DOCINFO
);
963 if (rInfoItem
.HasTemplate())
965 const OUString
& rName
= rInfoItem
.getTemplateName();
966 if (rName
.getLength() > SAL_MAX_INT16
) // tdf#122780 pick some ~arbitrary max size
967 m_xTemplValFt
->set_label(rName
.copy(0, SAL_MAX_INT16
));
969 m_xTemplValFt
->set_label(rName
);
974 m_xTemplValFt
->hide();
977 // determine file name
978 OUString
aFile( rInfoItem
.GetValue() );
979 OUString
aFactory( aFile
);
980 if ( aFile
.getLength() > 2 && aFile
[0] == '[' )
982 sal_Int32 nPos
= aFile
.indexOf( ']' );
983 aFactory
= aFile
.copy( 1, nPos
-1 );
984 aFile
= aFile
.copy( nPos
+1 );
988 INetURLObject
aURL(aFile
);
989 OUString aName
= aURL
.GetLastName(INetURLObject::DecodeMechanism::WithCharset
);
990 if ( aName
.isEmpty() || aURL
.GetProtocol() == INetProtocol::PrivSoffice
)
991 aName
= SfxResId( STR_NONAME
);
992 m_xNameED
->set_label( aName
);
994 // determine context symbol
995 aURL
.SetSmartProtocol( INetProtocol::File
);
996 aURL
.SetSmartURL( aFactory
);
997 const OUString
& rMainURL
= aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
998 OUString aImage
= SvFileInformationManager::GetImageId( aURL
, true );
999 m_xBmp
->set_from_icon_name(aImage
);
1001 // determine size and type
1002 OUString
aSizeText( m_aUnknownSize
);
1003 if ( aURL
.GetProtocol() == INetProtocol::File
||
1004 aURL
.isAnyKnownWebDAVScheme() )
1005 aSizeText
= CreateSizeText( SfxContentHelper::GetSize( aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) ) );
1006 m_xShowSizeFT
->set_label( aSizeText
);
1008 OUString aDescription
= SvFileInformationManager::GetDescription( INetURLObject(rMainURL
) );
1009 if ( aDescription
.isEmpty() )
1010 aDescription
= SfxResId( STR_SFX_NEWOFFICEDOC
);
1011 m_xShowTypeFT
->set_label( aDescription
);
1013 // determine location
1014 // online we don't know file location so we just set it as the name
1015 if (comphelper::LibreOfficeKit::isActive())
1017 m_xFileValEd
->set_label(aName
);
1018 m_xFileValEd
->set_uri(aName
);
1022 aURL
.SetSmartURL( aFile
);
1023 if ( aURL
.GetProtocol() == INetProtocol::File
)
1025 INetURLObject
aPath( aURL
);
1026 aPath
.setFinalSlash();
1027 aPath
.removeSegment();
1028 // we know it's a folder -> don't need the final slash, but it's better for WB_PATHELLIPSIS
1029 aPath
.removeFinalSlash();
1030 OUString
aText( aPath
.PathToFileName() ); //! (pb) MaxLen?
1031 m_xFileValEd
->set_label(aText
);
1033 osl::FileBase::getFileURLFromSystemPath(aText
, aURLStr
);
1034 m_xFileValEd
->set_uri(aURLStr
);
1036 else if (aURL
.GetProtocol() != INetProtocol::PrivSoffice
)
1038 m_xFileValEd
->set_label(aURL
.GetPartBeforeLastName());
1039 m_xFileValEd
->set_uri(m_xFileValEd
->get_label());
1044 // handle access data
1045 bool bUseUserData
= rInfoItem
.IsUseUserData();
1046 const LocaleDataWrapper
& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
1047 m_xCreateValFt
->set_label( ConvertDateTime_Impl( rInfoItem
.getAuthor(),
1048 rInfoItem
.getCreationDate(), rLocaleWrapper
) );
1049 util::DateTime
aTime( rInfoItem
.getModificationDate() );
1050 if ( aTime
.Month
> 0 )
1051 m_xChangeValFt
->set_label( ConvertDateTime_Impl(
1052 rInfoItem
.getModifiedBy(), aTime
, rLocaleWrapper
) );
1053 aTime
= rInfoItem
.getPrintDate();
1054 if ( aTime
.Month
> 0 )
1055 m_xPrintValFt
->set_label( ConvertDateTime_Impl( rInfoItem
.getPrintedBy(),
1056 aTime
, rLocaleWrapper
) );
1057 const tools::Long nTime
= rInfoItem
.getEditingDuration();
1060 const tools::Time
aT( nTime
/3600, (nTime
%3600)/60, nTime
%60 );
1061 m_xTimeLogValFt
->set_label( rLocaleWrapper
.getDuration( aT
) );
1062 m_xDocNoValFt
->set_label( OUString::number(
1063 rInfoItem
.getEditingCycles() ) );
1066 bool bUseThumbnailSave
= rInfoItem
.IsUseThumbnailSave();
1068 // Check for cmis properties where otherwise unavailable
1069 if ( rInfoItem
.isCmisDocument( ) )
1071 const uno::Sequence
< document::CmisProperty
> aCmisProps
= rInfoItem
.GetCmisProperties();
1072 for ( const auto& rCmisProp
: aCmisProps
)
1074 if ( rCmisProp
.Id
== "cmis:contentStreamLength" &&
1075 aSizeText
== m_aUnknownSize
)
1077 Sequence
< sal_Int64
> seqValue
;
1078 rCmisProp
.Value
>>= seqValue
;
1079 SvNumberFormatter
aNumberFormatter( ::comphelper::getProcessComponentContext(),
1080 Application::GetSettings().GetLanguageTag().getLanguageType() );
1081 sal_uInt32 nIndex
= aNumberFormatter
.GetFormatIndex( NF_NUMBER_SYSTEM
);
1082 if ( seqValue
.hasElements() )
1085 aNumberFormatter
.GetInputLineString( seqValue
[0], nIndex
, sValue
);
1086 m_xShowSizeFT
->set_label( CreateSizeText( sValue
.toInt64( ) ) );
1091 OUString emptyDate
= ConvertDateTime_Impl( u
"", uDT
, rLocaleWrapper
);
1092 if ( rCmisProp
.Id
== "cmis:creationDate" &&
1093 (m_xCreateValFt
->get_label() == emptyDate
||
1094 m_xCreateValFt
->get_label().isEmpty()))
1096 Sequence
< util::DateTime
> seqValue
;
1097 rCmisProp
.Value
>>= seqValue
;
1098 if ( seqValue
.hasElements() )
1100 m_xCreateValFt
->set_label( ConvertDateTime_Impl( u
"", seqValue
[0], rLocaleWrapper
) );
1103 if ( rCmisProp
.Id
== "cmis:lastModificationDate" &&
1104 (m_xChangeValFt
->get_label() == emptyDate
||
1105 m_xChangeValFt
->get_label().isEmpty()))
1107 Sequence
< util::DateTime
> seqValue
;
1108 rCmisProp
.Value
>>= seqValue
;
1109 if ( seqValue
.hasElements() )
1111 m_xChangeValFt
->set_label( ConvertDateTime_Impl( u
"", seqValue
[0], rLocaleWrapper
) );
1117 m_xUseUserDataCB
->set_active(bUseUserData
);
1118 m_xUseUserDataCB
->save_state();
1119 m_xUseUserDataCB
->set_sensitive( bEnableUseUserData
);
1120 bHandleDelete
= false;
1121 m_xDeleteBtn
->set_sensitive( bEnableUseUserData
);
1122 m_xUseThumbnailSaveCB
->set_active(bUseThumbnailSave
);
1123 m_xUseThumbnailSaveCB
->save_state();
1125 SfxObjectShell
* pDocSh
= SfxObjectShell::Current();
1126 sal_Int32 nImagePreferredDPI
= 0;
1131 uno::Reference
< lang::XMultiServiceFactory
> xFac( pDocSh
->GetModel(), uno::UNO_QUERY_THROW
);
1132 uno::Reference
< beans::XPropertySet
> xProps( xFac
->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY_THROW
);
1134 xProps
->getPropertyValue("ImagePreferredDPI") >>= nImagePreferredDPI
;
1136 catch( uno::Exception
& )
1140 if (nImagePreferredDPI
> 0)
1142 m_xImagePreferredDpiCheckButton
->set_state(TRISTATE_TRUE
);
1143 m_xImagePreferredDpiComboBox
->set_sensitive(true);
1144 m_xImagePreferredDpiComboBox
->set_entry_text(OUString::number(nImagePreferredDPI
));
1148 m_xImagePreferredDpiCheckButton
->set_state(TRISTATE_FALSE
);
1149 m_xImagePreferredDpiComboBox
->set_sensitive(false);
1150 m_xImagePreferredDpiComboBox
->set_entry_text("");
1155 SfxDocumentInfoDialog::SfxDocumentInfoDialog(weld::Window
* pParent
, const SfxItemSet
& rItemSet
)
1156 : SfxTabDialogController(pParent
, "sfx/ui/documentpropertiesdialog.ui",
1157 "DocumentPropertiesDialog", &rItemSet
)
1159 const SfxDocumentInfoItem
& rInfoItem
= rItemSet
.Get( SID_DOCINFO
);
1162 const SfxStringItem
* pURLItem
= rItemSet
.GetItem
<SfxStringItem
>(SID_BASEURL
, false);
1163 DBG_ASSERT( pURLItem
, "No BaseURL provided for InternetTabPage!" );
1166 // Determine the Titles
1167 OUString
aTitle(m_xDialog
->get_title());
1168 const SfxStringItem
* pItem
= rItemSet
.GetItemIfSet( SID_EXPLORER_PROPS_START
, false );
1172 const OUString
& aFile( rInfoItem
.GetValue() );
1175 aURL
.SetSmartProtocol( INetProtocol::File
);
1176 aURL
.SetSmartURL( aFile
);
1177 if ( INetProtocol::PrivSoffice
!= aURL
.GetProtocol() )
1179 OUString
aLastName( aURL
.GetLastName() );
1180 if ( !aLastName
.isEmpty() )
1181 aTitle
= aTitle
.replaceFirst("%1", aLastName
);
1183 aTitle
= aTitle
.replaceFirst("%1", aFile
);
1186 aTitle
= aTitle
.replaceFirst("%1", SfxResId( STR_NONAME
));
1190 aTitle
= aTitle
.replaceFirst("%1", pItem
->GetValue());
1192 m_xDialog
->set_title(aTitle
);
1195 AddTabPage("general", SfxDocumentPage::Create
, nullptr);
1196 AddTabPage("description", SfxDocumentDescPage::Create
, nullptr);
1198 if (!comphelper::LibreOfficeKit::isActive())
1199 AddTabPage("customprops", SfxCustomPropertiesPage::Create
, nullptr);
1201 RemoveTabPage("customprops");
1203 if (rInfoItem
.isCmisDocument())
1204 AddTabPage("cmisprops", SfxCmisPropertiesPage::Create
, nullptr);
1206 RemoveTabPage("cmisprops");
1207 // Disable security page for online as not fully asynced yet
1208 if (!comphelper::LibreOfficeKit::isActive())
1209 AddTabPage("security", SfxSecurityPage::Create
, nullptr);
1211 RemoveTabPage("security");
1214 void SfxDocumentInfoDialog::PageCreated(const OUString
& rId
, SfxTabPage
&rPage
)
1216 if (rId
== "general")
1217 static_cast<SfxDocumentPage
&>(rPage
).EnableUseUserData();
1220 void SfxDocumentInfoDialog::AddFontTabPage()
1222 AddTabPage("font", SfxResId(STR_FONT_TABPAGE
), SfxDocumentFontsPage::Create
);
1225 // class CustomPropertiesYesNoButton -------------------------------------
1227 CustomPropertiesYesNoButton::CustomPropertiesYesNoButton(std::unique_ptr
<weld::Widget
> xTopLevel
,
1228 std::unique_ptr
<weld::RadioButton
> xYesButton
,
1229 std::unique_ptr
<weld::RadioButton
> xNoButton
)
1230 : m_xTopLevel(std::move(xTopLevel
))
1231 , m_xYesButton(std::move(xYesButton
))
1232 , m_xNoButton(std::move(xNoButton
))
1237 CustomPropertiesYesNoButton::~CustomPropertiesYesNoButton()
1242 DurationDialog_Impl::DurationDialog_Impl(weld::Widget
* pParent
, const util::Duration
& rDuration
)
1243 : GenericDialogController(pParent
, "sfx/ui/editdurationdialog.ui", "EditDurationDialog")
1244 , m_xNegativeCB(m_xBuilder
->weld_check_button("negative"))
1245 , m_xYearNF(m_xBuilder
->weld_spin_button("years"))
1246 , m_xMonthNF(m_xBuilder
->weld_spin_button("months"))
1247 , m_xDayNF(m_xBuilder
->weld_spin_button("days"))
1248 , m_xHourNF(m_xBuilder
->weld_spin_button("hours"))
1249 , m_xMinuteNF(m_xBuilder
->weld_spin_button("minutes"))
1250 , m_xSecondNF(m_xBuilder
->weld_spin_button("seconds"))
1251 , m_xMSecondNF(m_xBuilder
->weld_spin_button("milliseconds"))
1253 m_xNegativeCB
->set_active(rDuration
.Negative
);
1254 m_xYearNF
->set_value(rDuration
.Years
);
1255 m_xMonthNF
->set_value(rDuration
.Months
);
1256 m_xDayNF
->set_value(rDuration
.Days
);
1257 m_xHourNF
->set_value(rDuration
.Hours
);
1258 m_xMinuteNF
->set_value(rDuration
.Minutes
);
1259 m_xSecondNF
->set_value(rDuration
.Seconds
);
1260 m_xMSecondNF
->set_value(rDuration
.NanoSeconds
);
1263 util::Duration
DurationDialog_Impl::GetDuration() const
1265 util::Duration aRet
;
1266 aRet
.Negative
= m_xNegativeCB
->get_active();
1267 aRet
.Years
= m_xYearNF
->get_value();
1268 aRet
.Months
= m_xMonthNF
->get_value();
1269 aRet
.Days
= m_xDayNF
->get_value();
1270 aRet
.Hours
= m_xHourNF
->get_value();
1271 aRet
.Minutes
= m_xMinuteNF
->get_value();
1272 aRet
.Seconds
= m_xSecondNF
->get_value();
1273 aRet
.NanoSeconds
= m_xMSecondNF
->get_value();
1277 CustomPropertiesDurationField::CustomPropertiesDurationField(std::unique_ptr
<weld::Entry
> xEntry
,
1278 std::unique_ptr
<weld::Button
> xEditButton
)
1279 : m_xEntry(std::move(xEntry
))
1280 , m_xEditButton(std::move(xEditButton
))
1282 m_xEditButton
->connect_clicked(LINK(this, CustomPropertiesDurationField
, ClickHdl
));
1283 SetDuration( util::Duration(false, 0, 0, 0, 0, 0, 0, 0) );
1286 void CustomPropertiesDurationField::set_visible(bool bVisible
)
1288 m_xEntry
->set_visible(bVisible
);
1289 m_xEditButton
->set_visible(bVisible
);
1292 void CustomPropertiesDurationField::SetDuration( const util::Duration
& rDuration
)
1294 m_aDuration
= rDuration
;
1295 OUString sText
= (rDuration
.Negative
? OUString('-') : OUString('+')) +
1296 SfxResId(SFX_ST_DURATION_FORMAT
);
1297 sText
= sText
.replaceFirst( "%1", OUString::number( rDuration
.Years
) );
1298 sText
= sText
.replaceFirst( "%2", OUString::number( rDuration
.Months
) );
1299 sText
= sText
.replaceFirst( "%3", OUString::number( rDuration
.Days
) );
1300 sText
= sText
.replaceFirst( "%4", OUString::number( rDuration
.Hours
) );
1301 sText
= sText
.replaceFirst( "%5", OUString::number( rDuration
.Minutes
) );
1302 sText
= sText
.replaceFirst( "%6", OUString::number( rDuration
.Seconds
) );
1303 m_xEntry
->set_text(sText
);
1306 IMPL_LINK(CustomPropertiesDurationField
, ClickHdl
, weld::Button
&, rButton
, void)
1308 m_xDurationDialog
= std::make_shared
<DurationDialog_Impl
>(&rButton
, GetDuration());
1309 weld::DialogController::runAsync(m_xDurationDialog
, [&](sal_Int32 response
)
1311 if (response
== RET_OK
)
1313 SetDuration(m_xDurationDialog
->GetDuration());
1318 CustomPropertiesDurationField::~CustomPropertiesDurationField()
1320 if (m_xDurationDialog
)
1321 m_xDurationDialog
->response(RET_CANCEL
);
1326 void fillNameBox(weld::ComboBox
& rNameBox
)
1328 for (size_t i
= 0; i
< SAL_N_ELEMENTS(SFX_CB_PROPERTY_STRINGARRAY
); ++i
)
1329 rNameBox
.append_text(SfxResId(SFX_CB_PROPERTY_STRINGARRAY
[i
]));
1330 Size
aSize(rNameBox
.get_preferred_size());
1331 rNameBox
.set_size_request(aSize
.Width(), aSize
.Height());
1334 void fillTypeBox(weld::ComboBox
& rTypeBox
)
1336 for (size_t i
= 0; i
< SAL_N_ELEMENTS(SFX_LB_PROPERTY_STRINGARRAY
); ++i
)
1338 OUString
sId(OUString::number(SFX_LB_PROPERTY_STRINGARRAY
[i
].second
));
1339 rTypeBox
.append(sId
, SfxResId(SFX_LB_PROPERTY_STRINGARRAY
[i
].first
));
1341 rTypeBox
.set_active(0);
1342 Size
aSize(rTypeBox
.get_preferred_size());
1343 rTypeBox
.set_size_request(aSize
.Width(), aSize
.Height());
1347 // struct CustomPropertyLine ---------------------------------------------
1348 CustomPropertyLine::CustomPropertyLine(CustomPropertiesWindow
* pParent
, weld::Widget
* pContainer
)
1349 : m_pParent(pParent
)
1350 , m_xBuilder(Application::CreateBuilder(pContainer
, "sfx/ui/linefragment.ui"))
1351 , m_xLine(m_xBuilder
->weld_container("lineentry"))
1352 , m_xNameBox(m_xBuilder
->weld_combo_box("namebox"))
1353 , m_xTypeBox(m_xBuilder
->weld_combo_box("typebox"))
1354 , m_xValueEdit(m_xBuilder
->weld_entry("valueedit"))
1355 , m_xDateTimeBox(m_xBuilder
->weld_widget("datetimebox"))
1356 , m_xDateField(new CustomPropertiesDateField(new SvtCalendarBox(m_xBuilder
->weld_menu_button("date"))))
1357 , m_xTimeField(new CustomPropertiesTimeField(m_xBuilder
->weld_formatted_spin_button("time")))
1358 , m_xDurationBox(m_xBuilder
->weld_widget("durationbox"))
1359 , m_xDurationField(new CustomPropertiesDurationField(m_xBuilder
->weld_entry("duration"),
1360 m_xBuilder
->weld_button("durationbutton")))
1361 , m_xYesNoButton(new CustomPropertiesYesNoButton(m_xBuilder
->weld_widget("yesno"),
1362 m_xBuilder
->weld_radio_button("yes"),
1363 m_xBuilder
->weld_radio_button("no")))
1364 , m_xRemoveButton(m_xBuilder
->weld_button("remove"))
1365 , m_bTypeLostFocus( false )
1367 fillNameBox(*m_xNameBox
);
1368 fillTypeBox(*m_xTypeBox
);
1370 m_xTypeBox
->connect_changed(LINK(this, CustomPropertyLine
, TypeHdl
));
1371 m_xRemoveButton
->connect_clicked(LINK(this, CustomPropertyLine
, RemoveHdl
));
1372 m_xValueEdit
->connect_focus_out(LINK(this, CustomPropertyLine
, EditLoseFocusHdl
));
1373 //add lose focus handlers of date/time fields
1374 m_xTypeBox
->connect_focus_out(LINK(this, CustomPropertyLine
, BoxLoseFocusHdl
));
1377 void CustomPropertyLine::Clear()
1379 m_xNameBox
->set_active(-1);
1380 m_xValueEdit
->set_text(OUString());
1384 void CustomPropertyLine::Hide()
1389 CustomPropertiesWindow::CustomPropertiesWindow(weld::Container
& rParent
, weld::Label
& rHeaderAccName
,
1390 weld::Label
& rHeaderAccType
, weld::Label
& rHeaderAccValue
)
1394 , m_pCurrentLine(nullptr)
1395 , m_aNumberFormatter(::comphelper::getProcessComponentContext(),
1396 Application::GetSettings().GetLanguageTag().getLanguageType())
1397 , m_aEditLoseFocusIdle("sfx2 CustomPropertiesWindow loseFocusIdle")
1398 , m_aBoxLoseFocusIdle("sfx2 CustomPropertiesWindow m_aBoxLoseFocusIdle")
1400 , m_rHeaderAccName(rHeaderAccName
)
1401 , m_rHeaderAccType(rHeaderAccType
)
1402 , m_rHeaderAccValue(rHeaderAccValue
)
1404 m_aEditLoseFocusIdle
.SetPriority( TaskPriority::LOWEST
);
1405 m_aEditLoseFocusIdle
.SetInvokeHandler( LINK( this, CustomPropertiesWindow
, EditTimeoutHdl
) );
1406 m_aBoxLoseFocusIdle
.SetPriority( TaskPriority::LOWEST
);
1407 m_aBoxLoseFocusIdle
.SetInvokeHandler( LINK( this, CustomPropertiesWindow
, BoxTimeoutHdl
) );
1410 CustomPropertiesWindow::~CustomPropertiesWindow()
1412 m_aEditLoseFocusIdle
.Stop();
1413 m_aBoxLoseFocusIdle
.Stop();
1415 m_pCurrentLine
= nullptr;
1418 void CustomPropertyLine::DoTypeHdl(const weld::ComboBox
& rBox
)
1420 auto nType
= rBox
.get_active_id().toInt32();
1421 m_xValueEdit
->set_visible( (Custom_Type_Text
== nType
) || (Custom_Type_Number
== nType
) );
1422 m_xDateTimeBox
->set_visible( (Custom_Type_Date
== nType
) || (Custom_Type_Datetime
== nType
) );
1423 m_xDateField
->set_visible( (Custom_Type_Date
== nType
) || (Custom_Type_Datetime
== nType
) );
1424 m_xTimeField
->set_visible( Custom_Type_Datetime
== nType
);
1425 m_xDurationBox
->set_visible( Custom_Type_Duration
== nType
);
1426 m_xDurationField
->set_visible( Custom_Type_Duration
== nType
);
1427 m_xYesNoButton
->set_visible( Custom_Type_Boolean
== nType
);
1430 IMPL_LINK(CustomPropertyLine
, TypeHdl
, weld::ComboBox
&, rBox
, void)
1435 void CustomPropertiesWindow::Remove(const CustomPropertyLine
* pLine
)
1437 StoreCustomProperties();
1439 auto pFound
= std::find_if( m_aCustomPropertiesLines
.begin(), m_aCustomPropertiesLines
.end(),
1440 [&] (const std::unique_ptr
<CustomPropertyLine
>& p
) { return p
.get() == pLine
; });
1441 if ( pFound
!= m_aCustomPropertiesLines
.end() )
1443 sal_uInt32 nLineNumber
= pFound
- m_aCustomPropertiesLines
.begin();
1444 sal_uInt32 nDataModelIndex
= GetCurrentDataModelPosition() + nLineNumber
;
1445 m_aCustomProperties
.erase(m_aCustomProperties
.begin() + nDataModelIndex
);
1447 ReloadLinesContent();
1450 m_aRemovedHdl
.Call(nullptr);
1453 IMPL_LINK_NOARG(CustomPropertyLine
, RemoveHdl
, weld::Button
&, void)
1455 m_pParent
->Remove(this);
1458 void CustomPropertiesWindow::EditLoseFocus(CustomPropertyLine
* pLine
)
1460 m_pCurrentLine
= pLine
;
1461 m_aEditLoseFocusIdle
.Start();
1464 IMPL_LINK_NOARG(CustomPropertyLine
, EditLoseFocusHdl
, weld::Widget
&, void)
1466 if (!m_bTypeLostFocus
)
1467 m_pParent
->EditLoseFocus(this);
1469 m_bTypeLostFocus
= false;
1472 void CustomPropertiesWindow::BoxLoseFocus(CustomPropertyLine
* pLine
)
1474 m_pCurrentLine
= pLine
;
1475 m_aBoxLoseFocusIdle
.Start();
1478 IMPL_LINK_NOARG(CustomPropertyLine
, BoxLoseFocusHdl
, weld::Widget
&, void)
1480 m_pParent
->BoxLoseFocus(this);
1483 IMPL_LINK_NOARG(CustomPropertiesWindow
, EditTimeoutHdl
, Timer
*, void)
1485 ValidateLine( m_pCurrentLine
, false );
1488 IMPL_LINK_NOARG(CustomPropertiesWindow
, BoxTimeoutHdl
, Timer
*, void)
1490 ValidateLine( m_pCurrentLine
, true );
1493 bool CustomPropertiesWindow::IsLineValid( CustomPropertyLine
* pLine
) const
1495 bool bIsValid
= true;
1496 pLine
->m_bTypeLostFocus
= false;
1497 auto nType
= pLine
->m_xTypeBox
->get_active_id().toInt32();
1498 OUString sValue
= pLine
->m_xValueEdit
->get_text();
1499 if ( sValue
.isEmpty() )
1502 sal_uInt32 nIndex
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
1503 if ( Custom_Type_Number
== nType
)
1504 // tdf#116214 Scientific format allows to use also standard numbers
1505 nIndex
= const_cast< SvNumberFormatter
& >(
1506 m_aNumberFormatter
).GetFormatIndex( NF_SCIENTIFIC_000E00
);
1507 else if ( Custom_Type_Date
== nType
)
1508 nIndex
= const_cast< SvNumberFormatter
& >(
1509 m_aNumberFormatter
).GetFormatIndex( NF_DATE_SYS_DDMMYYYY
);
1511 if ( nIndex
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
1513 sal_uInt32 nTemp
= nIndex
;
1514 double fDummy
= 0.0;
1515 bIsValid
= const_cast< SvNumberFormatter
& >(
1516 m_aNumberFormatter
).IsNumberFormat( sValue
, nIndex
, fDummy
);
1517 if ( bIsValid
&& nTemp
!= nIndex
)
1518 // sValue is a number but the format doesn't match the index
1525 void CustomPropertiesWindow::ValidateLine( CustomPropertyLine
* pLine
, bool bIsFromTypeBox
)
1527 if (pLine
&& !IsLineValid(pLine
))
1529 if ( bIsFromTypeBox
) // LoseFocus of TypeBox
1530 pLine
->m_bTypeLostFocus
= true;
1531 std::unique_ptr
<weld::MessageDialog
> xMessageBox(Application::CreateMessageDialog(&m_rBody
,
1532 VclMessageType::Question
, VclButtonsType::OkCancel
, SfxResId(STR_SFX_QUERY_WRONG_TYPE
)));
1533 if (xMessageBox
->run() == RET_OK
)
1534 pLine
->m_xTypeBox
->set_active_id(OUString::number(Custom_Type_Text
));
1536 pLine
->m_xValueEdit
->grab_focus();
1540 void CustomPropertiesWindow::SetVisibleLineCount(sal_uInt32 nCount
)
1542 while (GetExistingLineCount() < nCount
)
1548 void CustomPropertiesWindow::AddLine(const OUString
& sName
, Any
const & rAny
)
1550 m_aCustomProperties
.push_back(std::unique_ptr
<CustomProperty
>(new CustomProperty(sName
, rAny
)));
1551 ReloadLinesContent();
1554 void CustomPropertiesWindow::CreateNewLine()
1556 CustomPropertyLine
* pNewLine
= new CustomPropertyLine(this, &m_rBody
);
1557 pNewLine
->m_xNameBox
->set_accessible_relation_labeled_by(&m_rHeaderAccName
);
1558 pNewLine
->m_xNameBox
->set_accessible_name(m_rHeaderAccName
.get_label());
1559 pNewLine
->m_xTypeBox
->set_accessible_relation_labeled_by(&m_rHeaderAccType
);
1560 pNewLine
->m_xTypeBox
->set_accessible_name(m_rHeaderAccType
.get_label());
1561 pNewLine
->m_xValueEdit
->set_accessible_relation_labeled_by(&m_rHeaderAccValue
);
1562 pNewLine
->m_xValueEdit
->set_accessible_name(m_rHeaderAccValue
.get_label());
1564 m_aCustomPropertiesLines
.emplace_back( pNewLine
);
1566 // this breaks online's jsdialogbuilder
1567 if (!comphelper::LibreOfficeKit::isActive()){
1568 // for ui-testing. Distinguish the elements in the lines
1569 sal_uInt16 nSize
= m_aCustomPropertiesLines
.size();
1570 pNewLine
->m_xNameBox
->set_buildable_name(
1571 pNewLine
->m_xNameBox
->get_buildable_name() + OUString::number(nSize
));
1572 pNewLine
->m_xTypeBox
->set_buildable_name(
1573 pNewLine
->m_xTypeBox
->get_buildable_name() + OUString::number(nSize
));
1574 pNewLine
->m_xValueEdit
->set_buildable_name(
1575 pNewLine
->m_xValueEdit
->get_buildable_name() + OUString::number(nSize
));
1576 pNewLine
->m_xRemoveButton
->set_buildable_name(
1577 pNewLine
->m_xRemoveButton
->get_buildable_name() + OUString::number(nSize
));
1580 pNewLine
->DoTypeHdl(*pNewLine
->m_xTypeBox
);
1583 bool CustomPropertiesWindow::AreAllLinesValid() const
1586 for ( std::unique_ptr
<CustomPropertyLine
> const & pLine
: m_aCustomPropertiesLines
)
1588 if ( !IsLineValid( pLine
.get() ) )
1598 void CustomPropertiesWindow::ClearAllLines()
1600 for (auto& pLine
: m_aCustomPropertiesLines
)
1604 m_pCurrentLine
= nullptr;
1605 m_aCustomProperties
.clear();
1609 void CustomPropertiesWindow::DoScroll( sal_Int32 nNewPos
)
1611 StoreCustomProperties();
1612 m_nScrollPos
+= nNewPos
;
1613 ReloadLinesContent();
1616 Sequence
< beans::PropertyValue
> CustomPropertiesWindow::GetCustomProperties()
1618 StoreCustomProperties();
1620 Sequence
< beans::PropertyValue
> aPropertiesSeq(GetTotalLineCount());
1622 m_aCustomProperties
.begin(), m_aCustomProperties
.end(), aPropertiesSeq
.getArray(),
1623 [](const auto& el
) { return comphelper::makePropertyValue(el
->m_sName
, el
->m_aValue
); });
1625 return aPropertiesSeq
;
1628 CustomPropertiesTimeField::CustomPropertiesTimeField(std::unique_ptr
<weld::FormattedSpinButton
> xTimeField
)
1629 : m_xTimeField(std::move(xTimeField
))
1630 , m_xFormatter(new weld::TimeFormatter(*m_xTimeField
))
1633 m_xFormatter
->SetExtFormat(ExtTimeFieldFormat::LongDuration
);
1634 m_xFormatter
->EnableEmptyField(false);
1637 tools::Time
CustomPropertiesTimeField::get_value() const
1639 return m_xFormatter
->GetTime();
1642 void CustomPropertiesTimeField::set_value(const tools::Time
& rTime
)
1644 m_xFormatter
->SetTime(rTime
);
1647 CustomPropertiesTimeField::~CustomPropertiesTimeField()
1651 CustomPropertiesDateField::CustomPropertiesDateField(SvtCalendarBox
* pDateField
)
1652 : m_xDateField(pDateField
)
1654 DateTime
aDateTime(DateTime::SYSTEM
);
1655 m_xDateField
->set_date(aDateTime
);
1658 void CustomPropertiesDateField::set_visible(bool bVisible
)
1660 m_xDateField
->set_visible(bVisible
);
1663 Date
CustomPropertiesDateField::get_date() const
1665 return m_xDateField
->get_date();
1668 void CustomPropertiesDateField::set_date(const Date
& rDate
)
1670 m_xDateField
->set_date(rDate
);
1673 CustomPropertiesDateField::~CustomPropertiesDateField()
1677 void CustomPropertiesWindow::StoreCustomProperties()
1679 sal_uInt32 nDataModelPos
= GetCurrentDataModelPosition();
1681 for (sal_uInt32 i
= 0; nDataModelPos
+ i
< GetTotalLineCount() && i
< GetExistingLineCount(); i
++)
1683 CustomPropertyLine
* pLine
= m_aCustomPropertiesLines
[i
].get();
1685 OUString sPropertyName
= pLine
->m_xNameBox
->get_active_text();
1686 if (!sPropertyName
.isEmpty())
1688 m_aCustomProperties
[nDataModelPos
+ i
]->m_sName
= sPropertyName
;
1689 auto nType
= pLine
->m_xTypeBox
->get_active_id().toInt32();
1690 if (Custom_Type_Number
== nType
)
1693 sal_uInt32 nIndex
= m_aNumberFormatter
.GetFormatIndex(NF_NUMBER_SYSTEM
);
1694 bool bIsNum
= m_aNumberFormatter
.
1695 IsNumberFormat(pLine
->m_xValueEdit
->get_text(), nIndex
, nValue
);
1697 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= nValue
;
1699 else if (Custom_Type_Boolean
== nType
)
1701 bool bValue
= pLine
->m_xYesNoButton
->IsYesChecked();
1702 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= bValue
;
1704 else if (Custom_Type_Datetime
== nType
)
1706 Date aTmpDate
= pLine
->m_xDateField
->get_date();
1707 tools::Time aTmpTime
= pLine
->m_xTimeField
->get_value();
1708 util::DateTime
const aDateTime(aTmpTime
.GetNanoSec(),
1709 aTmpTime
.GetSec(), aTmpTime
.GetMin(), aTmpTime
.GetHour(),
1710 aTmpDate
.GetDay(), aTmpDate
.GetMonth(), aTmpDate
.GetYear(),
1711 pLine
->m_xTimeField
->m_isUTC
);
1712 if (pLine
->m_xDateField
->m_TZ
)
1714 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= util::DateTimeWithTimezone(
1715 aDateTime
, *pLine
->m_xDateField
->m_TZ
);
1719 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= aDateTime
;
1722 else if (Custom_Type_Date
== nType
)
1724 Date aTmpDate
= pLine
->m_xDateField
->get_date();
1725 util::Date
const aDate(aTmpDate
.GetDay(), aTmpDate
.GetMonth(),
1726 aTmpDate
.GetYear());
1727 if (pLine
->m_xDateField
->m_TZ
)
1729 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= util::DateWithTimezone(
1730 aDate
, *pLine
->m_xDateField
->m_TZ
);
1734 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= aDate
;
1737 else if (Custom_Type_Duration
== nType
)
1739 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= pLine
->m_xDurationField
->GetDuration();
1743 OUString
sValue(pLine
->m_xValueEdit
->get_text());
1744 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= sValue
;
1750 void CustomPropertiesWindow::SetCustomProperties(std::vector
< std::unique_ptr
<CustomProperty
> >&& rProperties
)
1752 m_aCustomProperties
= std::move(rProperties
);
1753 ReloadLinesContent();
1756 void CustomPropertiesWindow::ReloadLinesContent()
1758 double nTmpValue
= 0;
1759 bool bTmpValue
= false;
1761 util::DateTime aTmpDateTime
;
1762 util::Date aTmpDate
;
1763 util::DateTimeWithTimezone aTmpDateTimeTZ
;
1764 util::DateWithTimezone aTmpDateTZ
;
1765 util::Duration aTmpDuration
;
1766 SvtSysLocale aSysLocale
;
1767 const LocaleDataWrapper
& rLocaleWrapper
= aSysLocale
.GetLocaleData();
1768 CustomProperties nType
= Custom_Type_Unknown
;
1771 sal_uInt32 nDataModelPos
= GetCurrentDataModelPosition();
1774 for (; nDataModelPos
+ i
< GetTotalLineCount() && i
< GetExistingLineCount(); i
++)
1776 const OUString
& rName
= m_aCustomProperties
[nDataModelPos
+ i
]->m_sName
;
1777 const css::uno::Any
& rAny
= m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
;
1779 CustomPropertyLine
* pLine
= m_aCustomPropertiesLines
[i
].get();
1782 pLine
->m_xNameBox
->set_entry_text(rName
);
1783 pLine
->m_xLine
->show();
1785 if (!rAny
.hasValue())
1787 pLine
->m_xValueEdit
->set_text(OUString());
1789 else if (rAny
>>= nTmpValue
)
1791 sal_uInt32 nIndex
= m_aNumberFormatter
.GetFormatIndex(NF_NUMBER_SYSTEM
);
1792 m_aNumberFormatter
.GetInputLineString(nTmpValue
, nIndex
, sValue
);
1793 pLine
->m_xValueEdit
->set_text(sValue
);
1794 nType
= Custom_Type_Number
;
1796 else if (rAny
>>= bTmpValue
)
1798 sValue
= (bTmpValue
? rLocaleWrapper
.getTrueWord() : rLocaleWrapper
.getFalseWord());
1799 nType
= Custom_Type_Boolean
;
1801 else if (rAny
>>= sTmpValue
)
1803 pLine
->m_xValueEdit
->set_text(sTmpValue
);
1804 nType
= Custom_Type_Text
;
1806 else if (rAny
>>= aTmpDate
)
1808 pLine
->m_xDateField
->set_date(Date(aTmpDate
));
1809 nType
= Custom_Type_Date
;
1811 else if (rAny
>>= aTmpDateTime
)
1813 pLine
->m_xDateField
->set_date(Date(aTmpDateTime
));
1814 pLine
->m_xTimeField
->set_value(tools::Time(aTmpDateTime
));
1815 pLine
->m_xTimeField
->m_isUTC
= aTmpDateTime
.IsUTC
;
1816 nType
= Custom_Type_Datetime
;
1818 else if (rAny
>>= aTmpDateTZ
)
1820 pLine
->m_xDateField
->set_date(Date(aTmpDateTZ
.DateInTZ
.Day
,
1821 aTmpDateTZ
.DateInTZ
.Month
, aTmpDateTZ
.DateInTZ
.Year
));
1822 pLine
->m_xDateField
->m_TZ
= aTmpDateTZ
.Timezone
;
1823 nType
= Custom_Type_Date
;
1826 else if (rAny
>>= aTmpDateTimeTZ
)
1828 util::DateTime
const& rDT(aTmpDateTimeTZ
.DateTimeInTZ
);
1829 pLine
->m_xDateField
->set_date(Date(rDT
));
1830 pLine
->m_xTimeField
->set_value(tools::Time(rDT
));
1831 pLine
->m_xTimeField
->m_isUTC
= rDT
.IsUTC
;
1832 pLine
->m_xDateField
->m_TZ
= aTmpDateTimeTZ
.Timezone
;
1833 nType
= Custom_Type_Datetime
;
1835 else if (rAny
>>= aTmpDuration
)
1837 nType
= Custom_Type_Duration
;
1838 pLine
->m_xDurationField
->SetDuration(aTmpDuration
);
1841 if (Custom_Type_Boolean
== nType
)
1844 pLine
->m_xYesNoButton
->CheckYes();
1846 pLine
->m_xYesNoButton
->CheckNo();
1848 pLine
->m_xTypeBox
->set_active_id(OUString::number(nType
));
1850 pLine
->DoTypeHdl(*pLine
->m_xTypeBox
);
1853 // tdf#132667 - grab focus on the last inserted property
1854 if (i
> 0 && m_aCustomProperties
[nDataModelPos
+ i
- 1]->m_sName
.isEmpty())
1856 CustomPropertyLine
* pLine
= m_aCustomPropertiesLines
[i
- 1].get();
1857 pLine
->m_xNameBox
->grab_focus();
1860 while (nDataModelPos
+ i
>= GetTotalLineCount() && i
< GetExistingLineCount())
1862 CustomPropertyLine
* pLine
= m_aCustomPropertiesLines
[i
].get();
1868 CustomPropertiesControl::CustomPropertiesControl()
1873 void CustomPropertiesControl::Init(weld::Builder
& rBuilder
)
1875 m_xBox
= rBuilder
.weld_widget("box");
1876 m_xBody
= rBuilder
.weld_container("properties");
1878 m_xName
= rBuilder
.weld_label("name");
1879 m_xType
= rBuilder
.weld_label("type");
1880 m_xValue
= rBuilder
.weld_label("value");
1881 m_xVertScroll
= rBuilder
.weld_scrolled_window("scroll", true);
1882 m_xPropertiesWin
.reset(new CustomPropertiesWindow(*m_xBody
, *m_xName
, *m_xType
, *m_xValue
));
1884 m_xBox
->set_stack_background();
1885 m_xVertScroll
->show();
1887 std::unique_ptr
<CustomPropertyLine
> xNewLine(new CustomPropertyLine(m_xPropertiesWin
.get(), m_xBody
.get()));
1888 Size
aLineSize(xNewLine
->m_xLine
->get_preferred_size());
1889 m_xPropertiesWin
->SetLineHeight(aLineSize
.Height() + 6);
1890 m_xBody
->set_size_request(aLineSize
.Width() + 6, -1);
1891 auto nHeight
= aLineSize
.Height() * 8;
1892 m_xVertScroll
->set_size_request(-1, nHeight
+ 6);
1894 m_xPropertiesWin
->SetHeight(nHeight
);
1895 m_xVertScroll
->connect_size_allocate(LINK(this, CustomPropertiesControl
, ResizeHdl
));
1897 m_xName
->set_size_request(xNewLine
->m_xNameBox
->get_preferred_size().Width(), -1);
1898 m_xType
->set_size_request(xNewLine
->m_xTypeBox
->get_preferred_size().Width(), -1);
1899 m_xValue
->set_size_request(xNewLine
->m_xValueEdit
->get_preferred_size().Width(), -1);
1901 m_xBody
->move(xNewLine
->m_xLine
.get(), nullptr);
1904 m_xPropertiesWin
->SetRemovedHdl( LINK( this, CustomPropertiesControl
, RemovedHdl
) );
1906 m_xVertScroll
->vadjustment_set_lower(0);
1907 m_xVertScroll
->vadjustment_set_upper(0);
1908 m_xVertScroll
->vadjustment_set_page_size(0xFFFF);
1910 Link
<weld::ScrolledWindow
&,void> aScrollLink
= LINK( this, CustomPropertiesControl
, ScrollHdl
);
1911 m_xVertScroll
->connect_vadjustment_changed(aScrollLink
);
1913 ResizeHdl(Size(-1, nHeight
));
1916 IMPL_LINK(CustomPropertiesControl
, ResizeHdl
, const Size
&, rSize
, void)
1918 int nHeight
= rSize
.Height() - 6;
1919 if (nHeight
== m_xPropertiesWin
->GetHeight())
1921 m_xPropertiesWin
->SetHeight(nHeight
);
1922 sal_Int32 nScrollOffset
= m_xPropertiesWin
->GetLineHeight();
1923 sal_Int32 nVisibleEntries
= nHeight
/ nScrollOffset
;
1924 m_xPropertiesWin
->SetVisibleLineCount( nVisibleEntries
);
1925 m_xVertScroll
->vadjustment_set_page_increment( nVisibleEntries
- 1 );
1926 m_xVertScroll
->vadjustment_set_page_size( nVisibleEntries
);
1927 m_xPropertiesWin
->ReloadLinesContent();
1930 CustomPropertiesControl::~CustomPropertiesControl()
1934 IMPL_LINK( CustomPropertiesControl
, ScrollHdl
, weld::ScrolledWindow
&, rScrollBar
, void )
1936 sal_Int32 nOffset
= m_xPropertiesWin
->GetLineHeight();
1937 int nThumbPos
= rScrollBar
.vadjustment_get_value();
1938 nOffset
*= ( m_nThumbPos
- nThumbPos
);
1939 m_nThumbPos
= nThumbPos
;
1940 m_xPropertiesWin
->DoScroll( nOffset
);
1943 IMPL_LINK_NOARG(CustomPropertiesControl
, RemovedHdl
, void*, void)
1945 auto nLineCount
= m_xPropertiesWin
->GetTotalLineCount();
1946 m_xVertScroll
->vadjustment_set_upper(nLineCount
+ 1);
1947 if (m_xPropertiesWin
->GetTotalLineCount() > m_xPropertiesWin
->GetExistingLineCount())
1949 m_xVertScroll
->vadjustment_set_value(nLineCount
- 1);
1950 ScrollHdl(*m_xVertScroll
);
1954 void CustomPropertiesControl::AddLine( Any
const & rAny
)
1956 m_xPropertiesWin
->AddLine( OUString(), rAny
);
1957 auto nLineCount
= m_xPropertiesWin
->GetTotalLineCount();
1958 m_xVertScroll
->vadjustment_set_upper(nLineCount
+ 1);
1959 if (m_xPropertiesWin
->GetHeight() < nLineCount
* m_xPropertiesWin
->GetLineHeight())
1961 m_xVertScroll
->vadjustment_set_value(nLineCount
+ 1);
1962 ScrollHdl(*m_xVertScroll
);
1966 void CustomPropertiesControl::SetCustomProperties(std::vector
< std::unique_ptr
<CustomProperty
> >&& rProperties
)
1968 m_xPropertiesWin
->SetCustomProperties(std::move(rProperties
));
1969 auto nLineCount
= m_xPropertiesWin
->GetTotalLineCount();
1970 m_xVertScroll
->vadjustment_set_upper(nLineCount
+ 1);
1973 // class SfxCustomPropertiesPage -----------------------------------------
1974 SfxCustomPropertiesPage::SfxCustomPropertiesPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rItemSet
)
1975 : SfxTabPage(pPage
, pController
, "sfx/ui/custominfopage.ui", "CustomInfoPage", &rItemSet
)
1976 , m_xPropertiesCtrl(new CustomPropertiesControl
)
1977 , m_xAdd(m_xBuilder
->weld_button("add"))
1979 m_xPropertiesCtrl
->Init(*m_xBuilder
);
1980 m_xAdd
->connect_clicked(LINK(this, SfxCustomPropertiesPage
, AddHdl
));
1983 SfxCustomPropertiesPage::~SfxCustomPropertiesPage()
1985 m_xPropertiesCtrl
.reset();
1988 IMPL_LINK_NOARG(SfxCustomPropertiesPage
, AddHdl
, weld::Button
&, void)
1990 // tdf#115853: reload current lines before adding a brand new one
1991 // indeed the info are deleted by ClearCustomProperties
1992 // each time SfxDocumentInfoItem destructor is called
1993 SfxDocumentInfoItem pInfo
;
1994 const Sequence
< beans::PropertyValue
> aPropertySeq
= m_xPropertiesCtrl
->GetCustomProperties();
1995 for ( const auto& rProperty
: aPropertySeq
)
1997 if ( !rProperty
.Name
.isEmpty() )
1999 pInfo
.AddCustomProperty( rProperty
.Name
, rProperty
.Value
);
2004 m_xPropertiesCtrl
->AddLine(aAny
);
2007 bool SfxCustomPropertiesPage::FillItemSet( SfxItemSet
* rSet
)
2009 const SfxDocumentInfoItem
* pItem
= nullptr;
2010 SfxDocumentInfoItem
* pInfo
= nullptr;
2011 bool bMustDelete
= false;
2013 if (const SfxItemSet
* pItemSet
= GetDialogExampleSet())
2015 pItem
= pItemSet
->GetItemIfSet(SID_DOCINFO
);
2017 pInfo
= const_cast<SfxDocumentInfoItem
*>(&rSet
->Get( SID_DOCINFO
));
2021 pInfo
= new SfxDocumentInfoItem( *pItem
);
2027 // If it's a CMIS document, we can't save custom properties
2028 if ( pInfo
->isCmisDocument( ) )
2035 pInfo
->ClearCustomProperties();
2036 const Sequence
< beans::PropertyValue
> aPropertySeq
= m_xPropertiesCtrl
->GetCustomProperties();
2037 for ( const auto& rProperty
: aPropertySeq
)
2039 if ( !rProperty
.Name
.isEmpty() )
2040 pInfo
->AddCustomProperty( rProperty
.Name
, rProperty
.Value
);
2053 void SfxCustomPropertiesPage::Reset( const SfxItemSet
* rItemSet
)
2055 m_xPropertiesCtrl
->ClearAllLines();
2056 const SfxDocumentInfoItem
& rInfoItem
= rItemSet
->Get(SID_DOCINFO
);
2057 std::vector
< std::unique_ptr
<CustomProperty
> > aCustomProps
= rInfoItem
.GetCustomProperties();
2058 // tdf#123919 - sort custom document properties
2059 auto const sort
= comphelper::string::NaturalStringSorter(
2060 comphelper::getProcessComponentContext(),
2061 Application::GetSettings().GetLanguageTag().getLocale());
2062 std::sort(aCustomProps
.begin(), aCustomProps
.end(),
2063 [&sort
](const std::unique_ptr
<CustomProperty
>& rLHS
,
2064 const std::unique_ptr
<CustomProperty
>& rRHS
) {
2065 return sort
.compare(rLHS
->m_sName
, rRHS
->m_sName
) < 0;
2067 m_xPropertiesCtrl
->SetCustomProperties(std::move(aCustomProps
));
2070 DeactivateRC
SfxCustomPropertiesPage::DeactivatePage( SfxItemSet
* /*pSet*/ )
2072 DeactivateRC nRet
= DeactivateRC::LeavePage
;
2073 if ( !m_xPropertiesCtrl
->AreAllLinesValid() )
2074 nRet
= DeactivateRC::KeepPage
;
2078 std::unique_ptr
<SfxTabPage
> SfxCustomPropertiesPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
* rItemSet
)
2080 return std::make_unique
<SfxCustomPropertiesPage
>(pPage
, pController
, *rItemSet
);
2083 CmisValue::CmisValue(weld::Widget
* pParent
, const OUString
& aStr
)
2084 : m_xBuilder(Application::CreateBuilder(pParent
, "sfx/ui/cmisline.ui"))
2085 , m_xFrame(m_xBuilder
->weld_frame("CmisFrame"))
2086 , m_xValueEdit(m_xBuilder
->weld_entry("value"))
2088 m_xValueEdit
->show();
2089 m_xValueEdit
->set_text(aStr
);
2092 CmisDateTime::CmisDateTime(weld::Widget
* pParent
, const util::DateTime
& aDateTime
)
2093 : m_xBuilder(Application::CreateBuilder(pParent
, "sfx/ui/cmisline.ui"))
2094 , m_xFrame(m_xBuilder
->weld_frame("CmisFrame"))
2095 , m_xDateField(new SvtCalendarBox(m_xBuilder
->weld_menu_button("date")))
2096 , m_xTimeField(m_xBuilder
->weld_formatted_spin_button("time"))
2097 , m_xFormatter(new weld::TimeFormatter(*m_xTimeField
))
2099 m_xFormatter
->SetExtFormat(ExtTimeFieldFormat::LongDuration
);
2100 m_xFormatter
->EnableEmptyField(false);
2102 m_xDateField
->show();
2103 m_xTimeField
->show();
2104 m_xDateField
->set_date(Date(aDateTime
));
2105 m_xFormatter
->SetTime(tools::Time(aDateTime
));
2108 CmisYesNo::CmisYesNo(weld::Widget
* pParent
, bool bValue
)
2109 : m_xBuilder(Application::CreateBuilder(pParent
, "sfx/ui/cmisline.ui"))
2110 , m_xFrame(m_xBuilder
->weld_frame("CmisFrame"))
2111 , m_xYesButton(m_xBuilder
->weld_radio_button("yes"))
2112 , m_xNoButton(m_xBuilder
->weld_radio_button("no"))
2114 m_xYesButton
->show();
2115 m_xNoButton
->show();
2117 m_xYesButton
->set_active(true);
2119 m_xNoButton
->set_active(true);
2122 // struct CmisPropertyLine ---------------------------------------------
2123 CmisPropertyLine::CmisPropertyLine(weld::Widget
* pParent
)
2124 : m_xBuilder(Application::CreateBuilder(pParent
, "sfx/ui/cmisline.ui"))
2125 , m_sType(CMIS_TYPE_STRING
)
2126 , m_bUpdatable(false)
2127 , m_bRequired(false)
2128 , m_bMultiValued(false)
2129 , m_bOpenChoice(false)
2130 , m_xFrame(m_xBuilder
->weld_frame("CmisFrame"))
2131 , m_xName(m_xBuilder
->weld_label("name"))
2132 , m_xType(m_xBuilder
->weld_label("type"))
2134 m_xFrame
->set_sensitive(true);
2137 CmisPropertyLine::~CmisPropertyLine( )
2141 // class CmisPropertiesWindow -----------------------------------------
2143 CmisPropertiesWindow::CmisPropertiesWindow(std::unique_ptr
<weld::Container
> xParent
)
2144 : m_xBox(std::move(xParent
))
2145 , m_aNumberFormatter(::comphelper::getProcessComponentContext(),
2146 Application::GetSettings().GetLanguageTag().getLanguageType())
2150 CmisPropertiesWindow::~CmisPropertiesWindow()
2154 void CmisPropertiesWindow::ClearAllLines()
2156 m_aCmisPropertiesLines
.clear();
2159 void CmisPropertiesWindow::AddLine( const OUString
& sId
, const OUString
& sName
,
2160 const OUString
& sType
, const bool bUpdatable
,
2161 const bool bRequired
, const bool bMultiValued
,
2162 const bool bOpenChoice
, Any
& /*aChoices*/, Any
const & rAny
)
2164 std::unique_ptr
<CmisPropertyLine
> pNewLine(new CmisPropertyLine(m_xBox
.get()));
2166 pNewLine
->m_sId
= sId
;
2167 pNewLine
->m_sType
= sType
;
2168 pNewLine
->m_bUpdatable
= bUpdatable
;
2169 pNewLine
->m_bRequired
= bRequired
;
2170 pNewLine
->m_bMultiValued
= bMultiValued
;
2171 pNewLine
->m_bOpenChoice
= bOpenChoice
;
2173 if ( sType
== CMIS_TYPE_INTEGER
)
2175 Sequence
< sal_Int64
> seqValue
;
2177 sal_uInt32 nIndex
= m_aNumberFormatter
.GetFormatIndex( NF_NUMBER_SYSTEM
);
2178 for ( const auto& rValue
: std::as_const(seqValue
) )
2181 m_aNumberFormatter
.GetInputLineString( rValue
, nIndex
, sValue
);
2182 std::unique_ptr
<CmisValue
> pValue(new CmisValue(m_xBox
.get(), sValue
));
2183 pValue
->m_xValueEdit
->set_editable(bUpdatable
);
2184 pNewLine
->m_aValues
.push_back( std::move(pValue
) );
2187 else if ( sType
== CMIS_TYPE_DECIMAL
)
2189 Sequence
< double > seqValue
;
2191 sal_uInt32 nIndex
= m_aNumberFormatter
.GetFormatIndex( NF_NUMBER_SYSTEM
);
2192 for ( const auto& rValue
: std::as_const(seqValue
) )
2195 m_aNumberFormatter
.GetInputLineString( rValue
, nIndex
, sValue
);
2196 std::unique_ptr
<CmisValue
> pValue(new CmisValue(m_xBox
.get(), sValue
));
2197 pValue
->m_xValueEdit
->set_editable(bUpdatable
);
2198 pNewLine
->m_aValues
.push_back( std::move(pValue
) );
2202 else if ( sType
== CMIS_TYPE_BOOL
)
2204 Sequence
<sal_Bool
> seqValue
;
2206 for ( const auto& rValue
: std::as_const(seqValue
) )
2208 std::unique_ptr
<CmisYesNo
> pYesNo(new CmisYesNo(m_xBox
.get(), rValue
));
2209 pYesNo
->m_xYesButton
->set_sensitive( bUpdatable
);
2210 pYesNo
->m_xNoButton
->set_sensitive( bUpdatable
);
2211 pNewLine
->m_aYesNos
.push_back( std::move(pYesNo
) );
2214 else if ( sType
== CMIS_TYPE_STRING
)
2216 Sequence
< OUString
> seqValue
;
2218 for ( const auto& rValue
: std::as_const(seqValue
) )
2220 std::unique_ptr
<CmisValue
> pValue(new CmisValue(m_xBox
.get(), rValue
));
2221 pValue
->m_xValueEdit
->set_editable(bUpdatable
);
2222 pNewLine
->m_aValues
.push_back( std::move(pValue
) );
2225 else if ( sType
== CMIS_TYPE_DATETIME
)
2227 Sequence
< util::DateTime
> seqValue
;
2229 for ( const auto& rValue
: std::as_const(seqValue
) )
2231 std::unique_ptr
<CmisDateTime
> pDateTime(new CmisDateTime(m_xBox
.get(), rValue
));
2232 pDateTime
->m_xDateField
->set_sensitive(bUpdatable
);
2233 pDateTime
->m_xTimeField
->set_sensitive(bUpdatable
);
2234 pNewLine
->m_aDateTimes
.push_back( std::move(pDateTime
) );
2237 pNewLine
->m_xName
->set_label( sName
);
2238 pNewLine
->m_xName
->show();
2239 pNewLine
->m_xType
->set_label( sType
);
2240 pNewLine
->m_xType
->show();
2242 m_aCmisPropertiesLines
.push_back( std::move(pNewLine
) );
2245 Sequence
< document::CmisProperty
> CmisPropertiesWindow::GetCmisProperties() const
2247 Sequence
< document::CmisProperty
> aPropertiesSeq( m_aCmisPropertiesLines
.size() );
2248 auto aPropertiesSeqRange
= asNonConstRange(aPropertiesSeq
);
2250 for ( auto& rxLine
: m_aCmisPropertiesLines
)
2252 CmisPropertyLine
* pLine
= rxLine
.get();
2254 aPropertiesSeqRange
[i
].Id
= pLine
->m_sId
;
2255 aPropertiesSeqRange
[i
].Type
= pLine
->m_sType
;
2256 aPropertiesSeqRange
[i
].Updatable
= pLine
->m_bUpdatable
;
2257 aPropertiesSeqRange
[i
].Required
= pLine
->m_bRequired
;
2258 aPropertiesSeqRange
[i
].OpenChoice
= pLine
->m_bOpenChoice
;
2259 aPropertiesSeqRange
[i
].MultiValued
= pLine
->m_bMultiValued
;
2261 OUString sPropertyName
= pLine
->m_xName
->get_label();
2262 if ( !sPropertyName
.isEmpty() )
2264 aPropertiesSeqRange
[i
].Name
= sPropertyName
;
2265 OUString sType
= pLine
->m_xType
->get_label();
2266 if ( CMIS_TYPE_DECIMAL
== sType
)
2268 sal_uInt32 nIndex
= const_cast< SvNumberFormatter
& >(
2269 m_aNumberFormatter
).GetFormatIndex( NF_NUMBER_SYSTEM
);
2270 Sequence
< double > seqValue( pLine
->m_aValues
.size( ) );
2271 auto seqValueRange
= asNonConstRange(seqValue
);
2273 for ( const auto& rxValue
: pLine
->m_aValues
)
2275 double dValue
= 0.0;
2276 OUString
sValue( rxValue
->m_xValueEdit
->get_text() );
2277 bool bIsNum
= const_cast< SvNumberFormatter
& >( m_aNumberFormatter
).
2278 IsNumberFormat( sValue
, nIndex
, dValue
);
2280 seqValueRange
[k
] = dValue
;
2283 aPropertiesSeqRange
[i
].Value
<<= seqValue
;
2285 else if ( CMIS_TYPE_INTEGER
== sType
)
2287 sal_uInt32 nIndex
= const_cast< SvNumberFormatter
& >(
2288 m_aNumberFormatter
).GetFormatIndex( NF_NUMBER_SYSTEM
);
2289 Sequence
< sal_Int64
> seqValue( pLine
->m_aValues
.size( ) );
2290 auto seqValueRange
= asNonConstRange(seqValue
);
2292 for ( const auto& rxValue
: pLine
->m_aValues
)
2295 OUString
sValue( rxValue
->m_xValueEdit
->get_text() );
2296 bool bIsNum
= const_cast< SvNumberFormatter
& >( m_aNumberFormatter
).
2297 IsNumberFormat( sValue
, nIndex
, dValue
);
2299 seqValueRange
[k
] = static_cast<sal_Int64
>(dValue
);
2302 aPropertiesSeqRange
[i
].Value
<<= seqValue
;
2304 else if ( CMIS_TYPE_BOOL
== sType
)
2306 Sequence
<sal_Bool
> seqValue( pLine
->m_aYesNos
.size( ) );
2307 sal_Bool
* pseqValue
= seqValue
.getArray();
2309 for ( const auto& rxYesNo
: pLine
->m_aYesNos
)
2311 bool bValue
= rxYesNo
->m_xYesButton
->get_active();
2312 pseqValue
[k
] = bValue
;
2315 aPropertiesSeqRange
[i
].Value
<<= seqValue
;
2318 else if ( CMIS_TYPE_DATETIME
== sType
)
2320 Sequence
< util::DateTime
> seqValue( pLine
->m_aDateTimes
.size( ) );
2321 auto seqValueRange
= asNonConstRange(seqValue
);
2323 for ( const auto& rxDateTime
: pLine
->m_aDateTimes
)
2325 Date aTmpDate
= rxDateTime
->m_xDateField
->get_date();
2326 tools::Time aTmpTime
= rxDateTime
->m_xFormatter
->GetTime();
2327 util::DateTime
aDateTime( aTmpTime
.GetNanoSec(), aTmpTime
.GetSec(),
2328 aTmpTime
.GetMin(), aTmpTime
.GetHour(),
2329 aTmpDate
.GetDay(), aTmpDate
.GetMonth(),
2330 aTmpDate
.GetYear(), true );
2331 seqValueRange
[k
] = aDateTime
;
2334 aPropertiesSeqRange
[i
].Value
<<= seqValue
;
2338 Sequence
< OUString
> seqValue( pLine
->m_aValues
.size( ) );
2339 auto seqValueRange
= asNonConstRange(seqValue
);
2341 for ( const auto& rxValue
: pLine
->m_aValues
)
2343 OUString
sValue( rxValue
->m_xValueEdit
->get_text() );
2344 seqValueRange
[k
] = sValue
;
2347 aPropertiesSeqRange
[i
].Value
<<= seqValue
;
2353 return aPropertiesSeq
;
2356 CmisPropertiesControl::CmisPropertiesControl(weld::Builder
& rBuilder
)
2357 : m_aPropertiesWin(rBuilder
.weld_container("CmisWindow"))
2358 , m_xScrolledWindow(rBuilder
.weld_scrolled_window("CmisScroll"))
2360 // set height to something small and force it to take the size
2361 // dictated by the other pages
2362 m_xScrolledWindow
->set_size_request(-1, 42);
2365 void CmisPropertiesControl::ClearAllLines()
2367 m_aPropertiesWin
.ClearAllLines();
2370 void CmisPropertiesControl::AddLine( const OUString
& sId
, const OUString
& sName
,
2371 const OUString
& sType
, const bool bUpdatable
,
2372 const bool bRequired
, const bool bMultiValued
,
2373 const bool bOpenChoice
, Any
& aChoices
, Any
const & rAny
2376 m_aPropertiesWin
.AddLine( sId
, sName
, sType
, bUpdatable
, bRequired
, bMultiValued
,
2377 bOpenChoice
, aChoices
, rAny
);
2380 // class SfxCmisPropertiesPage -----------------------------------------
2381 SfxCmisPropertiesPage::SfxCmisPropertiesPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rItemSet
)
2382 : SfxTabPage(pPage
, pController
, "sfx/ui/cmisinfopage.ui", "CmisInfoPage", &rItemSet
)
2383 , m_xPropertiesCtrl(new CmisPropertiesControl(*m_xBuilder
))
2387 SfxCmisPropertiesPage::~SfxCmisPropertiesPage()
2389 m_xPropertiesCtrl
.reset();
2392 bool SfxCmisPropertiesPage::FillItemSet( SfxItemSet
* rSet
)
2394 const SfxDocumentInfoItem
* pItem
= nullptr;
2395 SfxDocumentInfoItem
* pInfo
= nullptr;
2396 bool bMustDelete
= false;
2398 if (const SfxItemSet
* pItemSet
= GetDialogExampleSet())
2400 pItem
= pItemSet
->GetItemIfSet(SID_DOCINFO
);
2402 pInfo
= const_cast<SfxDocumentInfoItem
*>(&rSet
->Get( SID_DOCINFO
));
2406 pInfo
= new SfxDocumentInfoItem( *pItem
);
2410 sal_Int32 modifiedNum
= 0;
2413 Sequence
< document::CmisProperty
> aOldProps
= pInfo
->GetCmisProperties( );
2414 Sequence
< document::CmisProperty
> aNewProps
= m_xPropertiesCtrl
->GetCmisProperties();
2416 std::vector
< document::CmisProperty
> changedProps
;
2417 for ( sal_Int32 i
= 0; i
< aNewProps
.getLength( ); ++i
)
2419 if ( aOldProps
[i
].Updatable
&& !aNewProps
[i
].Id
.isEmpty( ) )
2421 if ( aOldProps
[i
].Type
== CMIS_TYPE_DATETIME
)
2423 Sequence
< util::DateTime
> oldValue
;
2424 aOldProps
[i
].Value
>>= oldValue
;
2425 // We only edit hours and minutes
2426 // don't compare NanoSeconds and Seconds
2427 for ( auto& rDateTime
: asNonConstRange(oldValue
) )
2429 rDateTime
.NanoSeconds
= 0;
2430 rDateTime
.Seconds
= 0;
2432 Sequence
< util::DateTime
> newValue
;
2433 aNewProps
[i
].Value
>>= newValue
;
2434 if ( oldValue
!= newValue
)
2437 changedProps
.push_back( aNewProps
[i
] );
2440 else if ( aOldProps
[i
].Value
!= aNewProps
[i
].Value
)
2443 changedProps
.push_back( aNewProps
[i
] );
2447 Sequence
< document::CmisProperty
> aModifiedProps( comphelper::containerToSequence(changedProps
) );
2448 pInfo
->SetCmisProperties( aModifiedProps
);
2449 rSet
->Put( *pInfo
);
2457 void SfxCmisPropertiesPage::Reset( const SfxItemSet
* rItemSet
)
2459 m_xPropertiesCtrl
->ClearAllLines();
2460 const SfxDocumentInfoItem
& rInfoItem
= rItemSet
->Get(SID_DOCINFO
);
2461 uno::Sequence
< document::CmisProperty
> aCmisProps
= rInfoItem
.GetCmisProperties();
2462 for ( auto& rCmisProp
: asNonConstRange(aCmisProps
) )
2464 m_xPropertiesCtrl
->AddLine(rCmisProp
.Id
,
2467 rCmisProp
.Updatable
,
2469 rCmisProp
.MultiValued
,
2470 rCmisProp
.OpenChoice
,
2476 DeactivateRC
SfxCmisPropertiesPage::DeactivatePage( SfxItemSet
* /*pSet*/ )
2478 return DeactivateRC::LeavePage
;
2481 std::unique_ptr
<SfxTabPage
> SfxCmisPropertiesPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
* rItemSet
)
2483 return std::make_unique
<SfxCmisPropertiesPage
>(pPage
, pController
, *rItemSet
);
2486 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */