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>
24 #include <vcl/svapp.hxx>
25 #include <vcl/weld.hxx>
26 #include <vcl/weldutils.hxx>
27 #include <unotools/datetime.hxx>
28 #include <unotools/localedatawrapper.hxx>
29 #include <unotools/cmdoptions.hxx>
30 #include <comphelper/processfactory.hxx>
31 #include <comphelper/xmlsechelper.hxx>
32 #include <unotools/useroptions.hxx>
33 #include <svtools/ctrlbox.hxx>
34 #include <svtools/imagemgr.hxx>
35 #include <sal/log.hxx>
36 #include <osl/diagnose.h>
40 #include <comphelper/sequence.hxx>
41 #include <comphelper/string.hxx>
42 #include <com/sun/star/security/DocumentSignatureInformation.hpp>
43 #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
44 #include <unotools/syslocale.hxx>
45 #include <rtl/math.hxx>
46 #include <com/sun/star/beans/PropertyAttribute.hpp>
47 #include <com/sun/star/beans/XPropertyContainer.hpp>
48 #include <com/sun/star/beans/XPropertySet.hpp>
49 #include <com/sun/star/util/DateTime.hpp>
50 #include <com/sun/star/util/Date.hpp>
51 #include <com/sun/star/util/DateTimeWithTimezone.hpp>
52 #include <com/sun/star/util/DateWithTimezone.hpp>
53 #include <com/sun/star/util/Duration.hpp>
54 #include <com/sun/star/document/XDocumentProperties.hpp>
55 #include <com/sun/star/document/CmisProperty.hpp>
57 #include <vcl/timer.hxx>
58 #include <vcl/settings.hxx>
59 #include <sfx2/sfxresid.hxx>
60 #include <sfx2/frame.hxx>
61 #include <sfx2/filedlghelper.hxx>
62 #include <sfx2/dinfdlg.hxx>
63 #include <sfx2/sfxsids.hrc>
65 #include <sfx2/objsh.hxx>
66 #include <sfx2/docfile.hxx>
68 #include <documentfontsdialog.hxx>
69 #include <dinfdlg.hrc>
70 #include <sfx2/strings.hrc>
71 #include <strings.hxx>
72 #include <tools/diagnose_ex.h>
73 #include "securitypage.hxx"
77 using namespace ::com::sun::star
;
78 using namespace ::com::sun::star::lang
;
79 using namespace ::com::sun::star::ui::dialogs
;
80 using namespace ::com::sun::star::uno
;
85 css::uno::Any m_aValue
;
87 CustomProperty( const OUString
& sName
, const css::uno::Any
& rValue
) :
88 m_sName( sName
), m_aValue( rValue
) {}
91 SfxPoolItem
* SfxDocumentInfoItem::CreateDefault() { return new SfxDocumentInfoItem
; }
95 OUString
CreateSizeText( sal_Int64 nSize
)
97 OUString aUnitStr
= " " + SfxResId(STR_BYTES
);
98 sal_Int64 nSize1
= nSize
;
99 sal_Int64 nSize2
= nSize1
;
100 sal_Int64 nMega
= 1024 * 1024;
101 sal_Int64 nGiga
= nMega
* 1024;
102 double fSize
= nSize
;
105 if ( nSize1
>= 10000 && nSize1
< nMega
)
108 aUnitStr
= " " + SfxResId(STR_KB
);
112 else if ( nSize1
>= nMega
&& nSize1
< nGiga
)
115 aUnitStr
= " " + SfxResId(STR_MB
);
119 else if ( nSize1
>= nGiga
)
122 aUnitStr
= " " + SfxResId(STR_GB
);
126 const SvtSysLocale aSysLocale
;
127 const LocaleDataWrapper
& rLocaleWrapper
= aSysLocale
.GetLocaleData();
128 OUString aSizeStr
= rLocaleWrapper
.getNum( nSize1
, 0 ) + aUnitStr
;
129 if ( nSize1
< nSize2
)
131 aSizeStr
= ::rtl::math::doubleToUString( fSize
,
132 rtl_math_StringFormat_F
, nDec
,
133 rLocaleWrapper
.getNumDecimalSep()[0] )
136 + rLocaleWrapper
.getNum( nSize2
, 0 )
138 + SfxResId(STR_BYTES
)
144 OUString
ConvertDateTime_Impl( const OUString
& rName
,
145 const util::DateTime
& uDT
, const LocaleDataWrapper
& rWrapper
)
149 const OUString
aDelim( ", " );
150 OUString aStr
= rWrapper
.getDate( aD
)
152 + rWrapper
.getTime( aT
);
153 OUString aAuthor
= comphelper::string::stripStart(rName
, ' ');
154 if (!aAuthor
.isEmpty())
156 aStr
+= aDelim
+ aAuthor
;
164 SfxDocumentInfoItem::SfxDocumentInfoItem()
168 , m_isAutoloadEnabled(false)
174 , m_ModificationDate()
178 , m_EditingDuration(0)
183 , m_bHasTemplate( true )
184 , m_bDeleteUserData( false )
185 , m_bUseUserData( true )
186 , m_bUseThumbnailSave( true )
190 SfxDocumentInfoItem::SfxDocumentInfoItem( const OUString
& rFile
,
191 const uno::Reference
<document::XDocumentProperties
>& i_xDocProps
,
192 const uno::Sequence
<document::CmisProperty
>& i_cmisProps
,
193 bool bIs
, bool _bIs
)
194 : SfxStringItem( SID_DOCINFO
, rFile
)
195 , m_AutoloadDelay( i_xDocProps
->getAutoloadSecs() )
196 , m_AutoloadURL( i_xDocProps
->getAutoloadURL() )
197 , m_isAutoloadEnabled( (m_AutoloadDelay
> 0) || !m_AutoloadURL
.isEmpty() )
198 , m_DefaultTarget( i_xDocProps
->getDefaultTarget() )
199 , m_TemplateName( i_xDocProps
->getTemplateName() )
200 , m_Author( i_xDocProps
->getAuthor() )
201 , m_CreationDate( i_xDocProps
->getCreationDate() )
202 , m_ModifiedBy( i_xDocProps
->getModifiedBy() )
203 , m_ModificationDate( i_xDocProps
->getModificationDate() )
204 , m_PrintedBy( i_xDocProps
->getPrintedBy() )
205 , m_PrintDate( i_xDocProps
->getPrintDate() )
206 , m_EditingCycles( i_xDocProps
->getEditingCycles() )
207 , m_EditingDuration( i_xDocProps
->getEditingDuration() )
208 , m_Description( i_xDocProps
->getDescription() )
209 , m_Keywords( ::comphelper::string::convertCommaSeparated(
210 i_xDocProps
->getKeywords()) )
211 , m_Subject( i_xDocProps
->getSubject() )
212 , m_Title( i_xDocProps
->getTitle() )
213 , m_bHasTemplate( true )
214 , m_bDeleteUserData( false )
215 , m_bUseUserData( bIs
)
216 , m_bUseThumbnailSave( _bIs
)
220 Reference
< beans::XPropertyContainer
> xContainer
= i_xDocProps
->getUserDefinedProperties();
221 if ( xContainer
.is() )
223 Reference
< beans::XPropertySet
> xSet( xContainer
, UNO_QUERY
);
224 const Sequence
< beans::Property
> lProps
= xSet
->getPropertySetInfo()->getProperties();
225 for ( const beans::Property
& rProp
: lProps
)
227 // "fix" property? => not a custom property => ignore it!
228 if (!(rProp
.Attributes
& css::beans::PropertyAttribute::REMOVABLE
))
230 SAL_WARN( "sfx.dialog", "non-removable user-defined property?");
234 uno::Any aValue
= xSet
->getPropertyValue(rProp
.Name
);
235 std::unique_ptr
<CustomProperty
> pProp(new CustomProperty( rProp
.Name
, aValue
));
236 m_aCustomProperties
.push_back( std::move(pProp
) );
240 // get CMIS properties
241 m_aCmisProperties
= i_cmisProps
;
243 catch ( Exception
& ) {}
247 SfxDocumentInfoItem::SfxDocumentInfoItem( const SfxDocumentInfoItem
& rItem
)
248 : SfxStringItem( rItem
)
249 , m_AutoloadDelay( rItem
.getAutoloadDelay() )
250 , m_AutoloadURL( rItem
.getAutoloadURL() )
251 , m_isAutoloadEnabled( rItem
.isAutoloadEnabled() )
252 , m_DefaultTarget( rItem
.getDefaultTarget() )
253 , m_TemplateName( rItem
.getTemplateName() )
254 , m_Author( rItem
.getAuthor() )
255 , m_CreationDate( rItem
.getCreationDate() )
256 , m_ModifiedBy( rItem
.getModifiedBy() )
257 , m_ModificationDate( rItem
.getModificationDate() )
258 , m_PrintedBy( rItem
.getPrintedBy() )
259 , m_PrintDate( rItem
.getPrintDate() )
260 , m_EditingCycles( rItem
.getEditingCycles() )
261 , m_EditingDuration( rItem
.getEditingDuration() )
262 , m_Description( rItem
.getDescription() )
263 , m_Keywords( rItem
.getKeywords() )
264 , m_Subject( rItem
.getSubject() )
265 , m_Title( rItem
.getTitle() )
266 , m_bHasTemplate( rItem
.m_bHasTemplate
)
267 , m_bDeleteUserData( rItem
.m_bDeleteUserData
)
268 , m_bUseUserData( rItem
.m_bUseUserData
)
269 , m_bUseThumbnailSave( rItem
.m_bUseThumbnailSave
)
271 for (auto const & pOtherProp
: rItem
.m_aCustomProperties
)
273 std::unique_ptr
<CustomProperty
> pProp(new CustomProperty( pOtherProp
->m_sName
,
274 pOtherProp
->m_aValue
));
275 m_aCustomProperties
.push_back( std::move(pProp
) );
278 m_aCmisProperties
= rItem
.m_aCmisProperties
;
281 SfxDocumentInfoItem::~SfxDocumentInfoItem()
283 ClearCustomProperties();
286 SfxDocumentInfoItem
* SfxDocumentInfoItem::Clone( SfxItemPool
* ) const
288 return new SfxDocumentInfoItem( *this );
291 bool SfxDocumentInfoItem::operator==( const SfxPoolItem
& rItem
) const
293 if (!SfxStringItem::operator==(rItem
))
295 const SfxDocumentInfoItem
& rInfoItem(static_cast<const SfxDocumentInfoItem
&>(rItem
));
298 m_AutoloadDelay
== rInfoItem
.m_AutoloadDelay
&&
299 m_AutoloadURL
== rInfoItem
.m_AutoloadURL
&&
300 m_isAutoloadEnabled
== rInfoItem
.m_isAutoloadEnabled
&&
301 m_DefaultTarget
== rInfoItem
.m_DefaultTarget
&&
302 m_Author
== rInfoItem
.m_Author
&&
303 m_CreationDate
== rInfoItem
.m_CreationDate
&&
304 m_ModifiedBy
== rInfoItem
.m_ModifiedBy
&&
305 m_ModificationDate
== rInfoItem
.m_ModificationDate
&&
306 m_PrintedBy
== rInfoItem
.m_PrintedBy
&&
307 m_PrintDate
== rInfoItem
.m_PrintDate
&&
308 m_EditingCycles
== rInfoItem
.m_EditingCycles
&&
309 m_EditingDuration
== rInfoItem
.m_EditingDuration
&&
310 m_Description
== rInfoItem
.m_Description
&&
311 m_Keywords
== rInfoItem
.m_Keywords
&&
312 m_Subject
== rInfoItem
.m_Subject
&&
313 m_Title
== rInfoItem
.m_Title
&&
314 m_aCustomProperties
.size() == rInfoItem
.m_aCustomProperties
.size() &&
315 std::equal(m_aCustomProperties
.begin(), m_aCustomProperties
.end(),
316 rInfoItem
.m_aCustomProperties
.begin()) &&
317 m_aCmisProperties
.getLength() == rInfoItem
.m_aCmisProperties
.getLength();
321 void SfxDocumentInfoItem::resetUserData(const OUString
& i_rAuthor
)
323 m_Author
= i_rAuthor
;
324 DateTime
now( DateTime::SYSTEM
);
325 m_CreationDate
= now
.GetUNODateTime();
326 m_ModifiedBy
= OUString();
327 m_PrintedBy
= OUString();
328 m_ModificationDate
= util::DateTime();
329 m_PrintDate
= util::DateTime();
330 m_EditingDuration
= 0;
335 void SfxDocumentInfoItem::UpdateDocumentInfo(
336 const uno::Reference
<document::XDocumentProperties
>& i_xDocProps
,
337 bool i_bDoNotUpdateUserDefined
) const
339 if (isAutoloadEnabled()) {
340 i_xDocProps
->setAutoloadSecs(getAutoloadDelay());
341 i_xDocProps
->setAutoloadURL(getAutoloadURL());
343 i_xDocProps
->setAutoloadSecs(0);
344 i_xDocProps
->setAutoloadURL(OUString());
346 i_xDocProps
->setDefaultTarget(getDefaultTarget());
347 i_xDocProps
->setAuthor(getAuthor());
348 i_xDocProps
->setCreationDate(getCreationDate());
349 i_xDocProps
->setModifiedBy(getModifiedBy());
350 i_xDocProps
->setModificationDate(getModificationDate());
351 i_xDocProps
->setPrintedBy(getPrintedBy());
352 i_xDocProps
->setPrintDate(getPrintDate());
353 i_xDocProps
->setEditingCycles(getEditingCycles());
354 i_xDocProps
->setEditingDuration(getEditingDuration());
355 i_xDocProps
->setDescription(getDescription());
356 i_xDocProps
->setKeywords(
357 ::comphelper::string::convertCommaSeparated(getKeywords()));
358 i_xDocProps
->setSubject(getSubject());
359 i_xDocProps
->setTitle(getTitle());
361 // this is necessary in case of replaying a recorded macro:
362 // in this case, the macro may contain the 4 old user-defined DocumentInfo
363 // fields, but not any of the DocumentInfo properties;
364 // as a consequence, most of the UserDefined properties of the
365 // DocumentProperties would be summarily deleted here, which does not
366 // seem like a good idea.
367 if (i_bDoNotUpdateUserDefined
)
372 Reference
< beans::XPropertyContainer
> xContainer
= i_xDocProps
->getUserDefinedProperties();
373 Reference
< beans::XPropertySet
> xSet( xContainer
, UNO_QUERY
);
374 Reference
< beans::XPropertySetInfo
> xSetInfo
= xSet
->getPropertySetInfo();
375 const Sequence
< beans::Property
> lProps
= xSetInfo
->getProperties();
376 for ( const beans::Property
& rProp
: lProps
)
378 if (rProp
.Attributes
& css::beans::PropertyAttribute::REMOVABLE
)
380 xContainer
->removeProperty( rProp
.Name
);
384 for (auto const & pProp
: m_aCustomProperties
)
388 xContainer
->addProperty( pProp
->m_sName
,
389 beans::PropertyAttribute::REMOVABLE
, pProp
->m_aValue
);
391 catch ( Exception
const & )
393 TOOLS_WARN_EXCEPTION( "sfx.dialog", "SfxDocumentInfoItem::updateDocumentInfo(): exception while adding custom properties" );
397 catch ( Exception
const & )
399 TOOLS_WARN_EXCEPTION( "sfx.dialog", "SfxDocumentInfoItem::updateDocumentInfo(): exception while removing custom properties" );
404 void SfxDocumentInfoItem::SetDeleteUserData( bool bSet
)
406 m_bDeleteUserData
= bSet
;
410 void SfxDocumentInfoItem::SetUseUserData( bool bSet
)
412 m_bUseUserData
= bSet
;
415 void SfxDocumentInfoItem::SetUseThumbnailSave( bool bSet
)
417 m_bUseThumbnailSave
= bSet
;
420 std::vector
< std::unique_ptr
<CustomProperty
> > SfxDocumentInfoItem::GetCustomProperties() const
422 std::vector
< std::unique_ptr
<CustomProperty
> > aRet
;
423 for (auto const & pOtherProp
: m_aCustomProperties
)
425 std::unique_ptr
<CustomProperty
> pProp(new CustomProperty( pOtherProp
->m_sName
,
426 pOtherProp
->m_aValue
));
427 aRet
.push_back( std::move(pProp
) );
433 void SfxDocumentInfoItem::ClearCustomProperties()
435 m_aCustomProperties
.clear();
438 void SfxDocumentInfoItem::AddCustomProperty( const OUString
& sName
, const Any
& rValue
)
440 std::unique_ptr
<CustomProperty
> pProp(new CustomProperty( sName
, rValue
));
441 m_aCustomProperties
.push_back( std::move(pProp
) );
445 void SfxDocumentInfoItem::SetCmisProperties( const Sequence
< document::CmisProperty
>& cmisProps
)
447 m_aCmisProperties
= cmisProps
;
450 bool SfxDocumentInfoItem::QueryValue( Any
& rVal
, sal_uInt8 nMemberId
) const
453 sal_Int32 nValue
= 0;
456 bool bIsString
= false;
457 nMemberId
&= ~CONVERT_TWIPS
;
460 case MID_DOCINFO_USEUSERDATA
:
461 bValue
= IsUseUserData();
463 case MID_DOCINFO_USETHUMBNAILSAVE
:
464 bValue
= IsUseThumbnailSave();
466 case MID_DOCINFO_DELETEUSERDATA
:
467 bValue
= m_bDeleteUserData
;
469 case MID_DOCINFO_AUTOLOADENABLED
:
470 bValue
= isAutoloadEnabled();
472 case MID_DOCINFO_AUTOLOADSECS
:
474 nValue
= getAutoloadDelay();
476 case MID_DOCINFO_AUTOLOADURL
:
478 aValue
= getAutoloadURL();
480 case MID_DOCINFO_DEFAULTTARGET
:
482 aValue
= getDefaultTarget();
484 case MID_DOCINFO_DESCRIPTION
:
486 aValue
= getDescription();
488 case MID_DOCINFO_KEYWORDS
:
490 aValue
= getKeywords();
492 case MID_DOCINFO_SUBJECT
:
494 aValue
= getSubject();
496 case MID_DOCINFO_TITLE
:
501 OSL_FAIL("Wrong MemberId!");
514 bool SfxDocumentInfoItem::PutValue( const Any
& rVal
, sal_uInt8 nMemberId
)
520 nMemberId
&= ~CONVERT_TWIPS
;
523 case MID_DOCINFO_USEUSERDATA
:
524 bRet
= (rVal
>>= bValue
);
526 SetUseUserData( bValue
);
528 case MID_DOCINFO_USETHUMBNAILSAVE
:
529 bRet
= (rVal
>>=bValue
);
531 SetUseThumbnailSave( bValue
);
533 case MID_DOCINFO_DELETEUSERDATA
:
534 // QUESTION: deleting user data was done here; seems to be superfluous!
535 bRet
= (rVal
>>= bValue
);
537 SetDeleteUserData( bValue
);
539 case MID_DOCINFO_AUTOLOADENABLED
:
540 bRet
= (rVal
>>= bValue
);
542 m_isAutoloadEnabled
= bValue
;
544 case MID_DOCINFO_AUTOLOADSECS
:
545 bRet
= (rVal
>>= nValue
);
547 m_AutoloadDelay
= nValue
;
549 case MID_DOCINFO_AUTOLOADURL
:
550 bRet
= (rVal
>>= aValue
);
552 m_AutoloadURL
= aValue
;
554 case MID_DOCINFO_DEFAULTTARGET
:
555 bRet
= (rVal
>>= aValue
);
557 m_DefaultTarget
= aValue
;
559 case MID_DOCINFO_DESCRIPTION
:
560 bRet
= (rVal
>>= aValue
);
562 setDescription(aValue
);
564 case MID_DOCINFO_KEYWORDS
:
565 bRet
= (rVal
>>= aValue
);
569 case MID_DOCINFO_SUBJECT
:
570 bRet
= (rVal
>>= aValue
);
574 case MID_DOCINFO_TITLE
:
575 bRet
= (rVal
>>= aValue
);
580 OSL_FAIL("Wrong MemberId!");
587 SfxDocumentDescPage::SfxDocumentDescPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rItemSet
)
588 : SfxTabPage(pPage
, pController
, "sfx/ui/descriptioninfopage.ui", "DescriptionInfoPage", &rItemSet
)
589 , m_pInfoItem(nullptr)
590 , m_xTitleEd(m_xBuilder
->weld_entry("title"))
591 , m_xThemaEd(m_xBuilder
->weld_entry("subject"))
592 , m_xKeywordsEd(m_xBuilder
->weld_entry("keywords"))
593 , m_xCommentEd(m_xBuilder
->weld_text_view("comments"))
595 m_xCommentEd
->set_size_request(m_xKeywordsEd
->get_preferred_size().Width(),
596 m_xCommentEd
->get_height_rows(16));
599 SfxDocumentDescPage::~SfxDocumentDescPage()
603 std::unique_ptr
<SfxTabPage
> SfxDocumentDescPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
*rItemSet
)
605 return std::make_unique
<SfxDocumentDescPage
>(pPage
, pController
, *rItemSet
);
608 bool SfxDocumentDescPage::FillItemSet(SfxItemSet
*rSet
)
610 // Test whether a change is present
611 const bool bTitleMod
= m_xTitleEd
->get_value_changed_from_saved();
612 const bool bThemeMod
= m_xThemaEd
->get_value_changed_from_saved();
613 const bool bKeywordsMod
= m_xKeywordsEd
->get_value_changed_from_saved();
614 const bool bCommentMod
= m_xCommentEd
->get_value_changed_from_saved();
615 if ( !( bTitleMod
|| bThemeMod
|| bKeywordsMod
|| bCommentMod
) )
620 // Generating the output data
621 const SfxPoolItem
* pItem
= nullptr;
622 SfxDocumentInfoItem
* pInfo
= nullptr;
623 const SfxItemSet
* pExSet
= GetDialogExampleSet();
625 if ( pExSet
&& SfxItemState::SET
!= pExSet
->GetItemState( SID_DOCINFO
, true, &pItem
) )
628 pInfo
= new SfxDocumentInfoItem( *static_cast<const SfxDocumentInfoItem
*>(pItem
) );
632 SAL_WARN( "sfx.dialog", "SfxDocumentDescPage::FillItemSet(): no item found" );
638 pInfo
->setTitle( m_xTitleEd
->get_text() );
642 pInfo
->setSubject( m_xThemaEd
->get_text() );
646 pInfo
->setKeywords( m_xKeywordsEd
->get_text() );
650 pInfo
->setDescription( m_xCommentEd
->get_text() );
653 if ( pInfo
!= m_pInfoItem
)
661 void SfxDocumentDescPage::Reset(const SfxItemSet
*rSet
)
663 m_pInfoItem
= const_cast<SfxDocumentInfoItem
*>(&rSet
->Get(SID_DOCINFO
));
665 m_xTitleEd
->set_text(m_pInfoItem
->getTitle());
666 m_xThemaEd
->set_text(m_pInfoItem
->getSubject());
667 m_xKeywordsEd
->set_text(m_pInfoItem
->getKeywords());
668 m_xCommentEd
->set_text(m_pInfoItem
->getDescription());
670 m_xTitleEd
->save_value();
671 m_xThemaEd
->save_value();
672 m_xKeywordsEd
->save_value();
673 m_xCommentEd
->save_value();
675 const SfxBoolItem
* pROItem
= SfxItemSet::GetItem
<SfxBoolItem
>(rSet
, SID_DOC_READONLY
, false);
676 if (pROItem
&& pROItem
->GetValue())
678 m_xTitleEd
->set_editable(false);
679 m_xThemaEd
->set_editable(false);
680 m_xKeywordsEd
->set_editable(false);
681 m_xCommentEd
->set_editable(false);
685 SfxDocumentPage::SfxDocumentPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rItemSet
)
686 : SfxTabPage(pPage
, pController
, "sfx/ui/documentinfopage.ui", "DocumentInfoPage", &rItemSet
)
687 , bEnableUseUserData( false )
688 , bHandleDelete( false )
689 , m_xBmp(m_xBuilder
->weld_image("icon"))
690 , m_xNameED(m_xBuilder
->weld_label("nameed"))
691 , m_xChangePassBtn(m_xBuilder
->weld_button("changepass"))
692 , m_xShowTypeFT(m_xBuilder
->weld_label("showtype"))
693 , m_xFileValEd(m_xBuilder
->weld_label("showlocation"))
694 , m_xShowSizeFT(m_xBuilder
->weld_label("showsize"))
695 , m_xCreateValFt(m_xBuilder
->weld_label("showcreate"))
696 , m_xChangeValFt(m_xBuilder
->weld_label("showmodify"))
697 , m_xSignedValFt(m_xBuilder
->weld_label("showsigned"))
698 , m_xSignatureBtn(m_xBuilder
->weld_button("signature"))
699 , m_xPrintValFt(m_xBuilder
->weld_label("showprint"))
700 , m_xTimeLogValFt(m_xBuilder
->weld_label("showedittime"))
701 , m_xDocNoValFt(m_xBuilder
->weld_label("showrevision"))
702 , m_xUseUserDataCB(m_xBuilder
->weld_check_button("userdatacb"))
703 , m_xDeleteBtn(m_xBuilder
->weld_button("reset"))
704 , m_xUseThumbnailSaveCB(m_xBuilder
->weld_check_button("thumbnailsavecb"))
705 , m_xTemplFt(m_xBuilder
->weld_label("templateft"))
706 , m_xTemplValFt(m_xBuilder
->weld_label("showtemplate"))
708 m_aUnknownSize
= m_xShowSizeFT
->get_label();
709 m_xShowSizeFT
->set_label(OUString());
711 m_aMultiSignedStr
= m_xSignedValFt
->get_label();
712 m_xSignedValFt
->set_label(OUString());
714 ImplUpdateSignatures();
715 ImplCheckPasswordState();
716 m_xChangePassBtn
->connect_clicked( LINK( this, SfxDocumentPage
, ChangePassHdl
) );
717 m_xSignatureBtn
->connect_clicked( LINK( this, SfxDocumentPage
, SignatureHdl
) );
718 m_xDeleteBtn
->connect_clicked( LINK( this, SfxDocumentPage
, DeleteHdl
) );
720 // [i96288] Check if the document signature command is enabled
721 // on the main list enable/disable the pushbutton accordingly
722 SvtCommandOptions aCmdOptions
;
723 if ( aCmdOptions
.Lookup( SvtCommandOptions::CMDOPTION_DISABLED
, "Signature" ) )
724 m_xSignatureBtn
->set_sensitive(false);
727 SfxDocumentPage::~SfxDocumentPage()
731 IMPL_LINK_NOARG(SfxDocumentPage
, DeleteHdl
, weld::Button
&, void)
734 if (bEnableUseUserData
&& m_xUseUserDataCB
->get_active())
735 aName
= SvtUserOptions().GetFullName();
736 const LocaleDataWrapper
& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
737 DateTime
now( DateTime::SYSTEM
);
738 util::DateTime
uDT( now
.GetUNODateTime() );
739 m_xCreateValFt
->set_label( ConvertDateTime_Impl( aName
, uDT
, rLocaleWrapper
) );
740 m_xChangeValFt
->set_label( "" );
741 m_xPrintValFt
->set_label( "" );
742 const tools::Time
aTime( 0 );
743 m_xTimeLogValFt
->set_label( rLocaleWrapper
.getDuration( aTime
) );
744 m_xDocNoValFt
->set_label(OUString('1'));
745 bHandleDelete
= true;
748 IMPL_LINK_NOARG(SfxDocumentPage
, SignatureHdl
, weld::Button
&, void)
750 SfxObjectShell
* pDoc
= SfxObjectShell::Current();
753 pDoc
->SignDocumentContent(GetFrameWeld());
755 ImplUpdateSignatures();
759 IMPL_LINK_NOARG(SfxDocumentPage
, ChangePassHdl
, weld::Button
&, void)
761 SfxObjectShell
* pShell
= SfxObjectShell::Current();
766 SfxItemSet
* pMedSet
= pShell
->GetMedium()->GetItemSet();
769 std::shared_ptr
<const SfxFilter
> pFilter
= pShell
->GetMedium()->GetFilter();
773 sfx2::RequestPassword(pFilter
, OUString(), pMedSet
, GetFrameWeld()->GetXWindow());
774 pShell
->SetModified();
779 void SfxDocumentPage::ImplUpdateSignatures()
781 SfxObjectShell
* pDoc
= SfxObjectShell::Current();
785 SfxMedium
* pMedium
= pDoc
->GetMedium();
786 if ( !pMedium
|| pMedium
->GetName().isEmpty() || !pMedium
->GetStorage().is() )
789 Reference
< security::XDocumentDigitalSignatures
> xD
;
792 xD
= security::DocumentDigitalSignatures::createDefault(comphelper::getProcessComponentContext());
793 xD
->setParentWindow(GetDialogController()->getDialog()->GetXWindow());
795 catch ( const css::uno::DeploymentException
& )
799 Sequence
< security::DocumentSignatureInformation
> aInfos
;
802 aInfos
= xD
->verifyDocumentContentSignatures( pMedium
->GetZipStorageToSign_Impl(),
803 uno::Reference
< io::XInputStream
>() );
804 if ( aInfos
.getLength() > 1 )
805 s
= m_aMultiSignedStr
;
806 else if ( aInfos
.getLength() == 1 )
808 const security::DocumentSignatureInformation
& rInfo
= aInfos
[ 0 ];
809 s
= utl::GetDateTimeString( rInfo
.SignatureDate
, rInfo
.SignatureTime
) + ", " +
810 comphelper::xmlsec::GetContentPart(rInfo
.Signer
->getSubjectName(), rInfo
.Signer
->getCertificateKind());
812 m_xSignedValFt
->set_label(s
);
815 void SfxDocumentPage::ImplCheckPasswordState()
817 SfxObjectShell
* pShell
= SfxObjectShell::Current();
822 SfxItemSet
* pMedSet
= pShell
->GetMedium()->GetItemSet();
825 const SfxUnoAnyItem
* pEncryptionDataItem
= SfxItemSet::GetItem
<SfxUnoAnyItem
>(pMedSet
, SID_ENCRYPTIONDATA
, false);
826 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
827 if (pEncryptionDataItem
)
828 pEncryptionDataItem
->GetValue() >>= aEncryptionData
;
832 if (!aEncryptionData
.hasElements())
834 m_xChangePassBtn
->set_sensitive(true);
838 m_xChangePassBtn
->set_sensitive(false);
841 std::unique_ptr
<SfxTabPage
> SfxDocumentPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
* rItemSet
)
843 return std::make_unique
<SfxDocumentPage
>(pPage
, pController
, *rItemSet
);
846 void SfxDocumentPage::EnableUseUserData()
848 bEnableUseUserData
= true;
849 m_xUseUserDataCB
->show();
850 m_xDeleteBtn
->show();
853 bool SfxDocumentPage::FillItemSet( SfxItemSet
* rSet
)
857 if ( !bHandleDelete
&& bEnableUseUserData
&&
858 m_xUseUserDataCB
->get_state_changed_from_saved() )
860 const SfxItemSet
* pExpSet
= GetDialogExampleSet();
861 const SfxPoolItem
* pItem
;
863 if ( pExpSet
&& SfxItemState::SET
== pExpSet
->GetItemState( SID_DOCINFO
, true, &pItem
) )
865 const SfxDocumentInfoItem
* pInfoItem
= static_cast<const SfxDocumentInfoItem
*>(pItem
);
866 bool bUseData
= ( TRISTATE_TRUE
== m_xUseUserDataCB
->get_state() );
867 const_cast<SfxDocumentInfoItem
*>(pInfoItem
)->SetUseUserData( bUseData
);
868 rSet
->Put( *pInfoItem
);
875 const SfxItemSet
* pExpSet
= GetDialogExampleSet();
876 const SfxPoolItem
* pItem
;
877 if ( pExpSet
&& SfxItemState::SET
== pExpSet
->GetItemState( SID_DOCINFO
, true, &pItem
) )
879 const SfxDocumentInfoItem
* pInfoItem
= static_cast<const SfxDocumentInfoItem
*>(pItem
);
880 bool bUseAuthor
= bEnableUseUserData
&& m_xUseUserDataCB
->get_active();
881 SfxDocumentInfoItem
newItem( *pInfoItem
);
882 newItem
.resetUserData( bUseAuthor
883 ? SvtUserOptions().GetFullName()
885 const_cast<SfxDocumentInfoItem
*>(pInfoItem
)->SetUseUserData( TRISTATE_TRUE
== m_xUseUserDataCB
->get_state() );
886 newItem
.SetUseUserData( TRISTATE_TRUE
== m_xUseUserDataCB
->get_state() );
888 newItem
.SetDeleteUserData( true );
889 rSet
->Put( newItem
);
894 if ( m_xUseThumbnailSaveCB
->get_state_changed_from_saved() )
896 const SfxItemSet
* pExpSet
= GetDialogExampleSet();
897 const SfxPoolItem
* pItem
;
899 if ( pExpSet
&& SfxItemState::SET
== pExpSet
->GetItemState( SID_DOCINFO
, true, &pItem
) )
901 const SfxDocumentInfoItem
* pInfoItem
= static_cast<const SfxDocumentInfoItem
*>(pItem
);
902 bool bUseThumbnail
= ( TRISTATE_TRUE
== m_xUseThumbnailSaveCB
->get_state() );
903 const_cast<SfxDocumentInfoItem
*>(pInfoItem
)->SetUseThumbnailSave( bUseThumbnail
);
904 rSet
->Put( *pInfoItem
);
912 void SfxDocumentPage::Reset( const SfxItemSet
* rSet
)
914 // Determine the document information
915 const SfxDocumentInfoItem
& rInfoItem
= rSet
->Get(SID_DOCINFO
);
918 if (rInfoItem
.HasTemplate())
920 const OUString
& rName
= rInfoItem
.getTemplateName();
921 if (rName
.getLength() > SAL_MAX_INT16
) // tdf#122780 pick some ~arbitrary max size
922 m_xTemplValFt
->set_label(rName
.copy(0, SAL_MAX_INT16
));
924 m_xTemplValFt
->set_label(rName
);
929 m_xTemplValFt
->hide();
932 // determine file name
933 OUString
aFile( rInfoItem
.GetValue() );
934 OUString
aFactory( aFile
);
935 if ( aFile
.getLength() > 2 && aFile
[0] == '[' )
937 sal_Int32 nPos
= aFile
.indexOf( ']' );
938 aFactory
= aFile
.copy( 1, nPos
-1 );
939 aFile
= aFile
.copy( nPos
+1 );
943 INetURLObject
aURL(aFile
);
944 OUString aName
= aURL
.GetLastName(INetURLObject::DecodeMechanism::WithCharset
);
945 if ( aName
.isEmpty() || aURL
.GetProtocol() == INetProtocol::PrivSoffice
)
946 aName
= SfxResId( STR_NONAME
);
947 m_xNameED
->set_label( aName
);
949 // determine context symbol
950 aURL
.SetSmartProtocol( INetProtocol::File
);
951 aURL
.SetSmartURL( aFactory
);
952 const OUString
& rMainURL
= aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
953 OUString aImage
= SvFileInformationManager::GetImageId( aURL
, true );
954 m_xBmp
->set_from_icon_name(aImage
);
956 // determine size and type
957 OUString
aSizeText( m_aUnknownSize
);
958 if ( aURL
.GetProtocol() == INetProtocol::File
||
959 aURL
.isAnyKnownWebDAVScheme() )
960 aSizeText
= CreateSizeText( SfxContentHelper::GetSize( aURL
.GetMainURL( INetURLObject::DecodeMechanism::NONE
) ) );
961 m_xShowSizeFT
->set_label( aSizeText
);
963 OUString aDescription
= SvFileInformationManager::GetDescription( INetURLObject(rMainURL
) );
964 if ( aDescription
.isEmpty() )
965 aDescription
= SfxResId( STR_SFX_NEWOFFICEDOC
);
966 m_xShowTypeFT
->set_label( aDescription
);
968 // determine location
969 aURL
.SetSmartURL( aFile
);
970 if ( aURL
.GetProtocol() == INetProtocol::File
)
972 INetURLObject
aPath( aURL
);
973 aPath
.setFinalSlash();
974 aPath
.removeSegment();
975 // we know it's a folder -> don't need the final slash, but it's better for WB_PATHELLIPSIS
976 aPath
.removeFinalSlash();
977 OUString
aText( aPath
.PathToFileName() ); //! (pb) MaxLen?
978 m_xFileValEd
->set_label( aText
);
980 else if ( aURL
.GetProtocol() != INetProtocol::PrivSoffice
)
981 m_xFileValEd
->set_label( aURL
.GetPartBeforeLastName() );
983 // handle access data
984 bool bUseUserData
= rInfoItem
.IsUseUserData();
985 const LocaleDataWrapper
& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
986 m_xCreateValFt
->set_label( ConvertDateTime_Impl( rInfoItem
.getAuthor(),
987 rInfoItem
.getCreationDate(), rLocaleWrapper
) );
988 util::DateTime
aTime( rInfoItem
.getModificationDate() );
989 if ( aTime
.Month
> 0 )
990 m_xChangeValFt
->set_label( ConvertDateTime_Impl(
991 rInfoItem
.getModifiedBy(), aTime
, rLocaleWrapper
) );
992 aTime
= rInfoItem
.getPrintDate();
993 if ( aTime
.Month
> 0 )
994 m_xPrintValFt
->set_label( ConvertDateTime_Impl( rInfoItem
.getPrintedBy(),
995 aTime
, rLocaleWrapper
) );
996 const tools::Long nTime
= rInfoItem
.getEditingDuration();
999 const tools::Time
aT( nTime
/3600, (nTime
%3600)/60, nTime
%60 );
1000 m_xTimeLogValFt
->set_label( rLocaleWrapper
.getDuration( aT
) );
1001 m_xDocNoValFt
->set_label( OUString::number(
1002 rInfoItem
.getEditingCycles() ) );
1005 bool bUseThumbnailSave
= rInfoItem
.IsUseThumbnailSave();
1007 // Check for cmis properties where otherwise unavailable
1008 if ( rInfoItem
.isCmisDocument( ) )
1010 const uno::Sequence
< document::CmisProperty
> aCmisProps
= rInfoItem
.GetCmisProperties();
1011 for ( const auto& rCmisProp
: aCmisProps
)
1013 if ( rCmisProp
.Id
== "cmis:contentStreamLength" &&
1014 aSizeText
== m_aUnknownSize
)
1016 Sequence
< sal_Int64
> seqValue
;
1017 rCmisProp
.Value
>>= seqValue
;
1018 SvNumberFormatter
aNumberFormatter( ::comphelper::getProcessComponentContext(),
1019 Application::GetSettings().GetLanguageTag().getLanguageType() );
1020 sal_uInt32 nIndex
= aNumberFormatter
.GetFormatIndex( NF_NUMBER_SYSTEM
);
1021 if ( seqValue
.hasElements() )
1024 aNumberFormatter
.GetInputLineString( seqValue
[0], nIndex
, sValue
);
1025 m_xShowSizeFT
->set_label( CreateSizeText( sValue
.toInt64( ) ) );
1030 OUString emptyDate
= ConvertDateTime_Impl( "", uDT
, rLocaleWrapper
);
1031 if ( rCmisProp
.Id
== "cmis:creationDate" &&
1032 (m_xCreateValFt
->get_label() == emptyDate
||
1033 m_xCreateValFt
->get_label().isEmpty()))
1035 Sequence
< util::DateTime
> seqValue
;
1036 rCmisProp
.Value
>>= seqValue
;
1037 if ( seqValue
.hasElements() )
1039 m_xCreateValFt
->set_label( ConvertDateTime_Impl( "", seqValue
[0], rLocaleWrapper
) );
1042 if ( rCmisProp
.Id
== "cmis:lastModificationDate" &&
1043 (m_xChangeValFt
->get_label() == emptyDate
||
1044 m_xChangeValFt
->get_label().isEmpty()))
1046 Sequence
< util::DateTime
> seqValue
;
1047 rCmisProp
.Value
>>= seqValue
;
1048 if ( seqValue
.hasElements() )
1050 m_xChangeValFt
->set_label( ConvertDateTime_Impl( "", seqValue
[0], rLocaleWrapper
) );
1056 m_xUseUserDataCB
->set_active(bUseUserData
);
1057 m_xUseUserDataCB
->save_state();
1058 m_xUseUserDataCB
->set_sensitive( bEnableUseUserData
);
1059 bHandleDelete
= false;
1060 m_xDeleteBtn
->set_sensitive( bEnableUseUserData
);
1061 m_xUseThumbnailSaveCB
->set_active(bUseThumbnailSave
);
1062 m_xUseThumbnailSaveCB
->save_state();
1065 SfxDocumentInfoDialog::SfxDocumentInfoDialog(weld::Window
* pParent
, const SfxItemSet
& rItemSet
)
1066 : SfxTabDialogController(pParent
, "sfx/ui/documentpropertiesdialog.ui",
1067 "DocumentPropertiesDialog", &rItemSet
)
1069 const SfxDocumentInfoItem
& rInfoItem
= rItemSet
.Get( SID_DOCINFO
);
1072 const SfxStringItem
* pURLItem
= rItemSet
.GetItem
<SfxStringItem
>(SID_BASEURL
, false);
1073 DBG_ASSERT( pURLItem
, "No BaseURL provided for InternetTabPage!" );
1076 // Determine the Titles
1077 const SfxPoolItem
* pItem
= nullptr;
1078 OUString
aTitle(m_xDialog
->get_title());
1079 if ( SfxItemState::SET
!=
1080 rItemSet
.GetItemState( SID_EXPLORER_PROPS_START
, false, &pItem
) )
1083 const OUString
& aFile( rInfoItem
.GetValue() );
1086 aURL
.SetSmartProtocol( INetProtocol::File
);
1087 aURL
.SetSmartURL( aFile
);
1088 if ( INetProtocol::PrivSoffice
!= aURL
.GetProtocol() )
1090 OUString
aLastName( aURL
.GetLastName() );
1091 if ( !aLastName
.isEmpty() )
1092 aTitle
= aTitle
.replaceFirst("%1", aLastName
);
1094 aTitle
= aTitle
.replaceFirst("%1", aFile
);
1097 aTitle
= aTitle
.replaceFirst("%1", SfxResId( STR_NONAME
));
1101 DBG_ASSERT( dynamic_cast<const SfxStringItem
*>(pItem
) != nullptr,
1102 "SfxDocumentInfoDialog:<SfxStringItem> expected" );
1103 aTitle
= aTitle
.replaceFirst("%1", static_cast<const SfxStringItem
*>(pItem
)->GetValue());
1105 m_xDialog
->set_title(aTitle
);
1108 AddTabPage("general", SfxDocumentPage::Create
, nullptr);
1109 AddTabPage("description", SfxDocumentDescPage::Create
, nullptr);
1110 AddTabPage("customprops", SfxCustomPropertiesPage::Create
, nullptr);
1111 if (rInfoItem
.isCmisDocument())
1112 AddTabPage("cmisprops", SfxCmisPropertiesPage::Create
, nullptr);
1114 RemoveTabPage("cmisprops");
1115 AddTabPage("security", SfxSecurityPage::Create
, nullptr);
1118 void SfxDocumentInfoDialog::PageCreated(const OString
& rId
, SfxTabPage
&rPage
)
1120 if (rId
== "general")
1121 static_cast<SfxDocumentPage
&>(rPage
).EnableUseUserData();
1124 void SfxDocumentInfoDialog::AddFontTabPage()
1126 AddTabPage("font", SfxResId(STR_FONT_TABPAGE
), SfxDocumentFontsPage::Create
);
1129 // class CustomPropertiesYesNoButton -------------------------------------
1131 CustomPropertiesYesNoButton::CustomPropertiesYesNoButton(std::unique_ptr
<weld::Widget
> xTopLevel
,
1132 std::unique_ptr
<weld::RadioButton
> xYesButton
,
1133 std::unique_ptr
<weld::RadioButton
> xNoButton
)
1134 : m_xTopLevel(std::move(xTopLevel
))
1135 , m_xYesButton(std::move(xYesButton
))
1136 , m_xNoButton(std::move(xNoButton
))
1141 CustomPropertiesYesNoButton::~CustomPropertiesYesNoButton()
1147 class DurationDialog_Impl
: public weld::GenericDialogController
1149 std::unique_ptr
<weld::CheckButton
> m_xNegativeCB
;
1150 std::unique_ptr
<weld::SpinButton
> m_xYearNF
;
1151 std::unique_ptr
<weld::SpinButton
> m_xMonthNF
;
1152 std::unique_ptr
<weld::SpinButton
> m_xDayNF
;
1153 std::unique_ptr
<weld::SpinButton
> m_xHourNF
;
1154 std::unique_ptr
<weld::SpinButton
> m_xMinuteNF
;
1155 std::unique_ptr
<weld::SpinButton
> m_xSecondNF
;
1156 std::unique_ptr
<weld::SpinButton
> m_xMSecondNF
;
1159 DurationDialog_Impl(weld::Widget
* pParent
, const util::Duration
& rDuration
);
1160 util::Duration
GetDuration() const;
1165 DurationDialog_Impl::DurationDialog_Impl(weld::Widget
* pParent
, const util::Duration
& rDuration
)
1166 : GenericDialogController(pParent
, "sfx/ui/editdurationdialog.ui", "EditDurationDialog")
1167 , m_xNegativeCB(m_xBuilder
->weld_check_button("negative"))
1168 , m_xYearNF(m_xBuilder
->weld_spin_button("years"))
1169 , m_xMonthNF(m_xBuilder
->weld_spin_button("months"))
1170 , m_xDayNF(m_xBuilder
->weld_spin_button("days"))
1171 , m_xHourNF(m_xBuilder
->weld_spin_button("hours"))
1172 , m_xMinuteNF(m_xBuilder
->weld_spin_button("minutes"))
1173 , m_xSecondNF(m_xBuilder
->weld_spin_button("seconds"))
1174 , m_xMSecondNF(m_xBuilder
->weld_spin_button("milliseconds"))
1176 m_xNegativeCB
->set_active(rDuration
.Negative
);
1177 m_xYearNF
->set_value(rDuration
.Years
);
1178 m_xMonthNF
->set_value(rDuration
.Months
);
1179 m_xDayNF
->set_value(rDuration
.Days
);
1180 m_xHourNF
->set_value(rDuration
.Hours
);
1181 m_xMinuteNF
->set_value(rDuration
.Minutes
);
1182 m_xSecondNF
->set_value(rDuration
.Seconds
);
1183 m_xMSecondNF
->set_value(rDuration
.NanoSeconds
);
1186 util::Duration
DurationDialog_Impl::GetDuration() const
1188 util::Duration aRet
;
1189 aRet
.Negative
= m_xNegativeCB
->get_active();
1190 aRet
.Years
= m_xYearNF
->get_value();
1191 aRet
.Months
= m_xMonthNF
->get_value();
1192 aRet
.Days
= m_xDayNF
->get_value();
1193 aRet
.Hours
= m_xHourNF
->get_value();
1194 aRet
.Minutes
= m_xMinuteNF
->get_value();
1195 aRet
.Seconds
= m_xSecondNF
->get_value();
1196 aRet
.NanoSeconds
= m_xMSecondNF
->get_value();
1200 CustomPropertiesDurationField::CustomPropertiesDurationField(std::unique_ptr
<weld::Entry
> xEntry
,
1201 std::unique_ptr
<weld::Button
> xEditButton
)
1202 : m_xEntry(std::move(xEntry
))
1203 , m_xEditButton(std::move(xEditButton
))
1205 m_xEditButton
->connect_clicked(LINK(this, CustomPropertiesDurationField
, ClickHdl
));
1206 SetDuration( util::Duration(false, 0, 0, 0, 0, 0, 0, 0) );
1209 void CustomPropertiesDurationField::set_visible(bool bVisible
)
1211 m_xEntry
->set_visible(bVisible
);
1212 m_xEditButton
->set_visible(bVisible
);
1215 void CustomPropertiesDurationField::SetDuration( const util::Duration
& rDuration
)
1217 m_aDuration
= rDuration
;
1218 OUString sText
= (rDuration
.Negative
? OUString('-') : OUString('+')) +
1219 SfxResId(SFX_ST_DURATION_FORMAT
);
1220 sText
= sText
.replaceFirst( "%1", OUString::number( rDuration
.Years
) );
1221 sText
= sText
.replaceFirst( "%2", OUString::number( rDuration
.Months
) );
1222 sText
= sText
.replaceFirst( "%3", OUString::number( rDuration
.Days
) );
1223 sText
= sText
.replaceFirst( "%4", OUString::number( rDuration
.Hours
) );
1224 sText
= sText
.replaceFirst( "%5", OUString::number( rDuration
.Minutes
) );
1225 sText
= sText
.replaceFirst( "%6", OUString::number( rDuration
.Seconds
) );
1226 m_xEntry
->set_text(sText
);
1229 IMPL_LINK(CustomPropertiesDurationField
, ClickHdl
, weld::Button
&, rButton
, void)
1231 DurationDialog_Impl
aDurationDlg(&rButton
, GetDuration());
1232 if (aDurationDlg
.run() == RET_OK
)
1233 SetDuration(aDurationDlg
.GetDuration());
1238 void fillNameBox(weld::ComboBox
& rNameBox
)
1240 for (size_t i
= 0; i
< SAL_N_ELEMENTS(SFX_CB_PROPERTY_STRINGARRAY
); ++i
)
1241 rNameBox
.append_text(SfxResId(SFX_CB_PROPERTY_STRINGARRAY
[i
]));
1242 Size
aSize(rNameBox
.get_preferred_size());
1243 rNameBox
.set_size_request(aSize
.Width(), aSize
.Height());
1246 void fillTypeBox(weld::ComboBox
& rTypeBox
)
1248 for (size_t i
= 0; i
< SAL_N_ELEMENTS(SFX_LB_PROPERTY_STRINGARRAY
); ++i
)
1250 OUString
sId(OUString::number(SFX_LB_PROPERTY_STRINGARRAY
[i
].second
));
1251 rTypeBox
.append(sId
, SfxResId(SFX_LB_PROPERTY_STRINGARRAY
[i
].first
));
1253 rTypeBox
.set_active(0);
1254 Size
aSize(rTypeBox
.get_preferred_size());
1255 rTypeBox
.set_size_request(aSize
.Width(), aSize
.Height());
1259 // struct CustomPropertyLine ---------------------------------------------
1260 CustomPropertyLine::CustomPropertyLine(CustomPropertiesWindow
* pParent
, weld::Widget
* pContainer
)
1261 : m_pParent(pParent
)
1262 , m_xBuilder(Application::CreateBuilder(pContainer
, "sfx/ui/linefragment.ui"))
1263 , m_xLine(m_xBuilder
->weld_container("lineentry"))
1264 , m_xNameBox(m_xBuilder
->weld_combo_box("namebox"))
1265 , m_xTypeBox(m_xBuilder
->weld_combo_box("typebox"))
1266 , m_xValueEdit(m_xBuilder
->weld_entry("valueedit"))
1267 , m_xDateTimeBox(m_xBuilder
->weld_widget("datetimebox"))
1268 , m_xDateField(new CustomPropertiesDateField(new SvtCalendarBox(m_xBuilder
->weld_menu_button("date"))))
1269 , m_xTimeField(new CustomPropertiesTimeField(m_xBuilder
->weld_formatted_spin_button("time")))
1270 , m_xDurationBox(m_xBuilder
->weld_widget("durationbox"))
1271 , m_xDurationField(new CustomPropertiesDurationField(m_xBuilder
->weld_entry("duration"),
1272 m_xBuilder
->weld_button("durationbutton")))
1273 , m_xYesNoButton(new CustomPropertiesYesNoButton(m_xBuilder
->weld_widget("yesno"),
1274 m_xBuilder
->weld_radio_button("yes"),
1275 m_xBuilder
->weld_radio_button("no")))
1276 , m_xRemoveButton(m_xBuilder
->weld_button("remove"))
1277 , m_bTypeLostFocus( false )
1279 fillNameBox(*m_xNameBox
);
1280 fillTypeBox(*m_xTypeBox
);
1282 m_xTypeBox
->connect_changed(LINK(this, CustomPropertyLine
, TypeHdl
));
1283 m_xRemoveButton
->connect_clicked(LINK(this, CustomPropertyLine
, RemoveHdl
));
1284 m_xValueEdit
->connect_focus_out(LINK(this, CustomPropertyLine
, EditLoseFocusHdl
));
1285 //add lose focus handlers of date/time fields
1286 m_xTypeBox
->connect_focus_out(LINK(this, CustomPropertyLine
, BoxLoseFocusHdl
));
1289 void CustomPropertyLine::Clear()
1291 m_xNameBox
->set_active(-1);
1292 m_xValueEdit
->set_text(OUString());
1296 void CustomPropertyLine::Hide()
1301 CustomPropertiesWindow::CustomPropertiesWindow(weld::Container
& rParent
, weld::Label
& rHeaderAccName
,
1302 weld::Label
& rHeaderAccType
, weld::Label
& rHeaderAccValue
)
1306 , m_pCurrentLine(nullptr)
1307 , m_aNumberFormatter(::comphelper::getProcessComponentContext(),
1308 Application::GetSettings().GetLanguageTag().getLanguageType())
1310 , m_rHeaderAccName(rHeaderAccName
)
1311 , m_rHeaderAccType(rHeaderAccType
)
1312 , m_rHeaderAccValue(rHeaderAccValue
)
1314 m_aEditLoseFocusIdle
.SetPriority( TaskPriority::LOWEST
);
1315 m_aEditLoseFocusIdle
.SetInvokeHandler( LINK( this, CustomPropertiesWindow
, EditTimeoutHdl
) );
1316 m_aBoxLoseFocusIdle
.SetPriority( TaskPriority::LOWEST
);
1317 m_aBoxLoseFocusIdle
.SetInvokeHandler( LINK( this, CustomPropertiesWindow
, BoxTimeoutHdl
) );
1320 CustomPropertiesWindow::~CustomPropertiesWindow()
1322 m_aEditLoseFocusIdle
.Stop();
1323 m_aBoxLoseFocusIdle
.Stop();
1325 m_pCurrentLine
= nullptr;
1328 void CustomPropertyLine::DoTypeHdl(const weld::ComboBox
& rBox
)
1330 auto nType
= rBox
.get_active_id().toInt32();
1331 m_xValueEdit
->set_visible( (CUSTOM_TYPE_TEXT
== nType
) || (CUSTOM_TYPE_NUMBER
== nType
) );
1332 m_xDateTimeBox
->set_visible( (CUSTOM_TYPE_DATE
== nType
) || (CUSTOM_TYPE_DATETIME
== nType
) );
1333 m_xDateField
->set_visible( (CUSTOM_TYPE_DATE
== nType
) || (CUSTOM_TYPE_DATETIME
== nType
) );
1334 m_xTimeField
->set_visible( CUSTOM_TYPE_DATETIME
== nType
);
1335 m_xDurationBox
->set_visible( CUSTOM_TYPE_DURATION
== nType
);
1336 m_xDurationField
->set_visible( CUSTOM_TYPE_DURATION
== nType
);
1337 m_xYesNoButton
->set_visible( CUSTOM_TYPE_BOOLEAN
== nType
);
1340 IMPL_LINK(CustomPropertyLine
, TypeHdl
, weld::ComboBox
&, rBox
, void)
1345 void CustomPropertiesWindow::Remove(const CustomPropertyLine
* pLine
)
1347 StoreCustomProperties();
1349 auto pFound
= std::find_if( m_aCustomPropertiesLines
.begin(), m_aCustomPropertiesLines
.end(),
1350 [&] (const std::unique_ptr
<CustomPropertyLine
>& p
) { return p
.get() == pLine
; });
1351 if ( pFound
!= m_aCustomPropertiesLines
.end() )
1353 sal_uInt32 nLineNumber
= pFound
- m_aCustomPropertiesLines
.begin();
1354 sal_uInt32 nDataModelIndex
= GetCurrentDataModelPosition() + nLineNumber
;
1355 m_aCustomProperties
.erase(m_aCustomProperties
.begin() + nDataModelIndex
);
1357 ReloadLinesContent();
1360 m_aRemovedHdl
.Call(nullptr);
1363 IMPL_LINK_NOARG(CustomPropertyLine
, RemoveHdl
, weld::Button
&, void)
1365 m_pParent
->Remove(this);
1368 void CustomPropertiesWindow::EditLoseFocus(CustomPropertyLine
* pLine
)
1370 m_pCurrentLine
= pLine
;
1371 m_aEditLoseFocusIdle
.Start();
1374 IMPL_LINK_NOARG(CustomPropertyLine
, EditLoseFocusHdl
, weld::Widget
&, void)
1376 if (!m_bTypeLostFocus
)
1377 m_pParent
->EditLoseFocus(this);
1379 m_bTypeLostFocus
= false;
1382 void CustomPropertiesWindow::BoxLoseFocus(CustomPropertyLine
* pLine
)
1384 m_pCurrentLine
= pLine
;
1385 m_aBoxLoseFocusIdle
.Start();
1388 IMPL_LINK_NOARG(CustomPropertyLine
, BoxLoseFocusHdl
, weld::Widget
&, void)
1390 m_pParent
->BoxLoseFocus(this);
1393 IMPL_LINK_NOARG(CustomPropertiesWindow
, EditTimeoutHdl
, Timer
*, void)
1395 ValidateLine( m_pCurrentLine
, false );
1398 IMPL_LINK_NOARG(CustomPropertiesWindow
, BoxTimeoutHdl
, Timer
*, void)
1400 ValidateLine( m_pCurrentLine
, true );
1403 bool CustomPropertiesWindow::IsLineValid( CustomPropertyLine
* pLine
) const
1405 bool bIsValid
= true;
1406 pLine
->m_bTypeLostFocus
= false;
1407 auto nType
= pLine
->m_xTypeBox
->get_active_id().toInt32();
1408 OUString sValue
= pLine
->m_xValueEdit
->get_text();
1409 if ( sValue
.isEmpty() )
1412 sal_uInt32 nIndex
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
1413 if ( CUSTOM_TYPE_NUMBER
== nType
)
1414 // tdf#116214 Scientific format allows to use also standard numbers
1415 nIndex
= const_cast< SvNumberFormatter
& >(
1416 m_aNumberFormatter
).GetFormatIndex( NF_SCIENTIFIC_000E00
);
1417 else if ( CUSTOM_TYPE_DATE
== nType
)
1418 nIndex
= const_cast< SvNumberFormatter
& >(
1419 m_aNumberFormatter
).GetFormatIndex( NF_DATE_SYS_DDMMYYYY
);
1421 if ( nIndex
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
1423 sal_uInt32 nTemp
= nIndex
;
1424 double fDummy
= 0.0;
1425 bIsValid
= const_cast< SvNumberFormatter
& >(
1426 m_aNumberFormatter
).IsNumberFormat( sValue
, nIndex
, fDummy
);
1427 if ( bIsValid
&& nTemp
!= nIndex
)
1428 // sValue is a number but the format doesn't match the index
1435 void CustomPropertiesWindow::ValidateLine( CustomPropertyLine
* pLine
, bool bIsFromTypeBox
)
1437 if (pLine
&& !IsLineValid(pLine
))
1439 if ( bIsFromTypeBox
) // LoseFocus of TypeBox
1440 pLine
->m_bTypeLostFocus
= true;
1441 std::unique_ptr
<weld::MessageDialog
> xMessageBox(Application::CreateMessageDialog(&m_rBody
,
1442 VclMessageType::Question
, VclButtonsType::OkCancel
, SfxResId(STR_SFX_QUERY_WRONG_TYPE
)));
1443 if (xMessageBox
->run() == RET_OK
)
1444 pLine
->m_xTypeBox
->set_active_id(OUString::number(CUSTOM_TYPE_TEXT
));
1446 pLine
->m_xValueEdit
->grab_focus();
1450 void CustomPropertiesWindow::SetVisibleLineCount(sal_uInt32 nCount
)
1452 while (GetExistingLineCount() < nCount
)
1458 void CustomPropertiesWindow::AddLine(const OUString
& sName
, Any
const & rAny
)
1460 m_aCustomProperties
.push_back(std::unique_ptr
<CustomProperty
>(new CustomProperty(sName
, rAny
)));
1461 ReloadLinesContent();
1464 void CustomPropertiesWindow::CreateNewLine()
1466 CustomPropertyLine
* pNewLine
= new CustomPropertyLine(this, &m_rBody
);
1467 pNewLine
->m_xNameBox
->set_accessible_relation_labeled_by(&m_rHeaderAccName
);
1468 pNewLine
->m_xNameBox
->set_accessible_name(m_rHeaderAccName
.get_label());
1469 pNewLine
->m_xTypeBox
->set_accessible_relation_labeled_by(&m_rHeaderAccType
);
1470 pNewLine
->m_xTypeBox
->set_accessible_name(m_rHeaderAccType
.get_label());
1471 pNewLine
->m_xValueEdit
->set_accessible_relation_labeled_by(&m_rHeaderAccValue
);
1472 pNewLine
->m_xValueEdit
->set_accessible_name(m_rHeaderAccValue
.get_label());
1474 m_aCustomPropertiesLines
.emplace_back( pNewLine
);
1476 pNewLine
->DoTypeHdl(*pNewLine
->m_xTypeBox
);
1477 pNewLine
->m_xNameBox
->grab_focus();
1480 bool CustomPropertiesWindow::AreAllLinesValid() const
1483 for ( std::unique_ptr
<CustomPropertyLine
> const & pLine
: m_aCustomPropertiesLines
)
1485 if ( !IsLineValid( pLine
.get() ) )
1495 void CustomPropertiesWindow::ClearAllLines()
1497 for (auto& pLine
: m_aCustomPropertiesLines
)
1501 m_pCurrentLine
= nullptr;
1502 m_aCustomProperties
.clear();
1506 void CustomPropertiesWindow::DoScroll( sal_Int32 nNewPos
)
1508 StoreCustomProperties();
1509 m_nScrollPos
+= nNewPos
;
1510 ReloadLinesContent();
1513 Sequence
< beans::PropertyValue
> CustomPropertiesWindow::GetCustomProperties()
1515 StoreCustomProperties();
1517 Sequence
< beans::PropertyValue
> aPropertiesSeq(GetTotalLineCount());
1519 for (sal_uInt32 i
= 0; i
< GetTotalLineCount(); ++i
)
1521 aPropertiesSeq
[i
].Name
= m_aCustomProperties
[i
]->m_sName
;
1522 aPropertiesSeq
[i
].Value
= m_aCustomProperties
[i
]->m_aValue
;
1525 return aPropertiesSeq
;
1528 CustomPropertiesTimeField::CustomPropertiesTimeField(std::unique_ptr
<weld::FormattedSpinButton
> xTimeField
)
1529 : m_xTimeField(std::move(xTimeField
))
1530 , m_xFormatter(new weld::TimeFormatter(*m_xTimeField
))
1533 m_xFormatter
->SetExtFormat(ExtTimeFieldFormat::LongDuration
);
1534 m_xFormatter
->EnableEmptyField(false);
1537 tools::Time
CustomPropertiesTimeField::get_value() const
1539 return m_xFormatter
->GetTime();
1542 void CustomPropertiesTimeField::set_value(const tools::Time
& rTime
)
1544 m_xFormatter
->SetTime(rTime
);
1547 CustomPropertiesTimeField::~CustomPropertiesTimeField()
1551 CustomPropertiesDateField::CustomPropertiesDateField(SvtCalendarBox
* pDateField
)
1552 : m_xDateField(pDateField
)
1554 DateTime
aDateTime(DateTime::SYSTEM
);
1555 m_xDateField
->set_date(aDateTime
);
1558 void CustomPropertiesDateField::set_visible(bool bVisible
)
1560 m_xDateField
->set_visible(bVisible
);
1563 Date
CustomPropertiesDateField::get_date() const
1565 return m_xDateField
->get_date();
1568 void CustomPropertiesDateField::set_date(const Date
& rDate
)
1570 m_xDateField
->set_date(rDate
);
1573 CustomPropertiesDateField::~CustomPropertiesDateField()
1577 void CustomPropertiesWindow::StoreCustomProperties()
1579 sal_uInt32 nDataModelPos
= GetCurrentDataModelPosition();
1581 for (sal_uInt32 i
= 0; nDataModelPos
+ i
< GetTotalLineCount() && i
< GetExistingLineCount(); i
++)
1583 CustomPropertyLine
* pLine
= m_aCustomPropertiesLines
[i
].get();
1585 OUString sPropertyName
= pLine
->m_xNameBox
->get_active_text();
1586 if (!sPropertyName
.isEmpty())
1588 m_aCustomProperties
[nDataModelPos
+ i
]->m_sName
= sPropertyName
;
1589 auto nType
= pLine
->m_xTypeBox
->get_active_id().toInt32();
1590 if (CUSTOM_TYPE_NUMBER
== nType
)
1593 sal_uInt32 nIndex
= m_aNumberFormatter
.GetFormatIndex(NF_NUMBER_SYSTEM
);
1594 bool bIsNum
= m_aNumberFormatter
.
1595 IsNumberFormat(pLine
->m_xValueEdit
->get_text(), nIndex
, nValue
);
1597 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= nValue
;
1599 else if (CUSTOM_TYPE_BOOLEAN
== nType
)
1601 bool bValue
= pLine
->m_xYesNoButton
->IsYesChecked();
1602 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= bValue
;
1604 else if (CUSTOM_TYPE_DATETIME
== nType
)
1606 Date aTmpDate
= pLine
->m_xDateField
->get_date();
1607 tools::Time aTmpTime
= pLine
->m_xTimeField
->get_value();
1608 util::DateTime
const aDateTime(aTmpTime
.GetNanoSec(),
1609 aTmpTime
.GetSec(), aTmpTime
.GetMin(), aTmpTime
.GetHour(),
1610 aTmpDate
.GetDay(), aTmpDate
.GetMonth(), aTmpDate
.GetYear(),
1611 pLine
->m_xTimeField
->m_isUTC
);
1612 if (pLine
->m_xDateField
->m_TZ
)
1614 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= util::DateTimeWithTimezone(
1615 aDateTime
, *pLine
->m_xDateField
->m_TZ
);
1619 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= aDateTime
;
1622 else if (CUSTOM_TYPE_DATE
== nType
)
1624 Date aTmpDate
= pLine
->m_xDateField
->get_date();
1625 util::Date
const aDate(aTmpDate
.GetDay(), aTmpDate
.GetMonth(),
1626 aTmpDate
.GetYear());
1627 if (pLine
->m_xDateField
->m_TZ
)
1629 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= util::DateWithTimezone(
1630 aDate
, *pLine
->m_xDateField
->m_TZ
);
1634 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= aDate
;
1637 else if (CUSTOM_TYPE_DURATION
== nType
)
1639 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= pLine
->m_xDurationField
->GetDuration();
1643 OUString
sValue(pLine
->m_xValueEdit
->get_text());
1644 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= sValue
;
1650 void CustomPropertiesWindow::SetCustomProperties(std::vector
< std::unique_ptr
<CustomProperty
> >&& rProperties
)
1652 m_aCustomProperties
= std::move(rProperties
);
1653 ReloadLinesContent();
1656 void CustomPropertiesWindow::ReloadLinesContent()
1658 double nTmpValue
= 0;
1659 bool bTmpValue
= false;
1661 util::DateTime aTmpDateTime
;
1662 util::Date aTmpDate
;
1663 util::DateTimeWithTimezone aTmpDateTimeTZ
;
1664 util::DateWithTimezone aTmpDateTZ
;
1665 util::Duration aTmpDuration
;
1666 SvtSysLocale aSysLocale
;
1667 const LocaleDataWrapper
& rLocaleWrapper
= aSysLocale
.GetLocaleData();
1668 sal_IntPtr nType
= CUSTOM_TYPE_UNKNOWN
;
1671 sal_uInt32 nDataModelPos
= GetCurrentDataModelPosition();
1674 for (; nDataModelPos
+ i
< GetTotalLineCount() && i
< GetExistingLineCount(); i
++)
1676 const OUString
& rName
= m_aCustomProperties
[nDataModelPos
+ i
]->m_sName
;
1677 const css::uno::Any
& rAny
= m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
;
1679 CustomPropertyLine
* pLine
= m_aCustomPropertiesLines
[i
].get();
1682 pLine
->m_xNameBox
->set_entry_text(rName
);
1683 pLine
->m_xLine
->show();
1685 if (!rAny
.hasValue())
1687 pLine
->m_xValueEdit
->set_text(OUString());
1689 else if (rAny
>>= nTmpValue
)
1691 sal_uInt32 nIndex
= m_aNumberFormatter
.GetFormatIndex(NF_NUMBER_SYSTEM
);
1692 m_aNumberFormatter
.GetInputLineString(nTmpValue
, nIndex
, sValue
);
1693 pLine
->m_xValueEdit
->set_text(sValue
);
1694 nType
= CUSTOM_TYPE_NUMBER
;
1696 else if (rAny
>>= bTmpValue
)
1698 sValue
= (bTmpValue
? rLocaleWrapper
.getTrueWord() : rLocaleWrapper
.getFalseWord());
1699 nType
= CUSTOM_TYPE_BOOLEAN
;
1701 else if (rAny
>>= sTmpValue
)
1703 pLine
->m_xValueEdit
->set_text(sTmpValue
);
1704 nType
= CUSTOM_TYPE_TEXT
;
1706 else if (rAny
>>= aTmpDate
)
1708 pLine
->m_xDateField
->set_date(Date(aTmpDate
));
1709 nType
= CUSTOM_TYPE_DATE
;
1711 else if (rAny
>>= aTmpDateTime
)
1713 pLine
->m_xDateField
->set_date(Date(aTmpDateTime
));
1714 pLine
->m_xTimeField
->set_value(tools::Time(aTmpDateTime
));
1715 pLine
->m_xTimeField
->m_isUTC
= aTmpDateTime
.IsUTC
;
1716 nType
= CUSTOM_TYPE_DATETIME
;
1718 else if (rAny
>>= aTmpDateTZ
)
1720 pLine
->m_xDateField
->set_date(Date(aTmpDateTZ
.DateInTZ
.Day
,
1721 aTmpDateTZ
.DateInTZ
.Month
, aTmpDateTZ
.DateInTZ
.Year
));
1722 pLine
->m_xDateField
->m_TZ
= aTmpDateTZ
.Timezone
;
1723 nType
= CUSTOM_TYPE_DATE
;
1725 else if (rAny
>>= aTmpDateTimeTZ
)
1727 util::DateTime
const& rDT(aTmpDateTimeTZ
.DateTimeInTZ
);
1728 pLine
->m_xDateField
->set_date(Date(rDT
));
1729 pLine
->m_xTimeField
->set_value(tools::Time(rDT
));
1730 pLine
->m_xTimeField
->m_isUTC
= rDT
.IsUTC
;
1731 pLine
->m_xDateField
->m_TZ
= aTmpDateTimeTZ
.Timezone
;
1732 nType
= CUSTOM_TYPE_DATETIME
;
1734 else if (rAny
>>= aTmpDuration
)
1736 nType
= CUSTOM_TYPE_DURATION
;
1737 pLine
->m_xDurationField
->SetDuration(aTmpDuration
);
1740 if (nType
!= CUSTOM_TYPE_UNKNOWN
)
1742 if (CUSTOM_TYPE_BOOLEAN
== nType
)
1745 pLine
->m_xYesNoButton
->CheckYes();
1747 pLine
->m_xYesNoButton
->CheckNo();
1749 pLine
->m_xTypeBox
->set_active_id(OUString::number(nType
));
1752 pLine
->DoTypeHdl(*pLine
->m_xTypeBox
);
1755 while (nDataModelPos
+ i
>= GetTotalLineCount() && i
< GetExistingLineCount())
1757 CustomPropertyLine
* pLine
= m_aCustomPropertiesLines
[i
].get();
1763 CustomPropertiesControl::CustomPropertiesControl()
1768 void CustomPropertiesControl::Init(weld::Builder
& rBuilder
)
1770 m_xBox
= rBuilder
.weld_widget("box");
1771 m_xBody
= rBuilder
.weld_container("properties");
1773 m_xName
= rBuilder
.weld_label("name");
1774 m_xType
= rBuilder
.weld_label("type");
1775 m_xValue
= rBuilder
.weld_label("value");
1776 m_xVertScroll
= rBuilder
.weld_scrolled_window("scroll", true);
1777 m_xPropertiesWin
.reset(new CustomPropertiesWindow(*m_xBody
, *m_xName
, *m_xType
, *m_xValue
));
1779 m_xBox
->set_stack_background();
1780 m_xVertScroll
->show();
1782 std::unique_ptr
<CustomPropertyLine
> xNewLine(new CustomPropertyLine(m_xPropertiesWin
.get(), m_xBody
.get()));
1783 Size
aLineSize(xNewLine
->m_xLine
->get_preferred_size());
1784 m_xPropertiesWin
->SetLineHeight(aLineSize
.Height() + 6);
1785 m_xBody
->set_size_request(aLineSize
.Width() + 6, -1);
1786 auto nHeight
= aLineSize
.Height() * 8;
1787 m_xVertScroll
->set_size_request(-1, nHeight
+ 6);
1789 m_xPropertiesWin
->SetHeight(nHeight
);
1790 m_xVertScroll
->connect_size_allocate(LINK(this, CustomPropertiesControl
, ResizeHdl
));
1792 m_xName
->set_size_request(xNewLine
->m_xNameBox
->get_preferred_size().Width(), -1);
1793 m_xType
->set_size_request(xNewLine
->m_xTypeBox
->get_preferred_size().Width(), -1);
1794 m_xValue
->set_size_request(xNewLine
->m_xValueEdit
->get_preferred_size().Width(), -1);
1796 m_xBody
->move(xNewLine
->m_xLine
.get(), nullptr);
1799 m_xPropertiesWin
->SetRemovedHdl( LINK( this, CustomPropertiesControl
, RemovedHdl
) );
1801 m_xVertScroll
->vadjustment_set_lower(0);
1802 m_xVertScroll
->vadjustment_set_upper(0);
1803 m_xVertScroll
->vadjustment_set_page_size(0xFFFF);
1805 Link
<weld::ScrolledWindow
&,void> aScrollLink
= LINK( this, CustomPropertiesControl
, ScrollHdl
);
1806 m_xVertScroll
->connect_vadjustment_changed(aScrollLink
);
1808 ResizeHdl(Size(-1, nHeight
));
1811 IMPL_LINK(CustomPropertiesControl
, ResizeHdl
, const Size
&, rSize
, void)
1813 int nHeight
= rSize
.Height() - 6;
1814 if (nHeight
== m_xPropertiesWin
->GetHeight())
1816 m_xPropertiesWin
->SetHeight(nHeight
);
1817 sal_Int32 nScrollOffset
= m_xPropertiesWin
->GetLineHeight();
1818 sal_Int32 nVisibleEntries
= nHeight
/ nScrollOffset
;
1819 m_xPropertiesWin
->SetVisibleLineCount( nVisibleEntries
);
1820 m_xVertScroll
->vadjustment_set_page_increment( nVisibleEntries
- 1 );
1821 m_xVertScroll
->vadjustment_set_page_size( nVisibleEntries
);
1822 m_xPropertiesWin
->ReloadLinesContent();
1825 CustomPropertiesControl::~CustomPropertiesControl()
1829 IMPL_LINK( CustomPropertiesControl
, ScrollHdl
, weld::ScrolledWindow
&, rScrollBar
, void )
1831 sal_Int32 nOffset
= m_xPropertiesWin
->GetLineHeight();
1832 int nThumbPos
= rScrollBar
.vadjustment_get_value();
1833 nOffset
*= ( m_nThumbPos
- nThumbPos
);
1834 m_nThumbPos
= nThumbPos
;
1835 m_xPropertiesWin
->DoScroll( nOffset
);
1838 IMPL_LINK_NOARG(CustomPropertiesControl
, RemovedHdl
, void*, void)
1840 auto nLineCount
= m_xPropertiesWin
->GetTotalLineCount();
1841 m_xVertScroll
->vadjustment_set_upper(nLineCount
+ 1);
1842 if (m_xPropertiesWin
->GetTotalLineCount() > m_xPropertiesWin
->GetExistingLineCount())
1844 m_xVertScroll
->vadjustment_set_value(nLineCount
- 1);
1845 ScrollHdl(*m_xVertScroll
);
1849 void CustomPropertiesControl::AddLine( Any
const & rAny
)
1851 m_xPropertiesWin
->AddLine( OUString(), rAny
);
1852 auto nLineCount
= m_xPropertiesWin
->GetTotalLineCount();
1853 m_xVertScroll
->vadjustment_set_upper(nLineCount
+ 1);
1854 if (m_xPropertiesWin
->GetHeight() < nLineCount
* m_xPropertiesWin
->GetLineHeight())
1856 m_xVertScroll
->vadjustment_set_value(nLineCount
+ 1);
1857 ScrollHdl(*m_xVertScroll
);
1861 void CustomPropertiesControl::SetCustomProperties(std::vector
< std::unique_ptr
<CustomProperty
> >&& rProperties
)
1863 m_xPropertiesWin
->SetCustomProperties(std::move(rProperties
));
1864 auto nLineCount
= m_xPropertiesWin
->GetTotalLineCount();
1865 m_xVertScroll
->vadjustment_set_upper(nLineCount
+ 1);
1868 // class SfxCustomPropertiesPage -----------------------------------------
1869 SfxCustomPropertiesPage::SfxCustomPropertiesPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rItemSet
)
1870 : SfxTabPage(pPage
, pController
, "sfx/ui/custominfopage.ui", "CustomInfoPage", &rItemSet
)
1871 , m_xPropertiesCtrl(new CustomPropertiesControl
)
1872 , m_xAdd(m_xBuilder
->weld_button("add"))
1874 m_xPropertiesCtrl
->Init(*m_xBuilder
);
1875 m_xAdd
->connect_clicked(LINK(this, SfxCustomPropertiesPage
, AddHdl
));
1878 SfxCustomPropertiesPage::~SfxCustomPropertiesPage()
1880 m_xPropertiesCtrl
.reset();
1883 IMPL_LINK_NOARG(SfxCustomPropertiesPage
, AddHdl
, weld::Button
&, void)
1885 // tdf#115853: reload current lines before adding a brand new one
1886 // indeed the info are deleted by ClearCustomProperties
1887 // each time SfxDocumentInfoItem destructor is called
1888 SfxDocumentInfoItem pInfo
;
1889 const Sequence
< beans::PropertyValue
> aPropertySeq
= m_xPropertiesCtrl
->GetCustomProperties();
1890 for ( const auto& rProperty
: aPropertySeq
)
1892 if ( !rProperty
.Name
.isEmpty() )
1894 pInfo
.AddCustomProperty( rProperty
.Name
, rProperty
.Value
);
1899 m_xPropertiesCtrl
->AddLine(aAny
);
1902 bool SfxCustomPropertiesPage::FillItemSet( SfxItemSet
* rSet
)
1904 const SfxPoolItem
* pItem
= nullptr;
1905 SfxDocumentInfoItem
* pInfo
= nullptr;
1906 bool bMustDelete
= false;
1908 if (const SfxItemSet
* pItemSet
= GetDialogExampleSet())
1910 if (SfxItemState::SET
!= pItemSet
->GetItemState(SID_DOCINFO
, true, &pItem
))
1911 pInfo
= const_cast<SfxDocumentInfoItem
*>(&rSet
->Get( SID_DOCINFO
));
1915 pInfo
= new SfxDocumentInfoItem( *static_cast<const SfxDocumentInfoItem
*>(pItem
) );
1921 // If it's a CMIS document, we can't save custom properties
1922 if ( pInfo
->isCmisDocument( ) )
1929 pInfo
->ClearCustomProperties();
1930 const Sequence
< beans::PropertyValue
> aPropertySeq
= m_xPropertiesCtrl
->GetCustomProperties();
1931 for ( const auto& rProperty
: aPropertySeq
)
1933 if ( !rProperty
.Name
.isEmpty() )
1934 pInfo
->AddCustomProperty( rProperty
.Name
, rProperty
.Value
);
1947 void SfxCustomPropertiesPage::Reset( const SfxItemSet
* rItemSet
)
1949 m_xPropertiesCtrl
->ClearAllLines();
1950 const SfxDocumentInfoItem
& rInfoItem
= rItemSet
->Get(SID_DOCINFO
);
1951 std::vector
< std::unique_ptr
<CustomProperty
> > aCustomProps
= rInfoItem
.GetCustomProperties();
1952 m_xPropertiesCtrl
->SetCustomProperties(std::move(aCustomProps
));
1955 DeactivateRC
SfxCustomPropertiesPage::DeactivatePage( SfxItemSet
* /*pSet*/ )
1957 DeactivateRC nRet
= DeactivateRC::LeavePage
;
1958 if ( !m_xPropertiesCtrl
->AreAllLinesValid() )
1959 nRet
= DeactivateRC::KeepPage
;
1963 std::unique_ptr
<SfxTabPage
> SfxCustomPropertiesPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
* rItemSet
)
1965 return std::make_unique
<SfxCustomPropertiesPage
>(pPage
, pController
, *rItemSet
);
1968 CmisValue::CmisValue(weld::Widget
* pParent
, const OUString
& aStr
)
1969 : m_xBuilder(Application::CreateBuilder(pParent
, "sfx/ui/cmisline.ui"))
1970 , m_xFrame(m_xBuilder
->weld_frame("CmisFrame"))
1971 , m_xValueEdit(m_xBuilder
->weld_entry("value"))
1973 m_xValueEdit
->show();
1974 m_xValueEdit
->set_text(aStr
);
1977 CmisDateTime::CmisDateTime(weld::Widget
* pParent
, const util::DateTime
& aDateTime
)
1978 : m_xBuilder(Application::CreateBuilder(pParent
, "sfx/ui/cmisline.ui"))
1979 , m_xFrame(m_xBuilder
->weld_frame("CmisFrame"))
1980 , m_xDateField(new SvtCalendarBox(m_xBuilder
->weld_menu_button("date")))
1981 , m_xTimeField(m_xBuilder
->weld_formatted_spin_button("time"))
1982 , m_xFormatter(new weld::TimeFormatter(*m_xTimeField
))
1984 m_xFormatter
->SetExtFormat(ExtTimeFieldFormat::LongDuration
);
1985 m_xFormatter
->EnableEmptyField(false);
1987 m_xDateField
->show();
1988 m_xTimeField
->show();
1989 m_xDateField
->set_date(Date(aDateTime
));
1990 m_xFormatter
->SetTime(tools::Time(aDateTime
));
1993 CmisYesNo::CmisYesNo(weld::Widget
* pParent
, bool bValue
)
1994 : m_xBuilder(Application::CreateBuilder(pParent
, "sfx/ui/cmisline.ui"))
1995 , m_xFrame(m_xBuilder
->weld_frame("CmisFrame"))
1996 , m_xYesButton(m_xBuilder
->weld_radio_button("yes"))
1997 , m_xNoButton(m_xBuilder
->weld_radio_button("no"))
1999 m_xYesButton
->show();
2000 m_xNoButton
->show();
2002 m_xYesButton
->set_active(true);
2004 m_xNoButton
->set_active(true);
2007 // struct CmisPropertyLine ---------------------------------------------
2008 CmisPropertyLine::CmisPropertyLine(weld::Widget
* pParent
)
2009 : m_xBuilder(Application::CreateBuilder(pParent
, "sfx/ui/cmisline.ui"))
2010 , m_sType(CMIS_TYPE_STRING
)
2011 , m_bUpdatable(false)
2012 , m_bRequired(false)
2013 , m_bMultiValued(false)
2014 , m_bOpenChoice(false)
2015 , m_xFrame(m_xBuilder
->weld_frame("CmisFrame"))
2016 , m_xName(m_xBuilder
->weld_label("name"))
2017 , m_xType(m_xBuilder
->weld_label("type"))
2019 m_xFrame
->set_sensitive(true);
2022 CmisPropertyLine::~CmisPropertyLine( )
2026 // class CmisPropertiesWindow -----------------------------------------
2028 CmisPropertiesWindow::CmisPropertiesWindow(std::unique_ptr
<weld::Container
> xParent
)
2029 : m_xBox(std::move(xParent
))
2030 , m_aNumberFormatter(::comphelper::getProcessComponentContext(),
2031 Application::GetSettings().GetLanguageTag().getLanguageType())
2035 CmisPropertiesWindow::~CmisPropertiesWindow()
2039 void CmisPropertiesWindow::ClearAllLines()
2041 m_aCmisPropertiesLines
.clear();
2044 void CmisPropertiesWindow::AddLine( const OUString
& sId
, const OUString
& sName
,
2045 const OUString
& sType
, const bool bUpdatable
,
2046 const bool bRequired
, const bool bMultiValued
,
2047 const bool bOpenChoice
, Any
& /*aChoices*/, Any
const & rAny
)
2049 std::unique_ptr
<CmisPropertyLine
> pNewLine(new CmisPropertyLine(m_xBox
.get()));
2051 pNewLine
->m_sId
= sId
;
2052 pNewLine
->m_sType
= sType
;
2053 pNewLine
->m_bUpdatable
= bUpdatable
;
2054 pNewLine
->m_bRequired
= bRequired
;
2055 pNewLine
->m_bMultiValued
= bMultiValued
;
2056 pNewLine
->m_bOpenChoice
= bOpenChoice
;
2058 if ( sType
== CMIS_TYPE_INTEGER
)
2060 Sequence
< sal_Int64
> seqValue
;
2062 sal_uInt32 nIndex
= m_aNumberFormatter
.GetFormatIndex( NF_NUMBER_SYSTEM
);
2063 for ( const auto& rValue
: std::as_const(seqValue
) )
2066 m_aNumberFormatter
.GetInputLineString( rValue
, nIndex
, sValue
);
2067 std::unique_ptr
<CmisValue
> pValue(new CmisValue(m_xBox
.get(), sValue
));
2068 pValue
->m_xValueEdit
->set_editable(bUpdatable
);
2069 pNewLine
->m_aValues
.push_back( std::move(pValue
) );
2072 else if ( sType
== CMIS_TYPE_DECIMAL
)
2074 Sequence
< double > seqValue
;
2076 sal_uInt32 nIndex
= m_aNumberFormatter
.GetFormatIndex( NF_NUMBER_SYSTEM
);
2077 for ( const auto& rValue
: std::as_const(seqValue
) )
2080 m_aNumberFormatter
.GetInputLineString( rValue
, nIndex
, sValue
);
2081 std::unique_ptr
<CmisValue
> pValue(new CmisValue(m_xBox
.get(), sValue
));
2082 pValue
->m_xValueEdit
->set_editable(bUpdatable
);
2083 pNewLine
->m_aValues
.push_back( std::move(pValue
) );
2087 else if ( sType
== CMIS_TYPE_BOOL
)
2089 Sequence
<sal_Bool
> seqValue
;
2091 for ( const auto& rValue
: std::as_const(seqValue
) )
2093 std::unique_ptr
<CmisYesNo
> pYesNo(new CmisYesNo(m_xBox
.get(), rValue
));
2094 pYesNo
->m_xYesButton
->set_sensitive( bUpdatable
);
2095 pYesNo
->m_xNoButton
->set_sensitive( bUpdatable
);
2096 pNewLine
->m_aYesNos
.push_back( std::move(pYesNo
) );
2099 else if ( sType
== CMIS_TYPE_STRING
)
2101 Sequence
< OUString
> seqValue
;
2103 for ( const auto& rValue
: std::as_const(seqValue
) )
2105 std::unique_ptr
<CmisValue
> pValue(new CmisValue(m_xBox
.get(), rValue
));
2106 pValue
->m_xValueEdit
->set_editable(bUpdatable
);
2107 pNewLine
->m_aValues
.push_back( std::move(pValue
) );
2110 else if ( sType
== CMIS_TYPE_DATETIME
)
2112 Sequence
< util::DateTime
> seqValue
;
2114 for ( const auto& rValue
: std::as_const(seqValue
) )
2116 std::unique_ptr
<CmisDateTime
> pDateTime(new CmisDateTime(m_xBox
.get(), rValue
));
2117 pDateTime
->m_xDateField
->set_sensitive(bUpdatable
);
2118 pDateTime
->m_xTimeField
->set_sensitive(bUpdatable
);
2119 pNewLine
->m_aDateTimes
.push_back( std::move(pDateTime
) );
2122 pNewLine
->m_xName
->set_label( sName
);
2123 pNewLine
->m_xName
->show();
2124 pNewLine
->m_xType
->set_label( sType
);
2125 pNewLine
->m_xType
->show();
2127 m_aCmisPropertiesLines
.push_back( std::move(pNewLine
) );
2130 Sequence
< document::CmisProperty
> CmisPropertiesWindow::GetCmisProperties() const
2132 Sequence
< document::CmisProperty
> aPropertiesSeq( m_aCmisPropertiesLines
.size() );
2134 for ( auto& rxLine
: m_aCmisPropertiesLines
)
2136 CmisPropertyLine
* pLine
= rxLine
.get();
2138 aPropertiesSeq
[i
].Id
= pLine
->m_sId
;
2139 aPropertiesSeq
[i
].Type
= pLine
->m_sType
;
2140 aPropertiesSeq
[i
].Updatable
= pLine
->m_bUpdatable
;
2141 aPropertiesSeq
[i
].Required
= pLine
->m_bRequired
;
2142 aPropertiesSeq
[i
].OpenChoice
= pLine
->m_bOpenChoice
;
2143 aPropertiesSeq
[i
].MultiValued
= pLine
->m_bMultiValued
;
2145 OUString sPropertyName
= pLine
->m_xName
->get_label();
2146 if ( !sPropertyName
.isEmpty() )
2148 aPropertiesSeq
[i
].Name
= sPropertyName
;
2149 OUString sType
= pLine
->m_xType
->get_label();
2150 if ( CMIS_TYPE_DECIMAL
== sType
)
2152 sal_uInt32 nIndex
= const_cast< SvNumberFormatter
& >(
2153 m_aNumberFormatter
).GetFormatIndex( NF_NUMBER_SYSTEM
);
2154 Sequence
< double > seqValue( pLine
->m_aValues
.size( ) );
2156 for ( const auto& rxValue
: pLine
->m_aValues
)
2158 double dValue
= 0.0;
2159 OUString
sValue( rxValue
->m_xValueEdit
->get_text() );
2160 bool bIsNum
= const_cast< SvNumberFormatter
& >( m_aNumberFormatter
).
2161 IsNumberFormat( sValue
, nIndex
, dValue
);
2163 seqValue
[k
] = dValue
;
2166 aPropertiesSeq
[i
].Value
<<= seqValue
;
2168 else if ( CMIS_TYPE_INTEGER
== sType
)
2170 sal_uInt32 nIndex
= const_cast< SvNumberFormatter
& >(
2171 m_aNumberFormatter
).GetFormatIndex( NF_NUMBER_SYSTEM
);
2172 Sequence
< sal_Int64
> seqValue( pLine
->m_aValues
.size( ) );
2174 for ( const auto& rxValue
: pLine
->m_aValues
)
2177 OUString
sValue( rxValue
->m_xValueEdit
->get_text() );
2178 bool bIsNum
= const_cast< SvNumberFormatter
& >( m_aNumberFormatter
).
2179 IsNumberFormat( sValue
, nIndex
, dValue
);
2181 seqValue
[k
] = static_cast<sal_Int64
>(dValue
);
2184 aPropertiesSeq
[i
].Value
<<= seqValue
;
2186 else if ( CMIS_TYPE_BOOL
== sType
)
2188 Sequence
<sal_Bool
> seqValue( pLine
->m_aYesNos
.size( ) );
2190 for ( const auto& rxYesNo
: pLine
->m_aYesNos
)
2192 bool bValue
= rxYesNo
->m_xYesButton
->get_active();
2193 seqValue
[k
] = bValue
;
2196 aPropertiesSeq
[i
].Value
<<= seqValue
;
2199 else if ( CMIS_TYPE_DATETIME
== sType
)
2201 Sequence
< util::DateTime
> seqValue( pLine
->m_aDateTimes
.size( ) );
2203 for ( const auto& rxDateTime
: pLine
->m_aDateTimes
)
2205 Date aTmpDate
= rxDateTime
->m_xDateField
->get_date();
2206 tools::Time aTmpTime
= rxDateTime
->m_xFormatter
->GetTime();
2207 util::DateTime
aDateTime( aTmpTime
.GetNanoSec(), aTmpTime
.GetSec(),
2208 aTmpTime
.GetMin(), aTmpTime
.GetHour(),
2209 aTmpDate
.GetDay(), aTmpDate
.GetMonth(),
2210 aTmpDate
.GetYear(), true );
2211 seqValue
[k
] = aDateTime
;
2214 aPropertiesSeq
[i
].Value
<<= seqValue
;
2218 Sequence
< OUString
> seqValue( pLine
->m_aValues
.size( ) );
2220 for ( const auto& rxValue
: pLine
->m_aValues
)
2222 OUString
sValue( rxValue
->m_xValueEdit
->get_text() );
2223 seqValue
[k
] = sValue
;
2226 aPropertiesSeq
[i
].Value
<<= seqValue
;
2232 return aPropertiesSeq
;
2235 CmisPropertiesControl::CmisPropertiesControl(weld::Builder
& rBuilder
)
2236 : m_aPropertiesWin(rBuilder
.weld_container("CmisWindow"))
2237 , m_xScrolledWindow(rBuilder
.weld_scrolled_window("CmisScroll"))
2239 // set height to something small and force it to take the size
2240 // dictated by the other pages
2241 m_xScrolledWindow
->set_size_request(-1, 42);
2244 void CmisPropertiesControl::ClearAllLines()
2246 m_aPropertiesWin
.ClearAllLines();
2249 void CmisPropertiesControl::AddLine( const OUString
& sId
, const OUString
& sName
,
2250 const OUString
& sType
, const bool bUpdatable
,
2251 const bool bRequired
, const bool bMultiValued
,
2252 const bool bOpenChoice
, Any
& aChoices
, Any
const & rAny
2255 m_aPropertiesWin
.AddLine( sId
, sName
, sType
, bUpdatable
, bRequired
, bMultiValued
,
2256 bOpenChoice
, aChoices
, rAny
);
2259 // class SfxCmisPropertiesPage -----------------------------------------
2260 SfxCmisPropertiesPage::SfxCmisPropertiesPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rItemSet
)
2261 : SfxTabPage(pPage
, pController
, "sfx/ui/cmisinfopage.ui", "CmisInfoPage", &rItemSet
)
2262 , m_xPropertiesCtrl(new CmisPropertiesControl(*m_xBuilder
))
2266 SfxCmisPropertiesPage::~SfxCmisPropertiesPage()
2268 m_xPropertiesCtrl
.reset();
2271 bool SfxCmisPropertiesPage::FillItemSet( SfxItemSet
* rSet
)
2273 const SfxPoolItem
* pItem
= nullptr;
2274 SfxDocumentInfoItem
* pInfo
= nullptr;
2275 bool bMustDelete
= false;
2277 if (const SfxItemSet
* pItemSet
= GetDialogExampleSet())
2279 if (SfxItemState::SET
!= pItemSet
->GetItemState(SID_DOCINFO
, true, &pItem
))
2280 pInfo
= const_cast<SfxDocumentInfoItem
*>(&rSet
->Get( SID_DOCINFO
));
2284 pInfo
= new SfxDocumentInfoItem( *static_cast<const SfxDocumentInfoItem
*>(pItem
) );
2288 sal_Int32 modifiedNum
= 0;
2291 Sequence
< document::CmisProperty
> aOldProps
= pInfo
->GetCmisProperties( );
2292 Sequence
< document::CmisProperty
> aNewProps
= m_xPropertiesCtrl
->GetCmisProperties();
2294 std::vector
< document::CmisProperty
> changedProps
;
2295 for ( sal_Int32 i
= 0; i
< aNewProps
.getLength( ); ++i
)
2297 if ( aOldProps
[i
].Updatable
&& !aNewProps
[i
].Id
.isEmpty( ) )
2299 if ( aOldProps
[i
].Type
== CMIS_TYPE_DATETIME
)
2301 Sequence
< util::DateTime
> oldValue
;
2302 aOldProps
[i
].Value
>>= oldValue
;
2303 // We only edit hours and minutes
2304 // don't compare NanoSeconds and Seconds
2305 for ( auto& rDateTime
: oldValue
)
2307 rDateTime
.NanoSeconds
= 0;
2308 rDateTime
.Seconds
= 0;
2310 Sequence
< util::DateTime
> newValue
;
2311 aNewProps
[i
].Value
>>= newValue
;
2312 if ( oldValue
!= newValue
)
2315 changedProps
.push_back( aNewProps
[i
] );
2318 else if ( aOldProps
[i
].Value
!= aNewProps
[i
].Value
)
2321 changedProps
.push_back( aNewProps
[i
] );
2325 Sequence
< document::CmisProperty
> aModifiedProps( comphelper::containerToSequence(changedProps
) );
2326 pInfo
->SetCmisProperties( aModifiedProps
);
2327 rSet
->Put( *pInfo
);
2335 void SfxCmisPropertiesPage::Reset( const SfxItemSet
* rItemSet
)
2337 m_xPropertiesCtrl
->ClearAllLines();
2338 const SfxDocumentInfoItem
& rInfoItem
= rItemSet
->Get(SID_DOCINFO
);
2339 uno::Sequence
< document::CmisProperty
> aCmisProps
= rInfoItem
.GetCmisProperties();
2340 for ( auto& rCmisProp
: aCmisProps
)
2342 m_xPropertiesCtrl
->AddLine(rCmisProp
.Id
,
2345 rCmisProp
.Updatable
,
2347 rCmisProp
.MultiValued
,
2348 rCmisProp
.OpenChoice
,
2354 DeactivateRC
SfxCmisPropertiesPage::DeactivatePage( SfxItemSet
* /*pSet*/ )
2356 return DeactivateRC::LeavePage
;
2359 std::unique_ptr
<SfxTabPage
> SfxCmisPropertiesPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
* rItemSet
)
2361 return std::make_unique
<SfxCmisPropertiesPage
>(pPage
, pController
, *rItemSet
);
2364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */