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/propertyvalue.hxx>
32 #include <comphelper/stl_types.hxx>
33 #include <comphelper/xmlsechelper.hxx>
34 #include <unotools/useroptions.hxx>
35 #include <svtools/ctrlbox.hxx>
36 #include <svtools/imagemgr.hxx>
37 #include <sal/log.hxx>
38 #include <osl/diagnose.h>
39 #include <osl/file.hxx>
40 #include <comphelper/lok.hxx>
44 #include <comphelper/sequence.hxx>
45 #include <comphelper/string.hxx>
46 #include <com/sun/star/security/DocumentSignatureInformation.hpp>
47 #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
48 #include <unotools/syslocale.hxx>
49 #include <rtl/math.hxx>
50 #include <com/sun/star/beans/PropertyAttribute.hpp>
51 #include <com/sun/star/beans/XPropertyContainer.hpp>
52 #include <com/sun/star/beans/XPropertySet.hpp>
53 #include <com/sun/star/util/DateTime.hpp>
54 #include <com/sun/star/util/Date.hpp>
55 #include <com/sun/star/util/DateTimeWithTimezone.hpp>
56 #include <com/sun/star/util/DateWithTimezone.hpp>
57 #include <com/sun/star/util/Duration.hpp>
58 #include <com/sun/star/document/XDocumentProperties.hpp>
59 #include <com/sun/star/document/CmisProperty.hpp>
60 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
62 #include <vcl/timer.hxx>
63 #include <vcl/settings.hxx>
64 #include <sfx2/sfxresid.hxx>
65 #include <sfx2/frame.hxx>
66 #include <sfx2/filedlghelper.hxx>
67 #include <sfx2/dinfdlg.hxx>
68 #include <sfx2/sfxsids.hrc>
70 #include <sfx2/objsh.hxx>
71 #include <sfx2/docfile.hxx>
72 #include <vcl/abstdlg.hxx>
74 #include <documentfontsdialog.hxx>
75 #include <dinfdlg.hrc>
76 #include <sfx2/strings.hrc>
77 #include <strings.hxx>
78 #include <tools/diagnose_ex.h>
79 #include "securitypage.hxx"
83 using namespace ::com::sun::star
;
84 using namespace ::com::sun::star::uno
;
89 css::uno::Any m_aValue
;
91 CustomProperty( const OUString
& sName
, const css::uno::Any
& rValue
) :
92 m_sName( sName
), m_aValue( rValue
) {}
94 bool operator==(const CustomProperty
& rProp
) const
96 return m_sName
== rProp
.m_sName
&& m_aValue
== rProp
.m_aValue
;
100 SfxPoolItem
* SfxDocumentInfoItem::CreateDefault() { return new SfxDocumentInfoItem
; }
104 OUString
CreateSizeText( sal_Int64 nSize
)
106 OUString aUnitStr
= " " + SfxResId(STR_BYTES
);
107 sal_Int64 nSize1
= nSize
;
108 sal_Int64 nSize2
= nSize1
;
109 sal_Int64 nMega
= 1024 * 1024;
110 sal_Int64 nGiga
= nMega
* 1024;
111 double fSize
= nSize
;
114 if ( nSize1
>= 10000 && nSize1
< nMega
)
117 aUnitStr
= " " + SfxResId(STR_KB
);
121 else if ( nSize1
>= nMega
&& nSize1
< nGiga
)
124 aUnitStr
= " " + SfxResId(STR_MB
);
128 else if ( nSize1
>= nGiga
)
131 aUnitStr
= " " + SfxResId(STR_GB
);
135 const SvtSysLocale aSysLocale
;
136 const LocaleDataWrapper
& rLocaleWrapper
= aSysLocale
.GetLocaleData();
137 OUString aSizeStr
= rLocaleWrapper
.getNum( nSize1
, 0 ) + aUnitStr
;
138 if ( nSize1
< nSize2
)
140 aSizeStr
= ::rtl::math::doubleToUString( fSize
,
141 rtl_math_StringFormat_F
, nDec
,
142 rLocaleWrapper
.getNumDecimalSep()[0] )
145 + rLocaleWrapper
.getNum( nSize2
, 0 )
147 + SfxResId(STR_BYTES
)
153 OUString
ConvertDateTime_Impl( std::u16string_view rName
,
154 const util::DateTime
& uDT
, const LocaleDataWrapper
& rWrapper
)
158 static const OUStringLiteral
aDelim( u
", " );
159 OUString aStr
= rWrapper
.getDate( aD
)
161 + rWrapper
.getTime( aT
);
162 OUString aAuthor
= comphelper::string::stripStart(rName
, ' ');
163 if (!aAuthor
.isEmpty())
165 aStr
+= aDelim
+ aAuthor
;
173 SfxDocumentInfoItem::SfxDocumentInfoItem()
175 , m_isAutoloadEnabled(false)
177 , m_EditingDuration(0)
178 , m_bHasTemplate( true )
179 , m_bDeleteUserData( false )
180 , m_bUseUserData( true )
181 , m_bUseThumbnailSave( true )
185 SfxDocumentInfoItem::SfxDocumentInfoItem( const OUString
& rFile
,
186 const uno::Reference
<document::XDocumentProperties
>& i_xDocProps
,
187 const uno::Sequence
<document::CmisProperty
>& i_cmisProps
,
188 bool bIs
, bool _bIs
)
189 : SfxStringItem( SID_DOCINFO
, rFile
)
190 , m_AutoloadDelay( i_xDocProps
->getAutoloadSecs() )
191 , m_AutoloadURL( i_xDocProps
->getAutoloadURL() )
192 , m_isAutoloadEnabled( (m_AutoloadDelay
> 0) || !m_AutoloadURL
.isEmpty() )
193 , m_DefaultTarget( i_xDocProps
->getDefaultTarget() )
194 , m_TemplateName( i_xDocProps
->getTemplateName() )
195 , m_Author( i_xDocProps
->getAuthor() )
196 , m_CreationDate( i_xDocProps
->getCreationDate() )
197 , m_ModifiedBy( i_xDocProps
->getModifiedBy() )
198 , m_ModificationDate( i_xDocProps
->getModificationDate() )
199 , m_PrintedBy( i_xDocProps
->getPrintedBy() )
200 , m_PrintDate( i_xDocProps
->getPrintDate() )
201 , m_EditingCycles( i_xDocProps
->getEditingCycles() )
202 , m_EditingDuration( i_xDocProps
->getEditingDuration() )
203 , m_Description( i_xDocProps
->getDescription() )
204 , m_Keywords( ::comphelper::string::convertCommaSeparated(
205 i_xDocProps
->getKeywords()) )
206 , m_Subject( i_xDocProps
->getSubject() )
207 , m_Title( i_xDocProps
->getTitle() )
208 , m_bHasTemplate( true )
209 , m_bDeleteUserData( false )
210 , m_bUseUserData( bIs
)
211 , m_bUseThumbnailSave( _bIs
)
215 Reference
< beans::XPropertyContainer
> xContainer
= i_xDocProps
->getUserDefinedProperties();
216 if ( xContainer
.is() )
218 Reference
< beans::XPropertySet
> xSet( xContainer
, UNO_QUERY
);
219 const Sequence
< beans::Property
> lProps
= xSet
->getPropertySetInfo()->getProperties();
220 for ( const beans::Property
& rProp
: lProps
)
222 // "fix" property? => not a custom property => ignore it!
223 if (!(rProp
.Attributes
& css::beans::PropertyAttribute::REMOVABLE
))
225 SAL_WARN( "sfx.dialog", "non-removable user-defined property?");
229 uno::Any aValue
= xSet
->getPropertyValue(rProp
.Name
);
230 AddCustomProperty( rProp
.Name
, aValue
);
234 // get CMIS properties
235 m_aCmisProperties
= i_cmisProps
;
237 catch ( Exception
& ) {}
241 SfxDocumentInfoItem::SfxDocumentInfoItem( const SfxDocumentInfoItem
& rItem
)
242 : SfxStringItem( rItem
)
243 , m_AutoloadDelay( rItem
.getAutoloadDelay() )
244 , m_AutoloadURL( rItem
.getAutoloadURL() )
245 , m_isAutoloadEnabled( rItem
.isAutoloadEnabled() )
246 , m_DefaultTarget( rItem
.getDefaultTarget() )
247 , m_TemplateName( rItem
.getTemplateName() )
248 , m_Author( rItem
.getAuthor() )
249 , m_CreationDate( rItem
.getCreationDate() )
250 , m_ModifiedBy( rItem
.getModifiedBy() )
251 , m_ModificationDate( rItem
.getModificationDate() )
252 , m_PrintedBy( rItem
.getPrintedBy() )
253 , m_PrintDate( rItem
.getPrintDate() )
254 , m_EditingCycles( rItem
.getEditingCycles() )
255 , m_EditingDuration( rItem
.getEditingDuration() )
256 , m_Description( rItem
.getDescription() )
257 , m_Keywords( rItem
.getKeywords() )
258 , m_Subject( rItem
.getSubject() )
259 , m_Title( rItem
.getTitle() )
260 , m_bHasTemplate( rItem
.m_bHasTemplate
)
261 , m_bDeleteUserData( rItem
.m_bDeleteUserData
)
262 , m_bUseUserData( rItem
.m_bUseUserData
)
263 , m_bUseThumbnailSave( rItem
.m_bUseThumbnailSave
)
265 for (auto const & pOtherProp
: rItem
.m_aCustomProperties
)
267 AddCustomProperty( pOtherProp
->m_sName
, pOtherProp
->m_aValue
);
270 m_aCmisProperties
= rItem
.m_aCmisProperties
;
273 SfxDocumentInfoItem::~SfxDocumentInfoItem()
275 ClearCustomProperties();
278 SfxDocumentInfoItem
* SfxDocumentInfoItem::Clone( SfxItemPool
* ) const
280 return new SfxDocumentInfoItem( *this );
283 bool SfxDocumentInfoItem::operator==( const SfxPoolItem
& rItem
) const
285 if (!SfxStringItem::operator==(rItem
))
287 const SfxDocumentInfoItem
& rInfoItem(static_cast<const SfxDocumentInfoItem
&>(rItem
));
290 m_AutoloadDelay
== rInfoItem
.m_AutoloadDelay
&&
291 m_AutoloadURL
== rInfoItem
.m_AutoloadURL
&&
292 m_isAutoloadEnabled
== rInfoItem
.m_isAutoloadEnabled
&&
293 m_DefaultTarget
== rInfoItem
.m_DefaultTarget
&&
294 m_Author
== rInfoItem
.m_Author
&&
295 m_CreationDate
== rInfoItem
.m_CreationDate
&&
296 m_ModifiedBy
== rInfoItem
.m_ModifiedBy
&&
297 m_ModificationDate
== rInfoItem
.m_ModificationDate
&&
298 m_PrintedBy
== rInfoItem
.m_PrintedBy
&&
299 m_PrintDate
== rInfoItem
.m_PrintDate
&&
300 m_EditingCycles
== rInfoItem
.m_EditingCycles
&&
301 m_EditingDuration
== rInfoItem
.m_EditingDuration
&&
302 m_Description
== rInfoItem
.m_Description
&&
303 m_Keywords
== rInfoItem
.m_Keywords
&&
304 m_Subject
== rInfoItem
.m_Subject
&&
305 m_Title
== rInfoItem
.m_Title
&&
306 comphelper::ContainerUniquePtrEquals(m_aCustomProperties
, rInfoItem
.m_aCustomProperties
) &&
307 m_aCmisProperties
.getLength() == rInfoItem
.m_aCmisProperties
.getLength();
311 void SfxDocumentInfoItem::resetUserData(const OUString
& i_rAuthor
)
313 m_Author
= i_rAuthor
;
314 DateTime
now( DateTime::SYSTEM
);
315 m_CreationDate
= now
.GetUNODateTime();
316 m_ModifiedBy
= OUString();
317 m_PrintedBy
= OUString();
318 m_ModificationDate
= util::DateTime();
319 m_PrintDate
= util::DateTime();
320 m_EditingDuration
= 0;
325 void SfxDocumentInfoItem::UpdateDocumentInfo(
326 const uno::Reference
<document::XDocumentProperties
>& i_xDocProps
,
327 bool i_bDoNotUpdateUserDefined
) const
329 if (isAutoloadEnabled()) {
330 i_xDocProps
->setAutoloadSecs(getAutoloadDelay());
331 i_xDocProps
->setAutoloadURL(getAutoloadURL());
333 i_xDocProps
->setAutoloadSecs(0);
334 i_xDocProps
->setAutoloadURL(OUString());
336 i_xDocProps
->setDefaultTarget(getDefaultTarget());
337 i_xDocProps
->setAuthor(getAuthor());
338 i_xDocProps
->setCreationDate(getCreationDate());
339 i_xDocProps
->setModifiedBy(getModifiedBy());
340 i_xDocProps
->setModificationDate(getModificationDate());
341 i_xDocProps
->setPrintedBy(getPrintedBy());
342 i_xDocProps
->setPrintDate(getPrintDate());
343 i_xDocProps
->setEditingCycles(getEditingCycles());
344 i_xDocProps
->setEditingDuration(getEditingDuration());
345 i_xDocProps
->setDescription(getDescription());
346 i_xDocProps
->setKeywords(
347 ::comphelper::string::convertCommaSeparated(getKeywords()));
348 i_xDocProps
->setSubject(getSubject());
349 i_xDocProps
->setTitle(getTitle());
351 // this is necessary in case of replaying a recorded macro:
352 // in this case, the macro may contain the 4 old user-defined DocumentInfo
353 // fields, but not any of the DocumentInfo properties;
354 // as a consequence, most of the UserDefined properties of the
355 // DocumentProperties would be summarily deleted here, which does not
356 // seem like a good idea.
357 if (i_bDoNotUpdateUserDefined
)
362 Reference
< beans::XPropertyContainer
> xContainer
= i_xDocProps
->getUserDefinedProperties();
363 Reference
< beans::XPropertySet
> xSet( xContainer
, UNO_QUERY
);
364 Reference
< beans::XPropertySetInfo
> xSetInfo
= xSet
->getPropertySetInfo();
365 const Sequence
< beans::Property
> lProps
= xSetInfo
->getProperties();
366 for ( const beans::Property
& rProp
: lProps
)
368 if (rProp
.Attributes
& css::beans::PropertyAttribute::REMOVABLE
)
370 xContainer
->removeProperty( rProp
.Name
);
374 for (auto const & pProp
: m_aCustomProperties
)
378 xContainer
->addProperty( pProp
->m_sName
,
379 beans::PropertyAttribute::REMOVABLE
, pProp
->m_aValue
);
381 catch ( Exception
const & )
383 TOOLS_WARN_EXCEPTION( "sfx.dialog", "SfxDocumentInfoItem::updateDocumentInfo(): exception while adding custom properties" );
387 catch ( Exception
const & )
389 TOOLS_WARN_EXCEPTION( "sfx.dialog", "SfxDocumentInfoItem::updateDocumentInfo(): exception while removing custom properties" );
394 void SfxDocumentInfoItem::SetDeleteUserData( bool bSet
)
396 m_bDeleteUserData
= bSet
;
400 void SfxDocumentInfoItem::SetUseUserData( bool bSet
)
402 m_bUseUserData
= bSet
;
405 void SfxDocumentInfoItem::SetUseThumbnailSave( bool bSet
)
407 m_bUseThumbnailSave
= bSet
;
410 std::vector
< std::unique_ptr
<CustomProperty
> > SfxDocumentInfoItem::GetCustomProperties() const
412 std::vector
< std::unique_ptr
<CustomProperty
> > aRet
;
413 for (auto const & pOtherProp
: m_aCustomProperties
)
415 std::unique_ptr
<CustomProperty
> pProp(new CustomProperty( pOtherProp
->m_sName
,
416 pOtherProp
->m_aValue
));
417 aRet
.push_back( std::move(pProp
) );
423 void SfxDocumentInfoItem::ClearCustomProperties()
425 m_aCustomProperties
.clear();
428 void SfxDocumentInfoItem::AddCustomProperty( const OUString
& sName
, const Any
& rValue
)
430 std::unique_ptr
<CustomProperty
> pProp(new CustomProperty( sName
, rValue
));
431 m_aCustomProperties
.push_back( std::move(pProp
) );
435 void SfxDocumentInfoItem::SetCmisProperties( const Sequence
< document::CmisProperty
>& cmisProps
)
437 m_aCmisProperties
= cmisProps
;
440 bool SfxDocumentInfoItem::QueryValue( Any
& rVal
, sal_uInt8 nMemberId
) const
443 sal_Int32 nValue
= 0;
446 bool bIsString
= false;
447 nMemberId
&= ~CONVERT_TWIPS
;
450 case MID_DOCINFO_USEUSERDATA
:
451 bValue
= IsUseUserData();
453 case MID_DOCINFO_USETHUMBNAILSAVE
:
454 bValue
= IsUseThumbnailSave();
456 case MID_DOCINFO_DELETEUSERDATA
:
457 bValue
= m_bDeleteUserData
;
459 case MID_DOCINFO_AUTOLOADENABLED
:
460 bValue
= isAutoloadEnabled();
462 case MID_DOCINFO_AUTOLOADSECS
:
464 nValue
= getAutoloadDelay();
466 case MID_DOCINFO_AUTOLOADURL
:
468 aValue
= getAutoloadURL();
470 case MID_DOCINFO_DEFAULTTARGET
:
472 aValue
= getDefaultTarget();
474 case MID_DOCINFO_DESCRIPTION
:
476 aValue
= getDescription();
478 case MID_DOCINFO_KEYWORDS
:
480 aValue
= getKeywords();
482 case MID_DOCINFO_SUBJECT
:
484 aValue
= getSubject();
486 case MID_DOCINFO_TITLE
:
491 OSL_FAIL("Wrong MemberId!");
504 bool SfxDocumentInfoItem::PutValue( const Any
& rVal
, sal_uInt8 nMemberId
)
510 nMemberId
&= ~CONVERT_TWIPS
;
513 case MID_DOCINFO_USEUSERDATA
:
514 bRet
= (rVal
>>= bValue
);
516 SetUseUserData( bValue
);
518 case MID_DOCINFO_USETHUMBNAILSAVE
:
519 bRet
= (rVal
>>=bValue
);
521 SetUseThumbnailSave( bValue
);
523 case MID_DOCINFO_DELETEUSERDATA
:
524 // QUESTION: deleting user data was done here; seems to be superfluous!
525 bRet
= (rVal
>>= bValue
);
527 SetDeleteUserData( bValue
);
529 case MID_DOCINFO_AUTOLOADENABLED
:
530 bRet
= (rVal
>>= bValue
);
532 m_isAutoloadEnabled
= bValue
;
534 case MID_DOCINFO_AUTOLOADSECS
:
535 bRet
= (rVal
>>= nValue
);
537 m_AutoloadDelay
= nValue
;
539 case MID_DOCINFO_AUTOLOADURL
:
540 bRet
= (rVal
>>= aValue
);
542 m_AutoloadURL
= aValue
;
544 case MID_DOCINFO_DEFAULTTARGET
:
545 bRet
= (rVal
>>= aValue
);
547 m_DefaultTarget
= aValue
;
549 case MID_DOCINFO_DESCRIPTION
:
550 bRet
= (rVal
>>= aValue
);
552 setDescription(aValue
);
554 case MID_DOCINFO_KEYWORDS
:
555 bRet
= (rVal
>>= aValue
);
559 case MID_DOCINFO_SUBJECT
:
560 bRet
= (rVal
>>= aValue
);
564 case MID_DOCINFO_TITLE
:
565 bRet
= (rVal
>>= aValue
);
570 OSL_FAIL("Wrong MemberId!");
577 SfxDocumentDescPage::SfxDocumentDescPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rItemSet
)
578 : SfxTabPage(pPage
, pController
, "sfx/ui/descriptioninfopage.ui", "DescriptionInfoPage", &rItemSet
)
579 , m_pInfoItem(nullptr)
580 , m_xTitleEd(m_xBuilder
->weld_entry("title"))
581 , m_xThemaEd(m_xBuilder
->weld_entry("subject"))
582 , m_xKeywordsEd(m_xBuilder
->weld_entry("keywords"))
583 , m_xCommentEd(m_xBuilder
->weld_text_view("comments"))
585 m_xCommentEd
->set_size_request(m_xKeywordsEd
->get_preferred_size().Width(),
586 m_xCommentEd
->get_height_rows(16));
589 SfxDocumentDescPage::~SfxDocumentDescPage()
593 std::unique_ptr
<SfxTabPage
> SfxDocumentDescPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
*rItemSet
)
595 return std::make_unique
<SfxDocumentDescPage
>(pPage
, pController
, *rItemSet
);
598 bool SfxDocumentDescPage::FillItemSet(SfxItemSet
*rSet
)
600 // Test whether a change is present
601 const bool bTitleMod
= m_xTitleEd
->get_value_changed_from_saved();
602 const bool bThemeMod
= m_xThemaEd
->get_value_changed_from_saved();
603 const bool bKeywordsMod
= m_xKeywordsEd
->get_value_changed_from_saved();
604 const bool bCommentMod
= m_xCommentEd
->get_value_changed_from_saved();
605 if ( !( bTitleMod
|| bThemeMod
|| bKeywordsMod
|| bCommentMod
) )
610 // Generating the output data
611 const SfxPoolItem
* pItem
= nullptr;
612 SfxDocumentInfoItem
* pInfo
= nullptr;
613 const SfxItemSet
* pExSet
= GetDialogExampleSet();
615 if ( pExSet
&& SfxItemState::SET
!= pExSet
->GetItemState( SID_DOCINFO
, true, &pItem
) )
618 pInfo
= new SfxDocumentInfoItem( *static_cast<const SfxDocumentInfoItem
*>(pItem
) );
622 SAL_WARN( "sfx.dialog", "SfxDocumentDescPage::FillItemSet(): no item found" );
628 pInfo
->setTitle( m_xTitleEd
->get_text() );
632 pInfo
->setSubject( m_xThemaEd
->get_text() );
636 pInfo
->setKeywords( m_xKeywordsEd
->get_text() );
640 pInfo
->setDescription( m_xCommentEd
->get_text() );
643 if ( pInfo
!= m_pInfoItem
)
651 void SfxDocumentDescPage::Reset(const SfxItemSet
*rSet
)
653 m_pInfoItem
= const_cast<SfxDocumentInfoItem
*>(&rSet
->Get(SID_DOCINFO
));
655 m_xTitleEd
->set_text(m_pInfoItem
->getTitle());
656 m_xThemaEd
->set_text(m_pInfoItem
->getSubject());
657 m_xKeywordsEd
->set_text(m_pInfoItem
->getKeywords());
658 m_xCommentEd
->set_text(m_pInfoItem
->getDescription());
660 m_xTitleEd
->save_value();
661 m_xThemaEd
->save_value();
662 m_xKeywordsEd
->save_value();
663 m_xCommentEd
->save_value();
665 const SfxBoolItem
* pROItem
= SfxItemSet::GetItem
<SfxBoolItem
>(rSet
, SID_DOC_READONLY
, false);
666 if (pROItem
&& pROItem
->GetValue())
668 m_xTitleEd
->set_editable(false);
669 m_xThemaEd
->set_editable(false);
670 m_xKeywordsEd
->set_editable(false);
671 m_xCommentEd
->set_editable(false);
675 SfxDocumentPage::SfxDocumentPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rItemSet
)
676 : SfxTabPage(pPage
, pController
, "sfx/ui/documentinfopage.ui", "DocumentInfoPage", &rItemSet
)
677 , bEnableUseUserData( false )
678 , bHandleDelete( false )
679 , m_xBmp(m_xBuilder
->weld_image("icon"))
680 , m_xNameED(m_xBuilder
->weld_label("nameed"))
681 , m_xChangePassBtn(m_xBuilder
->weld_button("changepass"))
682 , m_xShowTypeFT(m_xBuilder
->weld_label("showtype"))
683 , m_xFileValEd(m_xBuilder
->weld_link_button("showlocation"))
684 , m_xShowSizeFT(m_xBuilder
->weld_label("showsize"))
685 , m_xCreateValFt(m_xBuilder
->weld_label("showcreate"))
686 , m_xChangeValFt(m_xBuilder
->weld_label("showmodify"))
687 , m_xSignedValFt(m_xBuilder
->weld_label("showsigned"))
688 , m_xSignatureBtn(m_xBuilder
->weld_button("signature"))
689 , m_xPrintValFt(m_xBuilder
->weld_label("showprint"))
690 , m_xTimeLogValFt(m_xBuilder
->weld_label("showedittime"))
691 , m_xDocNoValFt(m_xBuilder
->weld_label("showrevision"))
692 , m_xUseUserDataCB(m_xBuilder
->weld_check_button("userdatacb"))
693 , m_xDeleteBtn(m_xBuilder
->weld_button("reset"))
694 , m_xUseThumbnailSaveCB(m_xBuilder
->weld_check_button("thumbnailsavecb"))
695 , m_xTemplFt(m_xBuilder
->weld_label("templateft"))
696 , m_xTemplValFt(m_xBuilder
->weld_label("showtemplate"))
697 , m_xImagePreferredDpiCheckButton(m_xBuilder
->weld_check_button("image-preferred-dpi-checkbutton"))
698 , m_xImagePreferredDpiComboBox(m_xBuilder
->weld_combo_box("image-preferred-dpi-combobox"))
700 m_aUnknownSize
= m_xShowSizeFT
->get_label();
701 m_xShowSizeFT
->set_label(OUString());
703 m_aMultiSignedStr
= m_xSignedValFt
->get_label();
704 m_xSignedValFt
->set_label(OUString());
706 ImplUpdateSignatures();
707 ImplCheckPasswordState();
708 m_xChangePassBtn
->connect_clicked( LINK( this, SfxDocumentPage
, ChangePassHdl
) );
709 m_xSignatureBtn
->connect_clicked( LINK( this, SfxDocumentPage
, SignatureHdl
) );
710 if (comphelper::LibreOfficeKit::isActive())
711 m_xSignatureBtn
->hide();
712 m_xDeleteBtn
->connect_clicked( LINK( this, SfxDocumentPage
, DeleteHdl
) );
713 m_xImagePreferredDpiCheckButton
->connect_toggled(LINK(this, SfxDocumentPage
, ImagePreferredDPICheckBoxClicked
));
715 // [i96288] Check if the document signature command is enabled
716 // on the main list enable/disable the pushbutton accordingly
717 SvtCommandOptions aCmdOptions
;
718 if ( aCmdOptions
.Lookup( SvtCommandOptions::CMDOPTION_DISABLED
, "Signature" ) )
719 m_xSignatureBtn
->set_sensitive(false);
722 SfxDocumentPage::~SfxDocumentPage()
724 if (m_xPasswordDialog
)
726 m_xPasswordDialog
->Response(RET_CANCEL
);
727 m_xPasswordDialog
.clear();
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
, ImagePreferredDPICheckBoxClicked
, weld::Toggleable
&, void)
761 bool bEnabled
= m_xImagePreferredDpiCheckButton
->get_state() == TRISTATE_TRUE
;
762 m_xImagePreferredDpiComboBox
->set_sensitive(bEnabled
);
765 IMPL_LINK_NOARG(SfxDocumentPage
, ChangePassHdl
, weld::Button
&, void)
767 SfxObjectShell
* pShell
= SfxObjectShell::Current();
772 SfxItemSet
* pMedSet
= pShell
->GetMedium()->GetItemSet();
775 std::shared_ptr
<const SfxFilter
> pFilter
= pShell
->GetMedium()->GetFilter();
778 if (comphelper::LibreOfficeKit::isActive())
780 // MS Types support max len of 15 characters while OOXML is "unlimited"
781 const sal_uInt16 maxPwdLen
= sfx2::IsMSType(pFilter
) && !sfx2::IsOOXML(pFilter
) ? 15 : 0;
782 // handle the pwd dialog asynchronously
783 VclAbstractDialogFactory
* pFact
= VclAbstractDialogFactory::Create();
784 m_xPasswordDialog
= pFact
->CreatePasswordToOpenModifyDialog(GetFrameWeld(), maxPwdLen
, false);
785 m_xPasswordDialog
->AllowEmpty(); // needed to remove password
786 m_xPasswordDialog
->StartExecuteAsync([this, pFilter
, pMedSet
, pShell
](sal_Int32 nResult
)
788 if (nResult
== RET_OK
)
790 sfx2::SetPassword(pFilter
, pMedSet
, m_xPasswordDialog
->GetPasswordToOpen(),
791 m_xPasswordDialog
->GetPasswordToOpen(), true);
792 pShell
->SetModified();
794 m_xPasswordDialog
->disposeOnce();
797 sfx2::RequestPassword(pFilter
, OUString(), pMedSet
, GetFrameWeld()->GetXWindow());
798 pShell
->SetModified();
804 void SfxDocumentPage::ImplUpdateSignatures()
806 SfxObjectShell
* pDoc
= SfxObjectShell::Current();
810 SfxMedium
* pMedium
= pDoc
->GetMedium();
811 if ( !pMedium
|| pMedium
->GetName().isEmpty() || !pMedium
->GetStorage().is() )
814 Reference
< security::XDocumentDigitalSignatures
> xD
;
817 xD
= security::DocumentDigitalSignatures::createDefault(comphelper::getProcessComponentContext());
818 xD
->setParentWindow(GetDialogController()->getDialog()->GetXWindow());
820 catch ( const css::uno::DeploymentException
& )
824 Sequence
< security::DocumentSignatureInformation
> aInfos
;
827 aInfos
= xD
->verifyDocumentContentSignatures( pMedium
->GetZipStorageToSign_Impl(),
828 uno::Reference
< io::XInputStream
>() );
829 if ( aInfos
.getLength() > 1 )
830 s
= m_aMultiSignedStr
;
831 else if ( aInfos
.getLength() == 1 )
833 const security::DocumentSignatureInformation
& rInfo
= aInfos
[ 0 ];
834 s
= utl::GetDateTimeString( rInfo
.SignatureDate
, rInfo
.SignatureTime
) + ", " +
835 comphelper::xmlsec::GetContentPart(rInfo
.Signer
->getSubjectName(), rInfo
.Signer
->getCertificateKind());
837 m_xSignedValFt
->set_label(s
);
840 void SfxDocumentPage::ImplCheckPasswordState()
842 SfxObjectShell
* pShell
= SfxObjectShell::Current();
847 SfxItemSet
* pMedSet
= pShell
->GetMedium()->GetItemSet();
850 const SfxUnoAnyItem
* pEncryptionDataItem
= SfxItemSet::GetItem
<SfxUnoAnyItem
>(pMedSet
, SID_ENCRYPTIONDATA
, false);
851 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
852 if (pEncryptionDataItem
)
853 pEncryptionDataItem
->GetValue() >>= aEncryptionData
;
857 if (!aEncryptionData
.hasElements())
859 m_xChangePassBtn
->set_sensitive(true);
863 m_xChangePassBtn
->set_sensitive(comphelper::LibreOfficeKit::isActive());
866 std::unique_ptr
<SfxTabPage
> SfxDocumentPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
* rItemSet
)
868 return std::make_unique
<SfxDocumentPage
>(pPage
, pController
, *rItemSet
);
871 void SfxDocumentPage::EnableUseUserData()
873 bEnableUseUserData
= true;
874 m_xUseUserDataCB
->show();
875 m_xDeleteBtn
->show();
878 bool SfxDocumentPage::FillItemSet( SfxItemSet
* rSet
)
882 if ( !bHandleDelete
&& bEnableUseUserData
&&
883 m_xUseUserDataCB
->get_state_changed_from_saved() )
885 const SfxItemSet
* pExpSet
= GetDialogExampleSet();
886 const SfxPoolItem
* pItem
;
888 if ( pExpSet
&& SfxItemState::SET
== pExpSet
->GetItemState( SID_DOCINFO
, true, &pItem
) )
890 const SfxDocumentInfoItem
* pInfoItem
= static_cast<const SfxDocumentInfoItem
*>(pItem
);
891 bool bUseData
= ( TRISTATE_TRUE
== m_xUseUserDataCB
->get_state() );
892 const_cast<SfxDocumentInfoItem
*>(pInfoItem
)->SetUseUserData( bUseData
);
893 rSet
->Put( *pInfoItem
);
900 const SfxItemSet
* pExpSet
= GetDialogExampleSet();
901 const SfxPoolItem
* pItem
;
902 if ( pExpSet
&& SfxItemState::SET
== pExpSet
->GetItemState( SID_DOCINFO
, true, &pItem
) )
904 const SfxDocumentInfoItem
* pInfoItem
= static_cast<const SfxDocumentInfoItem
*>(pItem
);
905 bool bUseAuthor
= bEnableUseUserData
&& m_xUseUserDataCB
->get_active();
906 SfxDocumentInfoItem
newItem( *pInfoItem
);
907 newItem
.resetUserData( bUseAuthor
908 ? SvtUserOptions().GetFullName()
910 const_cast<SfxDocumentInfoItem
*>(pInfoItem
)->SetUseUserData( TRISTATE_TRUE
== m_xUseUserDataCB
->get_state() );
911 newItem
.SetUseUserData( TRISTATE_TRUE
== m_xUseUserDataCB
->get_state() );
913 newItem
.SetDeleteUserData( true );
914 rSet
->Put( newItem
);
919 if ( m_xUseThumbnailSaveCB
->get_state_changed_from_saved() )
921 const SfxItemSet
* pExpSet
= GetDialogExampleSet();
922 const SfxPoolItem
* pItem
;
924 if ( pExpSet
&& SfxItemState::SET
== pExpSet
->GetItemState( SID_DOCINFO
, true, &pItem
) )
926 const SfxDocumentInfoItem
* pInfoItem
= static_cast<const SfxDocumentInfoItem
*>(pItem
);
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::makeAny(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 const SfxPoolItem
* pItem
= nullptr;
1168 OUString
aTitle(m_xDialog
->get_title());
1169 if ( SfxItemState::SET
!=
1170 rItemSet
.GetItemState( SID_EXPLORER_PROPS_START
, false, &pItem
) )
1173 const OUString
& aFile( rInfoItem
.GetValue() );
1176 aURL
.SetSmartProtocol( INetProtocol::File
);
1177 aURL
.SetSmartURL( aFile
);
1178 if ( INetProtocol::PrivSoffice
!= aURL
.GetProtocol() )
1180 OUString
aLastName( aURL
.GetLastName() );
1181 if ( !aLastName
.isEmpty() )
1182 aTitle
= aTitle
.replaceFirst("%1", aLastName
);
1184 aTitle
= aTitle
.replaceFirst("%1", aFile
);
1187 aTitle
= aTitle
.replaceFirst("%1", SfxResId( STR_NONAME
));
1191 DBG_ASSERT( dynamic_cast<const SfxStringItem
*>(pItem
) != nullptr,
1192 "SfxDocumentInfoDialog:<SfxStringItem> expected" );
1193 aTitle
= aTitle
.replaceFirst("%1", static_cast<const SfxStringItem
*>(pItem
)->GetValue());
1195 m_xDialog
->set_title(aTitle
);
1198 AddTabPage("general", SfxDocumentPage::Create
, nullptr);
1199 AddTabPage("description", SfxDocumentDescPage::Create
, nullptr);
1201 if (!comphelper::LibreOfficeKit::isActive())
1202 AddTabPage("customprops", SfxCustomPropertiesPage::Create
, nullptr);
1204 RemoveTabPage("customprops");
1206 if (rInfoItem
.isCmisDocument())
1207 AddTabPage("cmisprops", SfxCmisPropertiesPage::Create
, nullptr);
1209 RemoveTabPage("cmisprops");
1210 // Disable security page for online as not fully asynced yet
1211 if (!comphelper::LibreOfficeKit::isActive())
1212 AddTabPage("security", SfxSecurityPage::Create
, nullptr);
1214 RemoveTabPage("security");
1217 void SfxDocumentInfoDialog::PageCreated(const OString
& rId
, SfxTabPage
&rPage
)
1219 if (rId
== "general")
1220 static_cast<SfxDocumentPage
&>(rPage
).EnableUseUserData();
1223 void SfxDocumentInfoDialog::AddFontTabPage()
1225 AddTabPage("font", SfxResId(STR_FONT_TABPAGE
), SfxDocumentFontsPage::Create
);
1228 // class CustomPropertiesYesNoButton -------------------------------------
1230 CustomPropertiesYesNoButton::CustomPropertiesYesNoButton(std::unique_ptr
<weld::Widget
> xTopLevel
,
1231 std::unique_ptr
<weld::RadioButton
> xYesButton
,
1232 std::unique_ptr
<weld::RadioButton
> xNoButton
)
1233 : m_xTopLevel(std::move(xTopLevel
))
1234 , m_xYesButton(std::move(xYesButton
))
1235 , m_xNoButton(std::move(xNoButton
))
1240 CustomPropertiesYesNoButton::~CustomPropertiesYesNoButton()
1245 DurationDialog_Impl::DurationDialog_Impl(weld::Widget
* pParent
, const util::Duration
& rDuration
)
1246 : GenericDialogController(pParent
, "sfx/ui/editdurationdialog.ui", "EditDurationDialog")
1247 , m_xNegativeCB(m_xBuilder
->weld_check_button("negative"))
1248 , m_xYearNF(m_xBuilder
->weld_spin_button("years"))
1249 , m_xMonthNF(m_xBuilder
->weld_spin_button("months"))
1250 , m_xDayNF(m_xBuilder
->weld_spin_button("days"))
1251 , m_xHourNF(m_xBuilder
->weld_spin_button("hours"))
1252 , m_xMinuteNF(m_xBuilder
->weld_spin_button("minutes"))
1253 , m_xSecondNF(m_xBuilder
->weld_spin_button("seconds"))
1254 , m_xMSecondNF(m_xBuilder
->weld_spin_button("milliseconds"))
1256 m_xNegativeCB
->set_active(rDuration
.Negative
);
1257 m_xYearNF
->set_value(rDuration
.Years
);
1258 m_xMonthNF
->set_value(rDuration
.Months
);
1259 m_xDayNF
->set_value(rDuration
.Days
);
1260 m_xHourNF
->set_value(rDuration
.Hours
);
1261 m_xMinuteNF
->set_value(rDuration
.Minutes
);
1262 m_xSecondNF
->set_value(rDuration
.Seconds
);
1263 m_xMSecondNF
->set_value(rDuration
.NanoSeconds
);
1266 util::Duration
DurationDialog_Impl::GetDuration() const
1268 util::Duration aRet
;
1269 aRet
.Negative
= m_xNegativeCB
->get_active();
1270 aRet
.Years
= m_xYearNF
->get_value();
1271 aRet
.Months
= m_xMonthNF
->get_value();
1272 aRet
.Days
= m_xDayNF
->get_value();
1273 aRet
.Hours
= m_xHourNF
->get_value();
1274 aRet
.Minutes
= m_xMinuteNF
->get_value();
1275 aRet
.Seconds
= m_xSecondNF
->get_value();
1276 aRet
.NanoSeconds
= m_xMSecondNF
->get_value();
1280 CustomPropertiesDurationField::CustomPropertiesDurationField(std::unique_ptr
<weld::Entry
> xEntry
,
1281 std::unique_ptr
<weld::Button
> xEditButton
)
1282 : m_xEntry(std::move(xEntry
))
1283 , m_xEditButton(std::move(xEditButton
))
1285 m_xEditButton
->connect_clicked(LINK(this, CustomPropertiesDurationField
, ClickHdl
));
1286 SetDuration( util::Duration(false, 0, 0, 0, 0, 0, 0, 0) );
1289 void CustomPropertiesDurationField::set_visible(bool bVisible
)
1291 m_xEntry
->set_visible(bVisible
);
1292 m_xEditButton
->set_visible(bVisible
);
1295 void CustomPropertiesDurationField::SetDuration( const util::Duration
& rDuration
)
1297 m_aDuration
= rDuration
;
1298 OUString sText
= (rDuration
.Negative
? OUString('-') : OUString('+')) +
1299 SfxResId(SFX_ST_DURATION_FORMAT
);
1300 sText
= sText
.replaceFirst( "%1", OUString::number( rDuration
.Years
) );
1301 sText
= sText
.replaceFirst( "%2", OUString::number( rDuration
.Months
) );
1302 sText
= sText
.replaceFirst( "%3", OUString::number( rDuration
.Days
) );
1303 sText
= sText
.replaceFirst( "%4", OUString::number( rDuration
.Hours
) );
1304 sText
= sText
.replaceFirst( "%5", OUString::number( rDuration
.Minutes
) );
1305 sText
= sText
.replaceFirst( "%6", OUString::number( rDuration
.Seconds
) );
1306 m_xEntry
->set_text(sText
);
1309 IMPL_LINK(CustomPropertiesDurationField
, ClickHdl
, weld::Button
&, rButton
, void)
1311 m_xDurationDialog
= std::make_shared
<DurationDialog_Impl
>(&rButton
, GetDuration());
1312 weld::DialogController::runAsync(m_xDurationDialog
, [&](sal_Int32 response
)
1314 if (response
== RET_OK
)
1316 SetDuration(m_xDurationDialog
->GetDuration());
1321 CustomPropertiesDurationField::~CustomPropertiesDurationField()
1323 if (m_xDurationDialog
)
1324 m_xDurationDialog
->response(RET_CANCEL
);
1329 void fillNameBox(weld::ComboBox
& rNameBox
)
1331 for (size_t i
= 0; i
< SAL_N_ELEMENTS(SFX_CB_PROPERTY_STRINGARRAY
); ++i
)
1332 rNameBox
.append_text(SfxResId(SFX_CB_PROPERTY_STRINGARRAY
[i
]));
1333 Size
aSize(rNameBox
.get_preferred_size());
1334 rNameBox
.set_size_request(aSize
.Width(), aSize
.Height());
1337 void fillTypeBox(weld::ComboBox
& rTypeBox
)
1339 for (size_t i
= 0; i
< SAL_N_ELEMENTS(SFX_LB_PROPERTY_STRINGARRAY
); ++i
)
1341 OUString
sId(OUString::number(SFX_LB_PROPERTY_STRINGARRAY
[i
].second
));
1342 rTypeBox
.append(sId
, SfxResId(SFX_LB_PROPERTY_STRINGARRAY
[i
].first
));
1344 rTypeBox
.set_active(0);
1345 Size
aSize(rTypeBox
.get_preferred_size());
1346 rTypeBox
.set_size_request(aSize
.Width(), aSize
.Height());
1350 // struct CustomPropertyLine ---------------------------------------------
1351 CustomPropertyLine::CustomPropertyLine(CustomPropertiesWindow
* pParent
, weld::Widget
* pContainer
)
1352 : m_pParent(pParent
)
1353 , m_xBuilder(Application::CreateBuilder(pContainer
, "sfx/ui/linefragment.ui"))
1354 , m_xLine(m_xBuilder
->weld_container("lineentry"))
1355 , m_xNameBox(m_xBuilder
->weld_combo_box("namebox"))
1356 , m_xTypeBox(m_xBuilder
->weld_combo_box("typebox"))
1357 , m_xValueEdit(m_xBuilder
->weld_entry("valueedit"))
1358 , m_xDateTimeBox(m_xBuilder
->weld_widget("datetimebox"))
1359 , m_xDateField(new CustomPropertiesDateField(new SvtCalendarBox(m_xBuilder
->weld_menu_button("date"))))
1360 , m_xTimeField(new CustomPropertiesTimeField(m_xBuilder
->weld_formatted_spin_button("time")))
1361 , m_xDurationBox(m_xBuilder
->weld_widget("durationbox"))
1362 , m_xDurationField(new CustomPropertiesDurationField(m_xBuilder
->weld_entry("duration"),
1363 m_xBuilder
->weld_button("durationbutton")))
1364 , m_xYesNoButton(new CustomPropertiesYesNoButton(m_xBuilder
->weld_widget("yesno"),
1365 m_xBuilder
->weld_radio_button("yes"),
1366 m_xBuilder
->weld_radio_button("no")))
1367 , m_xRemoveButton(m_xBuilder
->weld_button("remove"))
1368 , m_bTypeLostFocus( false )
1370 fillNameBox(*m_xNameBox
);
1371 fillTypeBox(*m_xTypeBox
);
1373 m_xTypeBox
->connect_changed(LINK(this, CustomPropertyLine
, TypeHdl
));
1374 m_xRemoveButton
->connect_clicked(LINK(this, CustomPropertyLine
, RemoveHdl
));
1375 m_xValueEdit
->connect_focus_out(LINK(this, CustomPropertyLine
, EditLoseFocusHdl
));
1376 //add lose focus handlers of date/time fields
1377 m_xTypeBox
->connect_focus_out(LINK(this, CustomPropertyLine
, BoxLoseFocusHdl
));
1380 void CustomPropertyLine::Clear()
1382 m_xNameBox
->set_active(-1);
1383 m_xValueEdit
->set_text(OUString());
1387 void CustomPropertyLine::Hide()
1392 CustomPropertiesWindow::CustomPropertiesWindow(weld::Container
& rParent
, weld::Label
& rHeaderAccName
,
1393 weld::Label
& rHeaderAccType
, weld::Label
& rHeaderAccValue
)
1397 , m_pCurrentLine(nullptr)
1398 , m_aNumberFormatter(::comphelper::getProcessComponentContext(),
1399 Application::GetSettings().GetLanguageTag().getLanguageType())
1400 , m_aEditLoseFocusIdle("sfx2 CustomPropertiesWindow loseFocusIdle")
1401 , m_aBoxLoseFocusIdle("sfx2 CustomPropertiesWindow m_aBoxLoseFocusIdle")
1403 , m_rHeaderAccName(rHeaderAccName
)
1404 , m_rHeaderAccType(rHeaderAccType
)
1405 , m_rHeaderAccValue(rHeaderAccValue
)
1407 m_aEditLoseFocusIdle
.SetPriority( TaskPriority::LOWEST
);
1408 m_aEditLoseFocusIdle
.SetInvokeHandler( LINK( this, CustomPropertiesWindow
, EditTimeoutHdl
) );
1409 m_aBoxLoseFocusIdle
.SetPriority( TaskPriority::LOWEST
);
1410 m_aBoxLoseFocusIdle
.SetInvokeHandler( LINK( this, CustomPropertiesWindow
, BoxTimeoutHdl
) );
1413 CustomPropertiesWindow::~CustomPropertiesWindow()
1415 m_aEditLoseFocusIdle
.Stop();
1416 m_aBoxLoseFocusIdle
.Stop();
1418 m_pCurrentLine
= nullptr;
1421 void CustomPropertyLine::DoTypeHdl(const weld::ComboBox
& rBox
)
1423 auto nType
= rBox
.get_active_id().toInt32();
1424 m_xValueEdit
->set_visible( (Custom_Type_Text
== nType
) || (Custom_Type_Number
== nType
) );
1425 m_xDateTimeBox
->set_visible( (Custom_Type_Date
== nType
) || (Custom_Type_Datetime
== nType
) );
1426 m_xDateField
->set_visible( (Custom_Type_Date
== nType
) || (Custom_Type_Datetime
== nType
) );
1427 m_xTimeField
->set_visible( Custom_Type_Datetime
== nType
);
1428 m_xDurationBox
->set_visible( Custom_Type_Duration
== nType
);
1429 m_xDurationField
->set_visible( Custom_Type_Duration
== nType
);
1430 m_xYesNoButton
->set_visible( Custom_Type_Boolean
== nType
);
1433 IMPL_LINK(CustomPropertyLine
, TypeHdl
, weld::ComboBox
&, rBox
, void)
1438 void CustomPropertiesWindow::Remove(const CustomPropertyLine
* pLine
)
1440 StoreCustomProperties();
1442 auto pFound
= std::find_if( m_aCustomPropertiesLines
.begin(), m_aCustomPropertiesLines
.end(),
1443 [&] (const std::unique_ptr
<CustomPropertyLine
>& p
) { return p
.get() == pLine
; });
1444 if ( pFound
!= m_aCustomPropertiesLines
.end() )
1446 sal_uInt32 nLineNumber
= pFound
- m_aCustomPropertiesLines
.begin();
1447 sal_uInt32 nDataModelIndex
= GetCurrentDataModelPosition() + nLineNumber
;
1448 m_aCustomProperties
.erase(m_aCustomProperties
.begin() + nDataModelIndex
);
1450 ReloadLinesContent();
1453 m_aRemovedHdl
.Call(nullptr);
1456 IMPL_LINK_NOARG(CustomPropertyLine
, RemoveHdl
, weld::Button
&, void)
1458 m_pParent
->Remove(this);
1461 void CustomPropertiesWindow::EditLoseFocus(CustomPropertyLine
* pLine
)
1463 m_pCurrentLine
= pLine
;
1464 m_aEditLoseFocusIdle
.Start();
1467 IMPL_LINK_NOARG(CustomPropertyLine
, EditLoseFocusHdl
, weld::Widget
&, void)
1469 if (!m_bTypeLostFocus
)
1470 m_pParent
->EditLoseFocus(this);
1472 m_bTypeLostFocus
= false;
1475 void CustomPropertiesWindow::BoxLoseFocus(CustomPropertyLine
* pLine
)
1477 m_pCurrentLine
= pLine
;
1478 m_aBoxLoseFocusIdle
.Start();
1481 IMPL_LINK_NOARG(CustomPropertyLine
, BoxLoseFocusHdl
, weld::Widget
&, void)
1483 m_pParent
->BoxLoseFocus(this);
1486 IMPL_LINK_NOARG(CustomPropertiesWindow
, EditTimeoutHdl
, Timer
*, void)
1488 ValidateLine( m_pCurrentLine
, false );
1491 IMPL_LINK_NOARG(CustomPropertiesWindow
, BoxTimeoutHdl
, Timer
*, void)
1493 ValidateLine( m_pCurrentLine
, true );
1496 bool CustomPropertiesWindow::IsLineValid( CustomPropertyLine
* pLine
) const
1498 bool bIsValid
= true;
1499 pLine
->m_bTypeLostFocus
= false;
1500 auto nType
= pLine
->m_xTypeBox
->get_active_id().toInt32();
1501 OUString sValue
= pLine
->m_xValueEdit
->get_text();
1502 if ( sValue
.isEmpty() )
1505 sal_uInt32 nIndex
= NUMBERFORMAT_ENTRY_NOT_FOUND
;
1506 if ( Custom_Type_Number
== nType
)
1507 // tdf#116214 Scientific format allows to use also standard numbers
1508 nIndex
= const_cast< SvNumberFormatter
& >(
1509 m_aNumberFormatter
).GetFormatIndex( NF_SCIENTIFIC_000E00
);
1510 else if ( Custom_Type_Date
== nType
)
1511 nIndex
= const_cast< SvNumberFormatter
& >(
1512 m_aNumberFormatter
).GetFormatIndex( NF_DATE_SYS_DDMMYYYY
);
1514 if ( nIndex
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
1516 sal_uInt32 nTemp
= nIndex
;
1517 double fDummy
= 0.0;
1518 bIsValid
= const_cast< SvNumberFormatter
& >(
1519 m_aNumberFormatter
).IsNumberFormat( sValue
, nIndex
, fDummy
);
1520 if ( bIsValid
&& nTemp
!= nIndex
)
1521 // sValue is a number but the format doesn't match the index
1528 void CustomPropertiesWindow::ValidateLine( CustomPropertyLine
* pLine
, bool bIsFromTypeBox
)
1530 if (pLine
&& !IsLineValid(pLine
))
1532 if ( bIsFromTypeBox
) // LoseFocus of TypeBox
1533 pLine
->m_bTypeLostFocus
= true;
1534 std::unique_ptr
<weld::MessageDialog
> xMessageBox(Application::CreateMessageDialog(&m_rBody
,
1535 VclMessageType::Question
, VclButtonsType::OkCancel
, SfxResId(STR_SFX_QUERY_WRONG_TYPE
)));
1536 if (xMessageBox
->run() == RET_OK
)
1537 pLine
->m_xTypeBox
->set_active_id(OUString::number(Custom_Type_Text
));
1539 pLine
->m_xValueEdit
->grab_focus();
1543 void CustomPropertiesWindow::SetVisibleLineCount(sal_uInt32 nCount
)
1545 while (GetExistingLineCount() < nCount
)
1551 void CustomPropertiesWindow::AddLine(const OUString
& sName
, Any
const & rAny
)
1553 m_aCustomProperties
.push_back(std::unique_ptr
<CustomProperty
>(new CustomProperty(sName
, rAny
)));
1554 ReloadLinesContent();
1557 void CustomPropertiesWindow::CreateNewLine()
1559 CustomPropertyLine
* pNewLine
= new CustomPropertyLine(this, &m_rBody
);
1560 pNewLine
->m_xNameBox
->set_accessible_relation_labeled_by(&m_rHeaderAccName
);
1561 pNewLine
->m_xNameBox
->set_accessible_name(m_rHeaderAccName
.get_label());
1562 pNewLine
->m_xTypeBox
->set_accessible_relation_labeled_by(&m_rHeaderAccType
);
1563 pNewLine
->m_xTypeBox
->set_accessible_name(m_rHeaderAccType
.get_label());
1564 pNewLine
->m_xValueEdit
->set_accessible_relation_labeled_by(&m_rHeaderAccValue
);
1565 pNewLine
->m_xValueEdit
->set_accessible_name(m_rHeaderAccValue
.get_label());
1567 m_aCustomPropertiesLines
.emplace_back( pNewLine
);
1569 // this breaks online's jsdialogbuilder
1570 if (!comphelper::LibreOfficeKit::isActive()){
1571 // for ui-testing. Distinguish the elements in the lines
1572 sal_uInt16 nSize
= m_aCustomPropertiesLines
.size();
1573 pNewLine
->m_xNameBox
->set_buildable_name(
1574 pNewLine
->m_xNameBox
->get_buildable_name() + OString::number(nSize
));
1575 pNewLine
->m_xTypeBox
->set_buildable_name(
1576 pNewLine
->m_xTypeBox
->get_buildable_name() + OString::number(nSize
));
1577 pNewLine
->m_xValueEdit
->set_buildable_name(
1578 pNewLine
->m_xValueEdit
->get_buildable_name() + OString::number(nSize
));
1579 pNewLine
->m_xRemoveButton
->set_buildable_name(
1580 pNewLine
->m_xRemoveButton
->get_buildable_name() + OString::number(nSize
));
1583 pNewLine
->DoTypeHdl(*pNewLine
->m_xTypeBox
);
1586 bool CustomPropertiesWindow::AreAllLinesValid() const
1589 for ( std::unique_ptr
<CustomPropertyLine
> const & pLine
: m_aCustomPropertiesLines
)
1591 if ( !IsLineValid( pLine
.get() ) )
1601 void CustomPropertiesWindow::ClearAllLines()
1603 for (auto& pLine
: m_aCustomPropertiesLines
)
1607 m_pCurrentLine
= nullptr;
1608 m_aCustomProperties
.clear();
1612 void CustomPropertiesWindow::DoScroll( sal_Int32 nNewPos
)
1614 StoreCustomProperties();
1615 m_nScrollPos
+= nNewPos
;
1616 ReloadLinesContent();
1619 Sequence
< beans::PropertyValue
> CustomPropertiesWindow::GetCustomProperties()
1621 StoreCustomProperties();
1623 Sequence
< beans::PropertyValue
> aPropertiesSeq(GetTotalLineCount());
1625 m_aCustomProperties
.begin(), m_aCustomProperties
.end(), aPropertiesSeq
.getArray(),
1626 [](const auto& el
) { return comphelper::makePropertyValue(el
->m_sName
, el
->m_aValue
); });
1628 return aPropertiesSeq
;
1631 CustomPropertiesTimeField::CustomPropertiesTimeField(std::unique_ptr
<weld::FormattedSpinButton
> xTimeField
)
1632 : m_xTimeField(std::move(xTimeField
))
1633 , m_xFormatter(new weld::TimeFormatter(*m_xTimeField
))
1636 m_xFormatter
->SetExtFormat(ExtTimeFieldFormat::LongDuration
);
1637 m_xFormatter
->EnableEmptyField(false);
1640 tools::Time
CustomPropertiesTimeField::get_value() const
1642 return m_xFormatter
->GetTime();
1645 void CustomPropertiesTimeField::set_value(const tools::Time
& rTime
)
1647 m_xFormatter
->SetTime(rTime
);
1650 CustomPropertiesTimeField::~CustomPropertiesTimeField()
1654 CustomPropertiesDateField::CustomPropertiesDateField(SvtCalendarBox
* pDateField
)
1655 : m_xDateField(pDateField
)
1657 DateTime
aDateTime(DateTime::SYSTEM
);
1658 m_xDateField
->set_date(aDateTime
);
1661 void CustomPropertiesDateField::set_visible(bool bVisible
)
1663 m_xDateField
->set_visible(bVisible
);
1666 Date
CustomPropertiesDateField::get_date() const
1668 return m_xDateField
->get_date();
1671 void CustomPropertiesDateField::set_date(const Date
& rDate
)
1673 m_xDateField
->set_date(rDate
);
1676 CustomPropertiesDateField::~CustomPropertiesDateField()
1680 void CustomPropertiesWindow::StoreCustomProperties()
1682 sal_uInt32 nDataModelPos
= GetCurrentDataModelPosition();
1684 for (sal_uInt32 i
= 0; nDataModelPos
+ i
< GetTotalLineCount() && i
< GetExistingLineCount(); i
++)
1686 CustomPropertyLine
* pLine
= m_aCustomPropertiesLines
[i
].get();
1688 OUString sPropertyName
= pLine
->m_xNameBox
->get_active_text();
1689 if (!sPropertyName
.isEmpty())
1691 m_aCustomProperties
[nDataModelPos
+ i
]->m_sName
= sPropertyName
;
1692 auto nType
= pLine
->m_xTypeBox
->get_active_id().toInt32();
1693 if (Custom_Type_Number
== nType
)
1696 sal_uInt32 nIndex
= m_aNumberFormatter
.GetFormatIndex(NF_NUMBER_SYSTEM
);
1697 bool bIsNum
= m_aNumberFormatter
.
1698 IsNumberFormat(pLine
->m_xValueEdit
->get_text(), nIndex
, nValue
);
1700 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= nValue
;
1702 else if (Custom_Type_Boolean
== nType
)
1704 bool bValue
= pLine
->m_xYesNoButton
->IsYesChecked();
1705 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= bValue
;
1707 else if (Custom_Type_Datetime
== nType
)
1709 Date aTmpDate
= pLine
->m_xDateField
->get_date();
1710 tools::Time aTmpTime
= pLine
->m_xTimeField
->get_value();
1711 util::DateTime
const aDateTime(aTmpTime
.GetNanoSec(),
1712 aTmpTime
.GetSec(), aTmpTime
.GetMin(), aTmpTime
.GetHour(),
1713 aTmpDate
.GetDay(), aTmpDate
.GetMonth(), aTmpDate
.GetYear(),
1714 pLine
->m_xTimeField
->m_isUTC
);
1715 if (pLine
->m_xDateField
->m_TZ
)
1717 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= util::DateTimeWithTimezone(
1718 aDateTime
, *pLine
->m_xDateField
->m_TZ
);
1722 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= aDateTime
;
1725 else if (Custom_Type_Date
== nType
)
1727 Date aTmpDate
= pLine
->m_xDateField
->get_date();
1728 util::Date
const aDate(aTmpDate
.GetDay(), aTmpDate
.GetMonth(),
1729 aTmpDate
.GetYear());
1730 if (pLine
->m_xDateField
->m_TZ
)
1732 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= util::DateWithTimezone(
1733 aDate
, *pLine
->m_xDateField
->m_TZ
);
1737 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= aDate
;
1740 else if (Custom_Type_Duration
== nType
)
1742 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= pLine
->m_xDurationField
->GetDuration();
1746 OUString
sValue(pLine
->m_xValueEdit
->get_text());
1747 m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
<<= sValue
;
1753 void CustomPropertiesWindow::SetCustomProperties(std::vector
< std::unique_ptr
<CustomProperty
> >&& rProperties
)
1755 m_aCustomProperties
= std::move(rProperties
);
1756 ReloadLinesContent();
1759 void CustomPropertiesWindow::ReloadLinesContent()
1761 double nTmpValue
= 0;
1762 bool bTmpValue
= false;
1764 util::DateTime aTmpDateTime
;
1765 util::Date aTmpDate
;
1766 util::DateTimeWithTimezone aTmpDateTimeTZ
;
1767 util::DateWithTimezone aTmpDateTZ
;
1768 util::Duration aTmpDuration
;
1769 SvtSysLocale aSysLocale
;
1770 const LocaleDataWrapper
& rLocaleWrapper
= aSysLocale
.GetLocaleData();
1771 CustomProperties nType
= Custom_Type_Unknown
;
1774 sal_uInt32 nDataModelPos
= GetCurrentDataModelPosition();
1777 for (; nDataModelPos
+ i
< GetTotalLineCount() && i
< GetExistingLineCount(); i
++)
1779 const OUString
& rName
= m_aCustomProperties
[nDataModelPos
+ i
]->m_sName
;
1780 const css::uno::Any
& rAny
= m_aCustomProperties
[nDataModelPos
+ i
]->m_aValue
;
1782 CustomPropertyLine
* pLine
= m_aCustomPropertiesLines
[i
].get();
1785 pLine
->m_xNameBox
->set_entry_text(rName
);
1786 pLine
->m_xLine
->show();
1788 if (!rAny
.hasValue())
1790 pLine
->m_xValueEdit
->set_text(OUString());
1792 else if (rAny
>>= nTmpValue
)
1794 sal_uInt32 nIndex
= m_aNumberFormatter
.GetFormatIndex(NF_NUMBER_SYSTEM
);
1795 m_aNumberFormatter
.GetInputLineString(nTmpValue
, nIndex
, sValue
);
1796 pLine
->m_xValueEdit
->set_text(sValue
);
1797 nType
= Custom_Type_Number
;
1799 else if (rAny
>>= bTmpValue
)
1801 sValue
= (bTmpValue
? rLocaleWrapper
.getTrueWord() : rLocaleWrapper
.getFalseWord());
1802 nType
= Custom_Type_Boolean
;
1804 else if (rAny
>>= sTmpValue
)
1806 pLine
->m_xValueEdit
->set_text(sTmpValue
);
1807 nType
= Custom_Type_Text
;
1809 else if (rAny
>>= aTmpDate
)
1811 pLine
->m_xDateField
->set_date(Date(aTmpDate
));
1812 nType
= Custom_Type_Date
;
1814 else if (rAny
>>= aTmpDateTime
)
1816 pLine
->m_xDateField
->set_date(Date(aTmpDateTime
));
1817 pLine
->m_xTimeField
->set_value(tools::Time(aTmpDateTime
));
1818 pLine
->m_xTimeField
->m_isUTC
= aTmpDateTime
.IsUTC
;
1819 nType
= Custom_Type_Datetime
;
1821 else if (rAny
>>= aTmpDateTZ
)
1823 pLine
->m_xDateField
->set_date(Date(aTmpDateTZ
.DateInTZ
.Day
,
1824 aTmpDateTZ
.DateInTZ
.Month
, aTmpDateTZ
.DateInTZ
.Year
));
1825 pLine
->m_xDateField
->m_TZ
= aTmpDateTZ
.Timezone
;
1826 nType
= Custom_Type_Date
;
1829 else if (rAny
>>= aTmpDateTimeTZ
)
1831 util::DateTime
const& rDT(aTmpDateTimeTZ
.DateTimeInTZ
);
1832 pLine
->m_xDateField
->set_date(Date(rDT
));
1833 pLine
->m_xTimeField
->set_value(tools::Time(rDT
));
1834 pLine
->m_xTimeField
->m_isUTC
= rDT
.IsUTC
;
1835 pLine
->m_xDateField
->m_TZ
= aTmpDateTimeTZ
.Timezone
;
1836 nType
= Custom_Type_Datetime
;
1838 else if (rAny
>>= aTmpDuration
)
1840 nType
= Custom_Type_Duration
;
1841 pLine
->m_xDurationField
->SetDuration(aTmpDuration
);
1844 if (Custom_Type_Boolean
== nType
)
1847 pLine
->m_xYesNoButton
->CheckYes();
1849 pLine
->m_xYesNoButton
->CheckNo();
1851 pLine
->m_xTypeBox
->set_active_id(OUString::number(nType
));
1853 pLine
->DoTypeHdl(*pLine
->m_xTypeBox
);
1856 // tdf#132667 - grab focus on the last inserted property
1857 if (i
> 0 && m_aCustomProperties
[nDataModelPos
+ i
- 1]->m_sName
.isEmpty())
1859 CustomPropertyLine
* pLine
= m_aCustomPropertiesLines
[i
- 1].get();
1860 pLine
->m_xNameBox
->grab_focus();
1863 while (nDataModelPos
+ i
>= GetTotalLineCount() && i
< GetExistingLineCount())
1865 CustomPropertyLine
* pLine
= m_aCustomPropertiesLines
[i
].get();
1871 CustomPropertiesControl::CustomPropertiesControl()
1876 void CustomPropertiesControl::Init(weld::Builder
& rBuilder
)
1878 m_xBox
= rBuilder
.weld_widget("box");
1879 m_xBody
= rBuilder
.weld_container("properties");
1881 m_xName
= rBuilder
.weld_label("name");
1882 m_xType
= rBuilder
.weld_label("type");
1883 m_xValue
= rBuilder
.weld_label("value");
1884 m_xVertScroll
= rBuilder
.weld_scrolled_window("scroll", true);
1885 m_xPropertiesWin
.reset(new CustomPropertiesWindow(*m_xBody
, *m_xName
, *m_xType
, *m_xValue
));
1887 m_xBox
->set_stack_background();
1888 m_xVertScroll
->show();
1890 std::unique_ptr
<CustomPropertyLine
> xNewLine(new CustomPropertyLine(m_xPropertiesWin
.get(), m_xBody
.get()));
1891 Size
aLineSize(xNewLine
->m_xLine
->get_preferred_size());
1892 m_xPropertiesWin
->SetLineHeight(aLineSize
.Height() + 6);
1893 m_xBody
->set_size_request(aLineSize
.Width() + 6, -1);
1894 auto nHeight
= aLineSize
.Height() * 8;
1895 m_xVertScroll
->set_size_request(-1, nHeight
+ 6);
1897 m_xPropertiesWin
->SetHeight(nHeight
);
1898 m_xVertScroll
->connect_size_allocate(LINK(this, CustomPropertiesControl
, ResizeHdl
));
1900 m_xName
->set_size_request(xNewLine
->m_xNameBox
->get_preferred_size().Width(), -1);
1901 m_xType
->set_size_request(xNewLine
->m_xTypeBox
->get_preferred_size().Width(), -1);
1902 m_xValue
->set_size_request(xNewLine
->m_xValueEdit
->get_preferred_size().Width(), -1);
1904 m_xBody
->move(xNewLine
->m_xLine
.get(), nullptr);
1907 m_xPropertiesWin
->SetRemovedHdl( LINK( this, CustomPropertiesControl
, RemovedHdl
) );
1909 m_xVertScroll
->vadjustment_set_lower(0);
1910 m_xVertScroll
->vadjustment_set_upper(0);
1911 m_xVertScroll
->vadjustment_set_page_size(0xFFFF);
1913 Link
<weld::ScrolledWindow
&,void> aScrollLink
= LINK( this, CustomPropertiesControl
, ScrollHdl
);
1914 m_xVertScroll
->connect_vadjustment_changed(aScrollLink
);
1916 ResizeHdl(Size(-1, nHeight
));
1919 IMPL_LINK(CustomPropertiesControl
, ResizeHdl
, const Size
&, rSize
, void)
1921 int nHeight
= rSize
.Height() - 6;
1922 if (nHeight
== m_xPropertiesWin
->GetHeight())
1924 m_xPropertiesWin
->SetHeight(nHeight
);
1925 sal_Int32 nScrollOffset
= m_xPropertiesWin
->GetLineHeight();
1926 sal_Int32 nVisibleEntries
= nHeight
/ nScrollOffset
;
1927 m_xPropertiesWin
->SetVisibleLineCount( nVisibleEntries
);
1928 m_xVertScroll
->vadjustment_set_page_increment( nVisibleEntries
- 1 );
1929 m_xVertScroll
->vadjustment_set_page_size( nVisibleEntries
);
1930 m_xPropertiesWin
->ReloadLinesContent();
1933 CustomPropertiesControl::~CustomPropertiesControl()
1937 IMPL_LINK( CustomPropertiesControl
, ScrollHdl
, weld::ScrolledWindow
&, rScrollBar
, void )
1939 sal_Int32 nOffset
= m_xPropertiesWin
->GetLineHeight();
1940 int nThumbPos
= rScrollBar
.vadjustment_get_value();
1941 nOffset
*= ( m_nThumbPos
- nThumbPos
);
1942 m_nThumbPos
= nThumbPos
;
1943 m_xPropertiesWin
->DoScroll( nOffset
);
1946 IMPL_LINK_NOARG(CustomPropertiesControl
, RemovedHdl
, void*, void)
1948 auto nLineCount
= m_xPropertiesWin
->GetTotalLineCount();
1949 m_xVertScroll
->vadjustment_set_upper(nLineCount
+ 1);
1950 if (m_xPropertiesWin
->GetTotalLineCount() > m_xPropertiesWin
->GetExistingLineCount())
1952 m_xVertScroll
->vadjustment_set_value(nLineCount
- 1);
1953 ScrollHdl(*m_xVertScroll
);
1957 void CustomPropertiesControl::AddLine( Any
const & rAny
)
1959 m_xPropertiesWin
->AddLine( OUString(), rAny
);
1960 auto nLineCount
= m_xPropertiesWin
->GetTotalLineCount();
1961 m_xVertScroll
->vadjustment_set_upper(nLineCount
+ 1);
1962 if (m_xPropertiesWin
->GetHeight() < nLineCount
* m_xPropertiesWin
->GetLineHeight())
1964 m_xVertScroll
->vadjustment_set_value(nLineCount
+ 1);
1965 ScrollHdl(*m_xVertScroll
);
1969 void CustomPropertiesControl::SetCustomProperties(std::vector
< std::unique_ptr
<CustomProperty
> >&& rProperties
)
1971 m_xPropertiesWin
->SetCustomProperties(std::move(rProperties
));
1972 auto nLineCount
= m_xPropertiesWin
->GetTotalLineCount();
1973 m_xVertScroll
->vadjustment_set_upper(nLineCount
+ 1);
1976 // class SfxCustomPropertiesPage -----------------------------------------
1977 SfxCustomPropertiesPage::SfxCustomPropertiesPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rItemSet
)
1978 : SfxTabPage(pPage
, pController
, "sfx/ui/custominfopage.ui", "CustomInfoPage", &rItemSet
)
1979 , m_xPropertiesCtrl(new CustomPropertiesControl
)
1980 , m_xAdd(m_xBuilder
->weld_button("add"))
1982 m_xPropertiesCtrl
->Init(*m_xBuilder
);
1983 m_xAdd
->connect_clicked(LINK(this, SfxCustomPropertiesPage
, AddHdl
));
1986 SfxCustomPropertiesPage::~SfxCustomPropertiesPage()
1988 m_xPropertiesCtrl
.reset();
1991 IMPL_LINK_NOARG(SfxCustomPropertiesPage
, AddHdl
, weld::Button
&, void)
1993 // tdf#115853: reload current lines before adding a brand new one
1994 // indeed the info are deleted by ClearCustomProperties
1995 // each time SfxDocumentInfoItem destructor is called
1996 SfxDocumentInfoItem pInfo
;
1997 const Sequence
< beans::PropertyValue
> aPropertySeq
= m_xPropertiesCtrl
->GetCustomProperties();
1998 for ( const auto& rProperty
: aPropertySeq
)
2000 if ( !rProperty
.Name
.isEmpty() )
2002 pInfo
.AddCustomProperty( rProperty
.Name
, rProperty
.Value
);
2007 m_xPropertiesCtrl
->AddLine(aAny
);
2010 bool SfxCustomPropertiesPage::FillItemSet( SfxItemSet
* rSet
)
2012 const SfxPoolItem
* pItem
= nullptr;
2013 SfxDocumentInfoItem
* pInfo
= nullptr;
2014 bool bMustDelete
= false;
2016 if (const SfxItemSet
* pItemSet
= GetDialogExampleSet())
2018 if (SfxItemState::SET
!= pItemSet
->GetItemState(SID_DOCINFO
, true, &pItem
))
2019 pInfo
= const_cast<SfxDocumentInfoItem
*>(&rSet
->Get( SID_DOCINFO
));
2023 pInfo
= new SfxDocumentInfoItem( *static_cast<const SfxDocumentInfoItem
*>(pItem
) );
2029 // If it's a CMIS document, we can't save custom properties
2030 if ( pInfo
->isCmisDocument( ) )
2037 pInfo
->ClearCustomProperties();
2038 const Sequence
< beans::PropertyValue
> aPropertySeq
= m_xPropertiesCtrl
->GetCustomProperties();
2039 for ( const auto& rProperty
: aPropertySeq
)
2041 if ( !rProperty
.Name
.isEmpty() )
2042 pInfo
->AddCustomProperty( rProperty
.Name
, rProperty
.Value
);
2055 void SfxCustomPropertiesPage::Reset( const SfxItemSet
* rItemSet
)
2057 m_xPropertiesCtrl
->ClearAllLines();
2058 const SfxDocumentInfoItem
& rInfoItem
= rItemSet
->Get(SID_DOCINFO
);
2059 std::vector
< std::unique_ptr
<CustomProperty
> > aCustomProps
= rInfoItem
.GetCustomProperties();
2060 // tdf#123919 - sort custom document properties
2061 auto const sort
= comphelper::string::NaturalStringSorter(
2062 comphelper::getProcessComponentContext(),
2063 Application::GetSettings().GetLanguageTag().getLocale());
2064 std::sort(aCustomProps
.begin(), aCustomProps
.end(),
2065 [&sort
](const std::unique_ptr
<CustomProperty
>& rLHS
,
2066 const std::unique_ptr
<CustomProperty
>& rRHS
) {
2067 return sort
.compare(rLHS
->m_sName
, rRHS
->m_sName
) < 0;
2069 m_xPropertiesCtrl
->SetCustomProperties(std::move(aCustomProps
));
2072 DeactivateRC
SfxCustomPropertiesPage::DeactivatePage( SfxItemSet
* /*pSet*/ )
2074 DeactivateRC nRet
= DeactivateRC::LeavePage
;
2075 if ( !m_xPropertiesCtrl
->AreAllLinesValid() )
2076 nRet
= DeactivateRC::KeepPage
;
2080 std::unique_ptr
<SfxTabPage
> SfxCustomPropertiesPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
* rItemSet
)
2082 return std::make_unique
<SfxCustomPropertiesPage
>(pPage
, pController
, *rItemSet
);
2085 CmisValue::CmisValue(weld::Widget
* pParent
, const OUString
& aStr
)
2086 : m_xBuilder(Application::CreateBuilder(pParent
, "sfx/ui/cmisline.ui"))
2087 , m_xFrame(m_xBuilder
->weld_frame("CmisFrame"))
2088 , m_xValueEdit(m_xBuilder
->weld_entry("value"))
2090 m_xValueEdit
->show();
2091 m_xValueEdit
->set_text(aStr
);
2094 CmisDateTime::CmisDateTime(weld::Widget
* pParent
, const util::DateTime
& aDateTime
)
2095 : m_xBuilder(Application::CreateBuilder(pParent
, "sfx/ui/cmisline.ui"))
2096 , m_xFrame(m_xBuilder
->weld_frame("CmisFrame"))
2097 , m_xDateField(new SvtCalendarBox(m_xBuilder
->weld_menu_button("date")))
2098 , m_xTimeField(m_xBuilder
->weld_formatted_spin_button("time"))
2099 , m_xFormatter(new weld::TimeFormatter(*m_xTimeField
))
2101 m_xFormatter
->SetExtFormat(ExtTimeFieldFormat::LongDuration
);
2102 m_xFormatter
->EnableEmptyField(false);
2104 m_xDateField
->show();
2105 m_xTimeField
->show();
2106 m_xDateField
->set_date(Date(aDateTime
));
2107 m_xFormatter
->SetTime(tools::Time(aDateTime
));
2110 CmisYesNo::CmisYesNo(weld::Widget
* pParent
, bool bValue
)
2111 : m_xBuilder(Application::CreateBuilder(pParent
, "sfx/ui/cmisline.ui"))
2112 , m_xFrame(m_xBuilder
->weld_frame("CmisFrame"))
2113 , m_xYesButton(m_xBuilder
->weld_radio_button("yes"))
2114 , m_xNoButton(m_xBuilder
->weld_radio_button("no"))
2116 m_xYesButton
->show();
2117 m_xNoButton
->show();
2119 m_xYesButton
->set_active(true);
2121 m_xNoButton
->set_active(true);
2124 // struct CmisPropertyLine ---------------------------------------------
2125 CmisPropertyLine::CmisPropertyLine(weld::Widget
* pParent
)
2126 : m_xBuilder(Application::CreateBuilder(pParent
, "sfx/ui/cmisline.ui"))
2127 , m_sType(CMIS_TYPE_STRING
)
2128 , m_bUpdatable(false)
2129 , m_bRequired(false)
2130 , m_bMultiValued(false)
2131 , m_bOpenChoice(false)
2132 , m_xFrame(m_xBuilder
->weld_frame("CmisFrame"))
2133 , m_xName(m_xBuilder
->weld_label("name"))
2134 , m_xType(m_xBuilder
->weld_label("type"))
2136 m_xFrame
->set_sensitive(true);
2139 CmisPropertyLine::~CmisPropertyLine( )
2143 // class CmisPropertiesWindow -----------------------------------------
2145 CmisPropertiesWindow::CmisPropertiesWindow(std::unique_ptr
<weld::Container
> xParent
)
2146 : m_xBox(std::move(xParent
))
2147 , m_aNumberFormatter(::comphelper::getProcessComponentContext(),
2148 Application::GetSettings().GetLanguageTag().getLanguageType())
2152 CmisPropertiesWindow::~CmisPropertiesWindow()
2156 void CmisPropertiesWindow::ClearAllLines()
2158 m_aCmisPropertiesLines
.clear();
2161 void CmisPropertiesWindow::AddLine( const OUString
& sId
, const OUString
& sName
,
2162 const OUString
& sType
, const bool bUpdatable
,
2163 const bool bRequired
, const bool bMultiValued
,
2164 const bool bOpenChoice
, Any
& /*aChoices*/, Any
const & rAny
)
2166 std::unique_ptr
<CmisPropertyLine
> pNewLine(new CmisPropertyLine(m_xBox
.get()));
2168 pNewLine
->m_sId
= sId
;
2169 pNewLine
->m_sType
= sType
;
2170 pNewLine
->m_bUpdatable
= bUpdatable
;
2171 pNewLine
->m_bRequired
= bRequired
;
2172 pNewLine
->m_bMultiValued
= bMultiValued
;
2173 pNewLine
->m_bOpenChoice
= bOpenChoice
;
2175 if ( sType
== CMIS_TYPE_INTEGER
)
2177 Sequence
< sal_Int64
> seqValue
;
2179 sal_uInt32 nIndex
= m_aNumberFormatter
.GetFormatIndex( NF_NUMBER_SYSTEM
);
2180 for ( const auto& rValue
: std::as_const(seqValue
) )
2183 m_aNumberFormatter
.GetInputLineString( rValue
, nIndex
, sValue
);
2184 std::unique_ptr
<CmisValue
> pValue(new CmisValue(m_xBox
.get(), sValue
));
2185 pValue
->m_xValueEdit
->set_editable(bUpdatable
);
2186 pNewLine
->m_aValues
.push_back( std::move(pValue
) );
2189 else if ( sType
== CMIS_TYPE_DECIMAL
)
2191 Sequence
< double > seqValue
;
2193 sal_uInt32 nIndex
= m_aNumberFormatter
.GetFormatIndex( NF_NUMBER_SYSTEM
);
2194 for ( const auto& rValue
: std::as_const(seqValue
) )
2197 m_aNumberFormatter
.GetInputLineString( rValue
, nIndex
, sValue
);
2198 std::unique_ptr
<CmisValue
> pValue(new CmisValue(m_xBox
.get(), sValue
));
2199 pValue
->m_xValueEdit
->set_editable(bUpdatable
);
2200 pNewLine
->m_aValues
.push_back( std::move(pValue
) );
2204 else if ( sType
== CMIS_TYPE_BOOL
)
2206 Sequence
<sal_Bool
> seqValue
;
2208 for ( const auto& rValue
: std::as_const(seqValue
) )
2210 std::unique_ptr
<CmisYesNo
> pYesNo(new CmisYesNo(m_xBox
.get(), rValue
));
2211 pYesNo
->m_xYesButton
->set_sensitive( bUpdatable
);
2212 pYesNo
->m_xNoButton
->set_sensitive( bUpdatable
);
2213 pNewLine
->m_aYesNos
.push_back( std::move(pYesNo
) );
2216 else if ( sType
== CMIS_TYPE_STRING
)
2218 Sequence
< OUString
> seqValue
;
2220 for ( const auto& rValue
: std::as_const(seqValue
) )
2222 std::unique_ptr
<CmisValue
> pValue(new CmisValue(m_xBox
.get(), rValue
));
2223 pValue
->m_xValueEdit
->set_editable(bUpdatable
);
2224 pNewLine
->m_aValues
.push_back( std::move(pValue
) );
2227 else if ( sType
== CMIS_TYPE_DATETIME
)
2229 Sequence
< util::DateTime
> seqValue
;
2231 for ( const auto& rValue
: std::as_const(seqValue
) )
2233 std::unique_ptr
<CmisDateTime
> pDateTime(new CmisDateTime(m_xBox
.get(), rValue
));
2234 pDateTime
->m_xDateField
->set_sensitive(bUpdatable
);
2235 pDateTime
->m_xTimeField
->set_sensitive(bUpdatable
);
2236 pNewLine
->m_aDateTimes
.push_back( std::move(pDateTime
) );
2239 pNewLine
->m_xName
->set_label( sName
);
2240 pNewLine
->m_xName
->show();
2241 pNewLine
->m_xType
->set_label( sType
);
2242 pNewLine
->m_xType
->show();
2244 m_aCmisPropertiesLines
.push_back( std::move(pNewLine
) );
2247 Sequence
< document::CmisProperty
> CmisPropertiesWindow::GetCmisProperties() const
2249 Sequence
< document::CmisProperty
> aPropertiesSeq( m_aCmisPropertiesLines
.size() );
2250 auto aPropertiesSeqRange
= asNonConstRange(aPropertiesSeq
);
2252 for ( auto& rxLine
: m_aCmisPropertiesLines
)
2254 CmisPropertyLine
* pLine
= rxLine
.get();
2256 aPropertiesSeqRange
[i
].Id
= pLine
->m_sId
;
2257 aPropertiesSeqRange
[i
].Type
= pLine
->m_sType
;
2258 aPropertiesSeqRange
[i
].Updatable
= pLine
->m_bUpdatable
;
2259 aPropertiesSeqRange
[i
].Required
= pLine
->m_bRequired
;
2260 aPropertiesSeqRange
[i
].OpenChoice
= pLine
->m_bOpenChoice
;
2261 aPropertiesSeqRange
[i
].MultiValued
= pLine
->m_bMultiValued
;
2263 OUString sPropertyName
= pLine
->m_xName
->get_label();
2264 if ( !sPropertyName
.isEmpty() )
2266 aPropertiesSeqRange
[i
].Name
= sPropertyName
;
2267 OUString sType
= pLine
->m_xType
->get_label();
2268 if ( CMIS_TYPE_DECIMAL
== sType
)
2270 sal_uInt32 nIndex
= const_cast< SvNumberFormatter
& >(
2271 m_aNumberFormatter
).GetFormatIndex( NF_NUMBER_SYSTEM
);
2272 Sequence
< double > seqValue( pLine
->m_aValues
.size( ) );
2273 auto seqValueRange
= asNonConstRange(seqValue
);
2275 for ( const auto& rxValue
: pLine
->m_aValues
)
2277 double dValue
= 0.0;
2278 OUString
sValue( rxValue
->m_xValueEdit
->get_text() );
2279 bool bIsNum
= const_cast< SvNumberFormatter
& >( m_aNumberFormatter
).
2280 IsNumberFormat( sValue
, nIndex
, dValue
);
2282 seqValueRange
[k
] = dValue
;
2285 aPropertiesSeqRange
[i
].Value
<<= seqValue
;
2287 else if ( CMIS_TYPE_INTEGER
== sType
)
2289 sal_uInt32 nIndex
= const_cast< SvNumberFormatter
& >(
2290 m_aNumberFormatter
).GetFormatIndex( NF_NUMBER_SYSTEM
);
2291 Sequence
< sal_Int64
> seqValue( pLine
->m_aValues
.size( ) );
2292 auto seqValueRange
= asNonConstRange(seqValue
);
2294 for ( const auto& rxValue
: pLine
->m_aValues
)
2297 OUString
sValue( rxValue
->m_xValueEdit
->get_text() );
2298 bool bIsNum
= const_cast< SvNumberFormatter
& >( m_aNumberFormatter
).
2299 IsNumberFormat( sValue
, nIndex
, dValue
);
2301 seqValueRange
[k
] = static_cast<sal_Int64
>(dValue
);
2304 aPropertiesSeqRange
[i
].Value
<<= seqValue
;
2306 else if ( CMIS_TYPE_BOOL
== sType
)
2308 Sequence
<sal_Bool
> seqValue( pLine
->m_aYesNos
.size( ) );
2309 sal_Bool
* pseqValue
= seqValue
.getArray();
2311 for ( const auto& rxYesNo
: pLine
->m_aYesNos
)
2313 bool bValue
= rxYesNo
->m_xYesButton
->get_active();
2314 pseqValue
[k
] = bValue
;
2317 aPropertiesSeqRange
[i
].Value
<<= seqValue
;
2320 else if ( CMIS_TYPE_DATETIME
== sType
)
2322 Sequence
< util::DateTime
> seqValue( pLine
->m_aDateTimes
.size( ) );
2323 auto seqValueRange
= asNonConstRange(seqValue
);
2325 for ( const auto& rxDateTime
: pLine
->m_aDateTimes
)
2327 Date aTmpDate
= rxDateTime
->m_xDateField
->get_date();
2328 tools::Time aTmpTime
= rxDateTime
->m_xFormatter
->GetTime();
2329 util::DateTime
aDateTime( aTmpTime
.GetNanoSec(), aTmpTime
.GetSec(),
2330 aTmpTime
.GetMin(), aTmpTime
.GetHour(),
2331 aTmpDate
.GetDay(), aTmpDate
.GetMonth(),
2332 aTmpDate
.GetYear(), true );
2333 seqValueRange
[k
] = aDateTime
;
2336 aPropertiesSeqRange
[i
].Value
<<= seqValue
;
2340 Sequence
< OUString
> seqValue( pLine
->m_aValues
.size( ) );
2341 auto seqValueRange
= asNonConstRange(seqValue
);
2343 for ( const auto& rxValue
: pLine
->m_aValues
)
2345 OUString
sValue( rxValue
->m_xValueEdit
->get_text() );
2346 seqValueRange
[k
] = sValue
;
2349 aPropertiesSeqRange
[i
].Value
<<= seqValue
;
2355 return aPropertiesSeq
;
2358 CmisPropertiesControl::CmisPropertiesControl(weld::Builder
& rBuilder
)
2359 : m_aPropertiesWin(rBuilder
.weld_container("CmisWindow"))
2360 , m_xScrolledWindow(rBuilder
.weld_scrolled_window("CmisScroll"))
2362 // set height to something small and force it to take the size
2363 // dictated by the other pages
2364 m_xScrolledWindow
->set_size_request(-1, 42);
2367 void CmisPropertiesControl::ClearAllLines()
2369 m_aPropertiesWin
.ClearAllLines();
2372 void CmisPropertiesControl::AddLine( const OUString
& sId
, const OUString
& sName
,
2373 const OUString
& sType
, const bool bUpdatable
,
2374 const bool bRequired
, const bool bMultiValued
,
2375 const bool bOpenChoice
, Any
& aChoices
, Any
const & rAny
2378 m_aPropertiesWin
.AddLine( sId
, sName
, sType
, bUpdatable
, bRequired
, bMultiValued
,
2379 bOpenChoice
, aChoices
, rAny
);
2382 // class SfxCmisPropertiesPage -----------------------------------------
2383 SfxCmisPropertiesPage::SfxCmisPropertiesPage(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
& rItemSet
)
2384 : SfxTabPage(pPage
, pController
, "sfx/ui/cmisinfopage.ui", "CmisInfoPage", &rItemSet
)
2385 , m_xPropertiesCtrl(new CmisPropertiesControl(*m_xBuilder
))
2389 SfxCmisPropertiesPage::~SfxCmisPropertiesPage()
2391 m_xPropertiesCtrl
.reset();
2394 bool SfxCmisPropertiesPage::FillItemSet( SfxItemSet
* rSet
)
2396 const SfxPoolItem
* pItem
= nullptr;
2397 SfxDocumentInfoItem
* pInfo
= nullptr;
2398 bool bMustDelete
= false;
2400 if (const SfxItemSet
* pItemSet
= GetDialogExampleSet())
2402 if (SfxItemState::SET
!= pItemSet
->GetItemState(SID_DOCINFO
, true, &pItem
))
2403 pInfo
= const_cast<SfxDocumentInfoItem
*>(&rSet
->Get( SID_DOCINFO
));
2407 pInfo
= new SfxDocumentInfoItem( *static_cast<const SfxDocumentInfoItem
*>(pItem
) );
2411 sal_Int32 modifiedNum
= 0;
2414 Sequence
< document::CmisProperty
> aOldProps
= pInfo
->GetCmisProperties( );
2415 Sequence
< document::CmisProperty
> aNewProps
= m_xPropertiesCtrl
->GetCmisProperties();
2417 std::vector
< document::CmisProperty
> changedProps
;
2418 for ( sal_Int32 i
= 0; i
< aNewProps
.getLength( ); ++i
)
2420 if ( aOldProps
[i
].Updatable
&& !aNewProps
[i
].Id
.isEmpty( ) )
2422 if ( aOldProps
[i
].Type
== CMIS_TYPE_DATETIME
)
2424 Sequence
< util::DateTime
> oldValue
;
2425 aOldProps
[i
].Value
>>= oldValue
;
2426 // We only edit hours and minutes
2427 // don't compare NanoSeconds and Seconds
2428 for ( auto& rDateTime
: asNonConstRange(oldValue
) )
2430 rDateTime
.NanoSeconds
= 0;
2431 rDateTime
.Seconds
= 0;
2433 Sequence
< util::DateTime
> newValue
;
2434 aNewProps
[i
].Value
>>= newValue
;
2435 if ( oldValue
!= newValue
)
2438 changedProps
.push_back( aNewProps
[i
] );
2441 else if ( aOldProps
[i
].Value
!= aNewProps
[i
].Value
)
2444 changedProps
.push_back( aNewProps
[i
] );
2448 Sequence
< document::CmisProperty
> aModifiedProps( comphelper::containerToSequence(changedProps
) );
2449 pInfo
->SetCmisProperties( aModifiedProps
);
2450 rSet
->Put( *pInfo
);
2458 void SfxCmisPropertiesPage::Reset( const SfxItemSet
* rItemSet
)
2460 m_xPropertiesCtrl
->ClearAllLines();
2461 const SfxDocumentInfoItem
& rInfoItem
= rItemSet
->Get(SID_DOCINFO
);
2462 uno::Sequence
< document::CmisProperty
> aCmisProps
= rInfoItem
.GetCmisProperties();
2463 for ( auto& rCmisProp
: asNonConstRange(aCmisProps
) )
2465 m_xPropertiesCtrl
->AddLine(rCmisProp
.Id
,
2468 rCmisProp
.Updatable
,
2470 rCmisProp
.MultiValued
,
2471 rCmisProp
.OpenChoice
,
2477 DeactivateRC
SfxCmisPropertiesPage::DeactivatePage( SfxItemSet
* /*pSet*/ )
2479 return DeactivateRC::LeavePage
;
2482 std::unique_ptr
<SfxTabPage
> SfxCmisPropertiesPage::Create(weld::Container
* pPage
, weld::DialogController
* pController
, const SfxItemSet
* rItemSet
)
2484 return std::make_unique
<SfxCmisPropertiesPage
>(pPage
, pController
, *rItemSet
);
2487 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */