bump product version to 5.0.4.1
[LibreOffice.git] / sfx2 / source / dialog / dinfdlg.cxx
blob0e47101b73852fa7a1498b2c364a0cec43a19141
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <tools/urlobj.hxx>
21 #include <vcl/layout.hxx>
22 #include <svl/eitem.hxx>
23 #include <vcl/svapp.hxx>
24 #include <unotools/localedatawrapper.hxx>
25 #include <unotools/cmdoptions.hxx>
26 #include <comphelper/processfactory.hxx>
27 #include <svl/urihelper.hxx>
28 #include <unotools/useroptions.hxx>
29 #include <svtools/imagemgr.hxx>
30 #include <tools/datetime.hxx>
32 #include <memory>
34 #include <comphelper/string.hxx>
35 #include <com/sun/star/security/DocumentSignatureInformation.hpp>
36 #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
37 #include <unotools/syslocale.hxx>
38 #include <rtl/math.hxx>
39 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
40 #include <com/sun/star/beans/PropertyAttribute.hpp>
41 #include <com/sun/star/beans/XPropertyContainer.hpp>
42 #include <com/sun/star/util/DateTime.hpp>
43 #include <com/sun/star/util/Date.hpp>
44 #include <com/sun/star/util/DateTimeWithTimezone.hpp>
45 #include <com/sun/star/util/DateWithTimezone.hpp>
46 #include <com/sun/star/util/Duration.hpp>
47 #include <com/sun/star/document/XDocumentProperties.hpp>
48 #include <com/sun/star/document/CmisProperty.hpp>
50 #include <vcl/timer.hxx>
51 #include <vcl/settings.hxx>
52 #include <sfx2/dinfdlg.hxx>
53 #include <sfx2/securitypage.hxx>
54 #include <sfx2/sfxresid.hxx>
55 #include <sfx2/dinfedt.hxx>
56 #include <sfx2/frame.hxx>
57 #include <sfx2/viewfrm.hxx>
58 #include <sfx2/request.hxx>
59 #include <sfx2/passwd.hxx>
60 #include <sfx2/filedlghelper.hxx>
61 #include "helper.hxx"
62 #include <sfx2/objsh.hxx>
63 #include <sfx2/docfile.hxx>
64 #include <comphelper/storagehelper.hxx>
66 #include "documentfontsdialog.hxx"
67 #include <sfx2/sfx.hrc>
68 #include "dinfdlg.hrc"
69 #include "../appl/app.hrc"
70 #include "sfxlocal.hrc"
71 #include <dialog.hrc>
72 #include <vcl/help.hxx>
73 #include <vcl/builderfactory.hxx>
75 #include <algorithm>
76 #include <boost/scoped_ptr.hpp>
78 using namespace ::com::sun::star;
79 using namespace ::com::sun::star::lang;
80 using namespace ::com::sun::star::ui::dialogs;
81 using namespace ::com::sun::star::uno;
83 const sal_uInt16 FONT_PAGE_ID = 99;
85 struct CustomProperty
87 OUString m_sName;
88 com::sun::star::uno::Any m_aValue;
90 CustomProperty( const OUString& sName,
91 const com::sun::star::uno::Any& rValue ) :
92 m_sName( sName ), m_aValue( rValue ) {}
95 static
96 bool operator==(const util::DateTime &i_rLeft, const util::DateTime &i_rRight)
98 return i_rLeft.Year == i_rRight.Year
99 && i_rLeft.Month == i_rRight.Month
100 && i_rLeft.Day == i_rRight.Day
101 && i_rLeft.Hours == i_rRight.Hours
102 && i_rLeft.Minutes == i_rRight.Minutes
103 && i_rLeft.Seconds == i_rRight.Seconds
104 && i_rLeft.NanoSeconds == i_rRight.NanoSeconds
105 && i_rLeft.IsUTC == i_rRight.IsUTC;
108 // STATIC DATA -----------------------------------------------------------
109 TYPEINIT1_AUTOFACTORY(SfxDocumentInfoItem, SfxStringItem);
111 const sal_uInt16 HI_NAME = 1;
112 const sal_uInt16 HI_TYPE = 2;
113 const sal_uInt16 HI_VALUE = 3;
114 const sal_uInt16 HI_ACTION = 4;
116 static const char DOCUMENT_SIGNATURE_MENU_CMD[] = "Signature";
119 namespace {
121 OUString CreateSizeText( sal_Int64 nSize )
123 OUString aUnitStr(" ");
124 aUnitStr += SfxResId(STR_BYTES).toString();
125 sal_Int64 nSize1 = nSize;
126 sal_Int64 nSize2 = nSize1;
127 sal_Int64 nMega = 1024 * 1024;
128 sal_Int64 nGiga = nMega * 1024;
129 double fSize = nSize;
130 int nDec = 0;
132 if ( nSize1 >= 10000 && nSize1 < nMega )
134 nSize1 /= 1024;
135 aUnitStr = " ";
136 aUnitStr += SfxResId(STR_KB).toString();
137 fSize /= 1024;
138 nDec = 0;
140 else if ( nSize1 >= nMega && nSize1 < nGiga )
142 nSize1 /= nMega;
143 aUnitStr = " ";
144 aUnitStr += SfxResId(STR_MB).toString();
145 fSize /= nMega;
146 nDec = 2;
148 else if ( nSize1 >= nGiga )
150 nSize1 /= nGiga;
151 aUnitStr = " ";
152 aUnitStr += SfxResId(STR_GB).toString();
153 fSize /= nGiga;
154 nDec = 3;
156 const SvtSysLocale aSysLocale;
157 const LocaleDataWrapper& rLocaleWrapper = aSysLocale.GetLocaleData();
158 OUString aSizeStr( rLocaleWrapper.getNum( nSize1, 0 ) );
159 aSizeStr += aUnitStr;
160 if ( nSize1 < nSize2 )
162 aSizeStr = ::rtl::math::doubleToUString( fSize,
163 rtl_math_StringFormat_F, nDec,
164 rLocaleWrapper.getNumDecimalSep()[0] );
165 aSizeStr += aUnitStr;
167 aSizeStr += " (";
168 aSizeStr += rLocaleWrapper.getNum( nSize2, 0 );
169 aSizeStr += " ";
170 aSizeStr += SfxResId(STR_BYTES).toString();
171 aSizeStr += ")";
173 return aSizeStr;
176 OUString ConvertDateTime_Impl( const OUString& rName,
177 const util::DateTime& uDT, const LocaleDataWrapper& rWrapper )
179 Date aD(uDT);
180 tools::Time aT(uDT);
181 const OUString pDelim ( ", " );
182 OUString aStr( rWrapper.getDate( aD ) );
183 aStr += pDelim;
184 aStr += rWrapper.getTime( aT, true, false );
185 OUString aAuthor = comphelper::string::stripStart(rName, ' ');
186 if (!aAuthor.isEmpty())
188 aStr += pDelim;
189 aStr += aAuthor;
191 return aStr;
197 SfxDocumentInfoItem::SfxDocumentInfoItem()
198 : SfxStringItem()
199 , m_AutoloadDelay(0)
200 , m_AutoloadURL()
201 , m_isAutoloadEnabled(false)
202 , m_DefaultTarget()
203 , m_TemplateName()
204 , m_Author()
205 , m_CreationDate()
206 , m_ModifiedBy()
207 , m_ModificationDate()
208 , m_PrintedBy()
209 , m_PrintDate()
210 , m_EditingCycles(0)
211 , m_EditingDuration(0)
212 , m_Description()
213 , m_Keywords()
214 , m_Subject()
215 , m_Title()
216 , m_bHasTemplate( true )
217 , m_bDeleteUserData( false )
218 , m_bUseUserData( true )
222 SfxDocumentInfoItem::SfxDocumentInfoItem( const OUString& rFile,
223 const uno::Reference<document::XDocumentProperties>& i_xDocProps,
224 const uno::Sequence<document::CmisProperty>& i_cmisProps,
225 bool bIs )
226 : SfxStringItem( SID_DOCINFO, rFile )
227 , m_AutoloadDelay( i_xDocProps->getAutoloadSecs() )
228 , m_AutoloadURL( i_xDocProps->getAutoloadURL() )
229 , m_isAutoloadEnabled( (m_AutoloadDelay > 0) || !m_AutoloadURL.isEmpty() )
230 , m_DefaultTarget( i_xDocProps->getDefaultTarget() )
231 , m_TemplateName( i_xDocProps->getTemplateName() )
232 , m_Author( i_xDocProps->getAuthor() )
233 , m_CreationDate( i_xDocProps->getCreationDate() )
234 , m_ModifiedBy( i_xDocProps->getModifiedBy() )
235 , m_ModificationDate( i_xDocProps->getModificationDate() )
236 , m_PrintedBy( i_xDocProps->getPrintedBy() )
237 , m_PrintDate( i_xDocProps->getPrintDate() )
238 , m_EditingCycles( i_xDocProps->getEditingCycles() )
239 , m_EditingDuration( i_xDocProps->getEditingDuration() )
240 , m_Description( i_xDocProps->getDescription() )
241 , m_Keywords( ::comphelper::string::convertCommaSeparated(
242 i_xDocProps->getKeywords()) )
243 , m_Subject( i_xDocProps->getSubject() )
244 , m_Title( i_xDocProps->getTitle() )
245 , m_bHasTemplate( true )
246 , m_bDeleteUserData( false )
247 , m_bUseUserData( bIs )
251 Reference< beans::XPropertyContainer > xContainer = i_xDocProps->getUserDefinedProperties();
252 if ( xContainer.is() )
254 Reference < beans::XPropertySet > xSet( xContainer, UNO_QUERY );
255 const Sequence< beans::Property > lProps = xSet->getPropertySetInfo()->getProperties();
256 const beans::Property* pProps = lProps.getConstArray();
257 sal_Int32 nCount = lProps.getLength();
258 for ( sal_Int32 i = 0; i < nCount; ++i )
260 // "fix" property? => not a custom property => ignore it!
261 if (!(pProps[i].Attributes &
262 ::com::sun::star::beans::PropertyAttribute::REMOVABLE))
264 DBG_ASSERT(false, "non-removable user-defined property?");
265 continue;
268 uno::Any aValue = xSet->getPropertyValue(pProps[i].Name);
269 CustomProperty* pProp = new CustomProperty( pProps[i].Name, aValue );
270 m_aCustomProperties.push_back( pProp );
274 // get CMIS properties
275 m_aCmisProperties = i_cmisProps;
277 catch ( Exception& ) {}
282 SfxDocumentInfoItem::SfxDocumentInfoItem( const SfxDocumentInfoItem& rItem )
283 : SfxStringItem( rItem )
284 , m_AutoloadDelay( rItem.getAutoloadDelay() )
285 , m_AutoloadURL( rItem.getAutoloadURL() )
286 , m_isAutoloadEnabled( rItem.isAutoloadEnabled() )
287 , m_DefaultTarget( rItem.getDefaultTarget() )
288 , m_TemplateName( rItem.getTemplateName() )
289 , m_Author( rItem.getAuthor() )
290 , m_CreationDate( rItem.getCreationDate() )
291 , m_ModifiedBy( rItem.getModifiedBy() )
292 , m_ModificationDate( rItem.getModificationDate() )
293 , m_PrintedBy( rItem.getPrintedBy() )
294 , m_PrintDate( rItem.getPrintDate() )
295 , m_EditingCycles( rItem.getEditingCycles() )
296 , m_EditingDuration( rItem.getEditingDuration() )
297 , m_Description( rItem.getDescription() )
298 , m_Keywords( rItem.getKeywords() )
299 , m_Subject( rItem.getSubject() )
300 , m_Title( rItem.getTitle() )
301 , m_bHasTemplate( rItem.m_bHasTemplate )
302 , m_bDeleteUserData( rItem.m_bDeleteUserData )
303 , m_bUseUserData( rItem.m_bUseUserData )
305 for ( sal_uInt32 i = 0; i < rItem.m_aCustomProperties.size(); i++ )
307 CustomProperty* pProp = new CustomProperty( rItem.m_aCustomProperties[i]->m_sName,
308 rItem.m_aCustomProperties[i]->m_aValue );
309 m_aCustomProperties.push_back( pProp );
312 m_aCmisProperties = rItem.m_aCmisProperties;
316 SfxDocumentInfoItem::~SfxDocumentInfoItem()
318 ClearCustomProperties();
322 SfxPoolItem* SfxDocumentInfoItem::Clone( SfxItemPool * ) const
324 return new SfxDocumentInfoItem( *this );
328 bool SfxDocumentInfoItem::operator==( const SfxPoolItem& rItem) const
330 if (!(rItem.Type() == Type() && SfxStringItem::operator==(rItem)))
331 return false;
332 const SfxDocumentInfoItem& rInfoItem(static_cast<const SfxDocumentInfoItem&>(rItem));
334 return
335 m_AutoloadDelay == rInfoItem.m_AutoloadDelay &&
336 m_AutoloadURL == rInfoItem.m_AutoloadURL &&
337 m_isAutoloadEnabled == rInfoItem.m_isAutoloadEnabled &&
338 m_DefaultTarget == rInfoItem.m_DefaultTarget &&
339 m_Author == rInfoItem.m_Author &&
340 m_CreationDate == rInfoItem.m_CreationDate &&
341 m_ModifiedBy == rInfoItem.m_ModifiedBy &&
342 m_ModificationDate == rInfoItem.m_ModificationDate &&
343 m_PrintedBy == rInfoItem.m_PrintedBy &&
344 m_PrintDate == rInfoItem.m_PrintDate &&
345 m_EditingCycles == rInfoItem.m_EditingCycles &&
346 m_EditingDuration == rInfoItem.m_EditingDuration &&
347 m_Description == rInfoItem.m_Description &&
348 m_Keywords == rInfoItem.m_Keywords &&
349 m_Subject == rInfoItem.m_Subject &&
350 m_Title == rInfoItem.m_Title &&
351 m_aCustomProperties.size() == rInfoItem.m_aCustomProperties.size() &&
352 std::equal(m_aCustomProperties.begin(), m_aCustomProperties.end(),
353 rInfoItem.m_aCustomProperties.begin()) &&
354 m_aCmisProperties.getLength() == rInfoItem.m_aCmisProperties.getLength();
358 void SfxDocumentInfoItem::resetUserData(const OUString & i_rAuthor)
360 setAuthor(i_rAuthor);
361 DateTime now( DateTime::SYSTEM );
362 setCreationDate( now.GetUNODateTime() );
363 setModifiedBy(OUString());
364 setPrintedBy(OUString());
365 setModificationDate(util::DateTime());
366 setPrintDate(util::DateTime());
367 setEditingDuration(0);
368 setEditingCycles(1);
372 void SfxDocumentInfoItem::UpdateDocumentInfo(
373 const uno::Reference<document::XDocumentProperties>& i_xDocProps,
374 bool i_bDoNotUpdateUserDefined) const
376 if (isAutoloadEnabled()) {
377 i_xDocProps->setAutoloadSecs(getAutoloadDelay());
378 i_xDocProps->setAutoloadURL(getAutoloadURL());
379 } else {
380 i_xDocProps->setAutoloadSecs(0);
381 i_xDocProps->setAutoloadURL(OUString());
383 i_xDocProps->setDefaultTarget(getDefaultTarget());
384 i_xDocProps->setAuthor(getAuthor());
385 i_xDocProps->setCreationDate(getCreationDate());
386 i_xDocProps->setModifiedBy(getModifiedBy());
387 i_xDocProps->setModificationDate(getModificationDate());
388 i_xDocProps->setPrintedBy(getPrintedBy());
389 i_xDocProps->setPrintDate(getPrintDate());
390 i_xDocProps->setEditingCycles(getEditingCycles());
391 i_xDocProps->setEditingDuration(getEditingDuration());
392 i_xDocProps->setDescription(getDescription());
393 i_xDocProps->setKeywords(
394 ::comphelper::string::convertCommaSeparated(getKeywords()));
395 i_xDocProps->setSubject(getSubject());
396 i_xDocProps->setTitle(getTitle());
398 // this is necessary in case of replaying a recorded macro:
399 // in this case, the macro may contain the 4 old user-defined DocumentInfo
400 // fields, but not any of the DocumentInfo properties;
401 // as a consequence, most of the UserDefined properties of the
402 // DocumentProperties would be summarily deleted here, which does not
403 // seem like a good idea.
404 if (i_bDoNotUpdateUserDefined)
405 return;
409 Reference< beans::XPropertyContainer > xContainer = i_xDocProps->getUserDefinedProperties();
410 Reference < beans::XPropertySet > xSet( xContainer, UNO_QUERY );
411 Reference< beans::XPropertySetInfo > xSetInfo = xSet->getPropertySetInfo();
412 const Sequence< beans::Property > lProps = xSetInfo->getProperties();
413 const beans::Property* pProps = lProps.getConstArray();
414 sal_Int32 nCount = lProps.getLength();
415 for ( sal_Int32 j = 0; j < nCount; ++j )
417 if ((pProps[j].Attributes &
418 ::com::sun::star::beans::PropertyAttribute::REMOVABLE))
420 xContainer->removeProperty( pProps[j].Name );
424 for ( sal_uInt32 k = 0; k < m_aCustomProperties.size(); ++k )
428 xContainer->addProperty( m_aCustomProperties[k]->m_sName,
429 beans::PropertyAttribute::REMOVABLE, m_aCustomProperties[k]->m_aValue );
431 catch ( Exception& )
433 SAL_WARN( "sfx.dialog", "SfxDocumentInfoItem::updateDocumentInfo(): exception while adding custom properties" );
437 catch ( Exception& )
439 SAL_WARN( "sfx.dialog", "SfxDocumentInfoItem::updateDocumentInfo(): exception while removing custom properties" );
445 void SfxDocumentInfoItem::SetDeleteUserData( bool bSet )
447 m_bDeleteUserData = bSet;
451 void SfxDocumentInfoItem::SetUseUserData( bool bSet )
453 m_bUseUserData = bSet;
456 std::vector< CustomProperty* > SfxDocumentInfoItem::GetCustomProperties() const
458 std::vector< CustomProperty* > aRet;
459 for ( sal_uInt32 i = 0; i < m_aCustomProperties.size(); i++ )
461 CustomProperty* pProp = new CustomProperty( m_aCustomProperties[i]->m_sName,
462 m_aCustomProperties[i]->m_aValue );
463 aRet.push_back( pProp );
466 return aRet;
469 void SfxDocumentInfoItem::ClearCustomProperties()
471 for ( sal_uInt32 i = 0; i < m_aCustomProperties.size(); i++ )
472 delete m_aCustomProperties[i];
473 m_aCustomProperties.clear();
476 void SfxDocumentInfoItem::AddCustomProperty( const OUString& sName, const Any& rValue )
478 CustomProperty* pProp = new CustomProperty( sName, rValue );
479 m_aCustomProperties.push_back( pProp );
483 void SfxDocumentInfoItem::SetCmisProperties( const Sequence< document::CmisProperty >& cmisProps)
485 m_aCmisProperties = cmisProps;
488 bool SfxDocumentInfoItem::QueryValue( Any& rVal, sal_uInt8 nMemberId ) const
490 OUString aValue;
491 sal_Int32 nValue = 0;
492 bool bValue = false;
493 bool bIsInt = false;
494 bool bIsString = false;
495 nMemberId &= ~CONVERT_TWIPS;
496 switch ( nMemberId )
498 case MID_DOCINFO_USEUSERDATA:
499 bValue = IsUseUserData();
500 break;
501 case MID_DOCINFO_DELETEUSERDATA:
502 bValue = IsDeleteUserData();
503 break;
504 case MID_DOCINFO_AUTOLOADENABLED:
505 bValue = isAutoloadEnabled();
506 break;
507 case MID_DOCINFO_AUTOLOADSECS:
508 bIsInt = true;
509 nValue = getAutoloadDelay();
510 break;
511 case MID_DOCINFO_AUTOLOADURL:
512 bIsString = true;
513 aValue = getAutoloadURL();
514 break;
515 case MID_DOCINFO_DEFAULTTARGET:
516 bIsString = true;
517 aValue = getDefaultTarget();
518 break;
519 case MID_DOCINFO_DESCRIPTION:
520 bIsString = true;
521 aValue = getDescription();
522 break;
523 case MID_DOCINFO_KEYWORDS:
524 bIsString = true;
525 aValue = getKeywords();
526 break;
527 case MID_DOCINFO_SUBJECT:
528 bIsString = true;
529 aValue = getSubject();
530 break;
531 case MID_DOCINFO_TITLE:
532 bIsString = true;
533 aValue = getTitle();
534 break;
535 default:
536 OSL_FAIL("Wrong MemberId!");
537 return false;
540 if ( bIsString )
541 rVal <<= OUString( aValue );
542 else if ( bIsInt )
543 rVal <<= nValue;
544 else
545 rVal <<= bValue;
546 return true;
549 bool SfxDocumentInfoItem::PutValue( const Any& rVal, sal_uInt8 nMemberId )
551 OUString aValue;
552 sal_Int32 nValue=0;
553 bool bValue = false;
554 bool bRet = false;
555 nMemberId &= ~CONVERT_TWIPS;
556 switch ( nMemberId )
558 case MID_DOCINFO_USEUSERDATA:
559 bRet = (rVal >>= bValue);
560 if ( bRet )
561 SetUseUserData( bValue );
562 break;
563 case MID_DOCINFO_DELETEUSERDATA:
564 // QUESTION: deleting user data was done here; seems to be superfluous!
565 bRet = (rVal >>= bValue);
566 if ( bRet )
567 SetDeleteUserData( bValue );
568 break;
569 case MID_DOCINFO_AUTOLOADENABLED:
570 bRet = (rVal >>= bValue);
571 if ( bRet )
572 setAutoloadEnabled(bValue);
573 break;
574 case MID_DOCINFO_AUTOLOADSECS:
575 bRet = (rVal >>= nValue);
576 if ( bRet )
577 setAutoloadDelay(nValue);
578 break;
579 case MID_DOCINFO_AUTOLOADURL:
580 bRet = (rVal >>= aValue);
581 if ( bRet )
582 setAutoloadURL(aValue);
583 break;
584 case MID_DOCINFO_DEFAULTTARGET:
585 bRet = (rVal >>= aValue);
586 if ( bRet )
587 setDefaultTarget(aValue);
588 break;
589 case MID_DOCINFO_DESCRIPTION:
590 bRet = (rVal >>= aValue);
591 if ( bRet )
592 setDescription(aValue);
593 break;
594 case MID_DOCINFO_KEYWORDS:
595 bRet = (rVal >>= aValue);
596 if ( bRet )
597 setKeywords(aValue);
598 break;
599 case MID_DOCINFO_SUBJECT:
600 bRet = (rVal >>= aValue);
601 if ( bRet )
602 setSubject(aValue);
603 break;
604 case MID_DOCINFO_TITLE:
605 bRet = (rVal >>= aValue);
606 if ( bRet )
607 setTitle(aValue);
608 break;
609 default:
610 OSL_FAIL("Wrong MemberId!");
611 return false;
614 return bRet;
617 SfxDocumentDescPage::SfxDocumentDescPage( vcl::Window * pParent, const SfxItemSet& rItemSet )
618 : SfxTabPage(pParent, "DescriptionInfoPage", "sfx/ui/descriptioninfopage.ui", &rItemSet)
619 , m_pInfoItem ( NULL )
622 get(m_pTitleEd, "title");
623 get(m_pThemaEd, "subject");
624 get(m_pKeywordsEd, "keywords");
625 get(m_pCommentEd, "comments");
626 m_pCommentEd->set_width_request(m_pKeywordsEd->get_preferred_size().Width());
627 m_pCommentEd->set_height_request(m_pCommentEd->GetTextHeight() * 16);
630 SfxDocumentDescPage::~SfxDocumentDescPage()
632 disposeOnce();
635 void SfxDocumentDescPage::dispose()
637 m_pTitleEd.clear();
638 m_pThemaEd.clear();
639 m_pKeywordsEd.clear();
640 m_pCommentEd.clear();
641 SfxTabPage::dispose();
644 VclPtr<SfxTabPage> SfxDocumentDescPage::Create(vcl::Window *pParent, const SfxItemSet *rItemSet)
646 return VclPtr<SfxDocumentDescPage>::Create(pParent, *rItemSet);
649 bool SfxDocumentDescPage::FillItemSet(SfxItemSet *rSet)
651 // Test whether a change is present
652 const bool bTitleMod = m_pTitleEd->IsModified();
653 const bool bThemeMod = m_pThemaEd->IsModified();
654 const bool bKeywordsMod = m_pKeywordsEd->IsModified();
655 const bool bCommentMod = m_pCommentEd->IsModified();
656 if ( !( bTitleMod || bThemeMod || bKeywordsMod || bCommentMod ) )
658 return false;
661 // Generating the output data
662 const SfxPoolItem* pItem = NULL;
663 SfxDocumentInfoItem* pInfo = NULL;
664 SfxTabDialog* pDlg = GetTabDialog();
665 const SfxItemSet* pExSet = NULL;
667 if ( pDlg )
668 pExSet = pDlg->GetExampleSet();
670 if ( pExSet && SfxItemState::SET != pExSet->GetItemState( SID_DOCINFO, true, &pItem ) )
671 pInfo = m_pInfoItem;
672 else if ( pItem )
673 pInfo = new SfxDocumentInfoItem( *static_cast<const SfxDocumentInfoItem *>(pItem) );
675 if ( !pInfo )
677 SAL_WARN( "sfx.dialog", "SfxDocumentDescPage::FillItemSet(): no item found" );
678 return false;
681 if ( bTitleMod )
683 pInfo->setTitle( m_pTitleEd->GetText() );
685 if ( bThemeMod )
687 pInfo->setSubject( m_pThemaEd->GetText() );
689 if ( bKeywordsMod )
691 pInfo->setKeywords( m_pKeywordsEd->GetText() );
693 if ( bCommentMod )
695 pInfo->setDescription( m_pCommentEd->GetText() );
697 rSet->Put( SfxDocumentInfoItem( *pInfo ) );
698 if ( pInfo != m_pInfoItem )
700 delete pInfo;
703 return true;
707 void SfxDocumentDescPage::Reset(const SfxItemSet *rSet)
709 m_pInfoItem = const_cast<SfxDocumentInfoItem*>(&static_cast<const SfxDocumentInfoItem &>(rSet->Get(SID_DOCINFO)));
711 m_pTitleEd->SetText( m_pInfoItem->getTitle() );
712 m_pThemaEd->SetText( m_pInfoItem->getSubject() );
713 m_pKeywordsEd->SetText( m_pInfoItem->getKeywords() );
714 m_pCommentEd->SetText( m_pInfoItem->getDescription() );
716 SFX_ITEMSET_ARG( rSet, pROItem, SfxBoolItem, SID_DOC_READONLY, false );
717 if ( pROItem && pROItem->GetValue() )
719 m_pTitleEd->SetReadOnly( true );
720 m_pThemaEd->SetReadOnly( true );
721 m_pKeywordsEd->SetReadOnly( true );
722 m_pCommentEd->SetReadOnly( true );
727 namespace
729 OUString GetDateTimeString( sal_Int32 _nDate, sal_Int32 _nTime )
731 const LocaleDataWrapper& rWrapper( Application::GetSettings().GetLocaleDataWrapper() );
733 Date aDate( _nDate );
734 tools::Time aTime( _nTime );
735 OUString aStr( rWrapper.getDate( aDate ) );
736 aStr += ", ";
737 aStr += rWrapper.getTime( aTime );
738 return aStr;
741 // copy from xmlsecurity/source/dialog/resourcemanager.cxx
742 OUString GetContentPart( const OUString& _rRawString, const OUString& _rPartId )
744 OUString s;
746 sal_Int32 nContStart = _rRawString.indexOf( _rPartId );
747 if ( nContStart != -1 )
749 nContStart = nContStart + _rPartId.getLength();
750 ++nContStart; // now its start of content, directly after Id
752 sal_Int32 nContEnd = _rRawString.indexOf( ',', nContStart );
754 s = _rRawString.copy( nContStart, nContEnd - nContStart );
757 return s;
761 SfxDocumentPage::SfxDocumentPage(vcl::Window* pParent, const SfxItemSet& rItemSet)
762 : SfxTabPage(pParent, "DocumentInfoPage", "sfx/ui/documentinfopage.ui", &rItemSet)
763 , bEnableUseUserData( false )
764 , bHandleDelete( false )
766 get(m_pBmp, "icon");
767 get(m_pNameED, "nameed");
768 get(m_pChangePassBtn, "changepass");
770 get(m_pShowTypeFT, "showtype");
771 get(m_pFileValEd, "showlocation");
772 get(m_pShowSizeFT, "showsize");
773 m_aUnknownSize = m_pShowSizeFT->GetText();
774 m_pShowSizeFT->SetText(OUString());
776 get(m_pCreateValFt, "showcreate");
777 get(m_pChangeValFt, "showmodify");
778 get(m_pSignedValFt, "showsigned");
779 m_aMultiSignedStr = m_pSignedValFt->GetText();
780 m_pSignedValFt->SetText(OUString());
781 get(m_pSignatureBtn, "signature");
782 get(m_pPrintValFt, "showprint");
783 get(m_pTimeLogValFt, "showedittime");
784 get(m_pDocNoValFt, "showrevision");
786 get(m_pUseUserDataCB, "userdatacb");
787 get(m_pDeleteBtn, "reset");
789 get(m_pTemplFt, "templateft");
790 get(m_pTemplValFt, "showtemplate");
792 ImplUpdateSignatures();
793 ImplCheckPasswordState();
794 m_pChangePassBtn->SetClickHdl( LINK( this, SfxDocumentPage, ChangePassHdl ) );
795 m_pSignatureBtn->SetClickHdl( LINK( this, SfxDocumentPage, SignatureHdl ) );
796 m_pDeleteBtn->SetClickHdl( LINK( this, SfxDocumentPage, DeleteHdl ) );
798 // [i96288] Check if the document signature command is enabled
799 // on the main list enable/disable the pushbutton accordingly
800 SvtCommandOptions aCmdOptions;
801 if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED,
802 OUString( DOCUMENT_SIGNATURE_MENU_CMD ) ) )
803 m_pSignatureBtn->Disable();
806 SfxDocumentPage::~SfxDocumentPage()
808 disposeOnce();
811 void SfxDocumentPage::dispose()
813 m_pBmp.clear();
814 m_pNameED.clear();
815 m_pChangePassBtn.clear();
816 m_pShowTypeFT.clear();
817 m_pFileValEd.clear();
818 m_pShowSizeFT.clear();
819 m_pCreateValFt.clear();
820 m_pChangeValFt.clear();
821 m_pSignedValFt.clear();
822 m_pSignatureBtn.clear();
823 m_pPrintValFt.clear();
824 m_pTimeLogValFt.clear();
825 m_pDocNoValFt.clear();
826 m_pUseUserDataCB.clear();
827 m_pDeleteBtn.clear();
828 m_pTemplFt.clear();
829 m_pTemplValFt.clear();
830 SfxTabPage::dispose();
834 IMPL_LINK_NOARG(SfxDocumentPage, DeleteHdl)
836 OUString aName;
837 if ( bEnableUseUserData && m_pUseUserDataCB->IsChecked() )
838 aName = SvtUserOptions().GetFullName();
839 const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
840 DateTime now( DateTime::SYSTEM );
841 util::DateTime uDT( now.GetUNODateTime() );
842 m_pCreateValFt->SetText( ConvertDateTime_Impl( aName, uDT, rLocaleWrapper ) );
843 OUString aEmpty;
844 m_pChangeValFt->SetText( aEmpty );
845 m_pPrintValFt->SetText( aEmpty );
846 const tools::Time aTime( 0 );
847 m_pTimeLogValFt->SetText( rLocaleWrapper.getDuration( aTime ) );
848 m_pDocNoValFt->SetText(OUString('1'));
849 bHandleDelete = true;
850 return 0;
853 IMPL_LINK_NOARG(SfxDocumentPage, SignatureHdl)
855 SfxObjectShell* pDoc = SfxObjectShell::Current();
856 if( pDoc )
858 pDoc->SignDocumentContent();
860 ImplUpdateSignatures();
863 return 0;
866 IMPL_STATIC_LINK_NOARG(SfxDocumentPage, ChangePassHdl)
868 SfxObjectShell* pShell = SfxObjectShell::Current();
871 if (!pShell)
872 break;
873 SfxItemSet* pMedSet = pShell->GetMedium()->GetItemSet();
874 if (!pMedSet)
875 break;
876 const SfxFilter* pFilter = pShell->GetMedium()->GetFilter();
877 if (!pFilter)
878 break;
880 OUString aDocName;
881 sfx2::RequestPassword(pFilter, aDocName, pMedSet);
882 pShell->SetModified(true);
884 while (false);
885 return 0;
888 void SfxDocumentPage::ImplUpdateSignatures()
890 SfxObjectShell* pDoc = SfxObjectShell::Current();
891 if ( pDoc )
893 SfxMedium* pMedium = pDoc->GetMedium();
894 if ( pMedium && !pMedium->GetName().isEmpty() && pMedium->GetStorage().is() )
896 Reference< security::XDocumentDigitalSignatures > xD(
897 security::DocumentDigitalSignatures::createDefault(comphelper::getProcessComponentContext()) );
899 OUString s;
900 Sequence< security::DocumentSignatureInformation > aInfos;
901 aInfos = xD->verifyDocumentContentSignatures( pMedium->GetZipStorageToSign_Impl(),
902 uno::Reference< io::XInputStream >() );
903 if ( aInfos.getLength() > 1 )
904 s = m_aMultiSignedStr;
905 else if ( aInfos.getLength() == 1 )
907 OUString aCN_Id("CN");
908 const security::DocumentSignatureInformation& rInfo = aInfos[ 0 ];
909 s = GetDateTimeString( rInfo.SignatureDate, rInfo.SignatureTime );
910 s += ", ";
911 s += GetContentPart( rInfo.Signer->getSubjectName(), aCN_Id );
913 m_pSignedValFt->SetText( s );
918 void SfxDocumentPage::ImplCheckPasswordState()
920 SfxObjectShell* pShell = SfxObjectShell::Current();
923 if (!pShell)
924 break;
925 SfxItemSet* pMedSet = pShell->GetMedium()->GetItemSet();
926 if (!pMedSet)
927 break;
928 SFX_ITEMSET_ARG( pMedSet, pEncryptionDataItem, SfxUnoAnyItem, SID_ENCRYPTIONDATA, false);
929 uno::Sequence< beans::NamedValue > aEncryptionData;
930 if (pEncryptionDataItem)
931 pEncryptionDataItem->GetValue() >>= aEncryptionData;
932 else
933 break;
935 if (!aEncryptionData.getLength())
936 break;
937 m_pChangePassBtn->Enable();
938 return;
940 while (false);
941 m_pChangePassBtn->Disable();
944 VclPtr<SfxTabPage> SfxDocumentPage::Create( vcl::Window* pParent, const SfxItemSet* rItemSet )
946 return VclPtr<SfxDocumentPage>::Create( pParent, *rItemSet );
949 void SfxDocumentPage::EnableUseUserData()
951 bEnableUseUserData = true;
952 m_pUseUserDataCB->Show();
953 m_pDeleteBtn->Show();
956 bool SfxDocumentPage::FillItemSet( SfxItemSet* rSet )
958 bool bRet = false;
960 if ( !bHandleDelete && bEnableUseUserData &&
961 m_pUseUserDataCB->IsValueChangedFromSaved() &&
962 GetTabDialog() && GetTabDialog()->GetExampleSet() )
964 SfxItemSet* pExpSet = GetTabDialog()->GetExampleSet();
965 const SfxPoolItem* pItem;
967 if ( pExpSet && SfxItemState::SET == pExpSet->GetItemState( SID_DOCINFO, true, &pItem ) )
969 const SfxDocumentInfoItem* m_pInfoItem = static_cast<const SfxDocumentInfoItem*>(pItem);
970 bool bUseData = ( TRISTATE_TRUE == m_pUseUserDataCB->GetState() );
971 const_cast<SfxDocumentInfoItem*>(m_pInfoItem)->SetUseUserData( bUseData );
972 rSet->Put( SfxDocumentInfoItem( *m_pInfoItem ) );
973 bRet = true;
977 if ( bHandleDelete )
979 SfxItemSet* pExpSet = GetTabDialog()->GetExampleSet();
980 const SfxPoolItem* pItem;
981 if ( pExpSet && SfxItemState::SET == pExpSet->GetItemState( SID_DOCINFO, true, &pItem ) )
983 const SfxDocumentInfoItem* pInfoItem = static_cast<const SfxDocumentInfoItem*>(pItem);
984 bool bUseAuthor = bEnableUseUserData && m_pUseUserDataCB->IsChecked();
985 SfxDocumentInfoItem newItem( *pInfoItem );
986 newItem.resetUserData( bUseAuthor
987 ? SvtUserOptions().GetFullName()
988 : OUString() );
989 const_cast<SfxDocumentInfoItem*>(pInfoItem)->SetUseUserData( TRISTATE_TRUE == m_pUseUserDataCB->GetState() );
990 newItem.SetUseUserData( TRISTATE_TRUE == m_pUseUserDataCB->GetState() );
992 newItem.SetDeleteUserData( true );
993 rSet->Put( newItem );
994 bRet = true;
998 return bRet;
1001 void SfxDocumentPage::Reset( const SfxItemSet* rSet )
1003 // Determine the document information
1004 const SfxDocumentInfoItem& rInfoItem =
1005 static_cast<const SfxDocumentInfoItem &>(rSet->Get(SID_DOCINFO));
1007 // template data
1008 if ( rInfoItem.HasTemplate() )
1009 m_pTemplValFt->SetText( rInfoItem.getTemplateName() );
1010 else
1012 m_pTemplFt->Hide();
1013 m_pTemplValFt->Hide();
1016 // determine file name
1017 OUString aFile( rInfoItem.GetValue() );
1018 OUString aFactory( aFile );
1019 if ( aFile.getLength() > 2 && aFile[0] == '[' )
1021 sal_Int32 nPos = aFile.indexOf( ']' );
1022 aFactory = aFile.copy( 1, nPos-1 );
1023 aFile = aFile.copy( nPos+1 );
1026 // determine name
1027 INetURLObject aURL(aFile);
1028 OUString aName = aURL.GetName( INetURLObject::DECODE_WITH_CHARSET );
1029 if ( aName.isEmpty() || aURL.GetProtocol() == INetProtocol::PrivSoffice )
1030 aName = SfxResId( STR_NONAME ).toString();
1031 m_pNameED->SetText( aName );
1033 // determine context symbol
1034 aURL.SetSmartProtocol( INetProtocol::File );
1035 aURL.SetSmartURL( aFactory);
1036 const OUString& rMainURL = aURL.GetMainURL( INetURLObject::NO_DECODE );
1037 Image aImage = SvFileInformationManager::GetImage( aURL, true );
1039 if ( GetDPIScaleFactor() > 1)
1041 BitmapEx b = aImage.GetBitmapEx();
1042 b.Scale(GetDPIScaleFactor(), GetDPIScaleFactor());
1043 aImage = Image(b);
1046 m_pBmp->SetImage( aImage );
1048 // determine size and type
1049 OUString aSizeText( m_aUnknownSize );
1050 if ( aURL.GetProtocol() == INetProtocol::File )
1051 aSizeText = CreateSizeText( SfxContentHelper::GetSize( aURL.GetMainURL( INetURLObject::NO_DECODE ) ) );
1052 m_pShowSizeFT->SetText( aSizeText );
1054 OUString aDescription = SvFileInformationManager::GetDescription( INetURLObject(rMainURL) );
1055 if ( aDescription.isEmpty() )
1056 aDescription = SfxResId( STR_SFX_NEWOFFICEDOC ).toString();
1057 m_pShowTypeFT->SetText( aDescription );
1059 // determine location
1060 aURL.SetSmartURL( aFile);
1061 if ( aURL.GetProtocol() == INetProtocol::File )
1063 INetURLObject aPath( aURL );
1064 aPath.setFinalSlash();
1065 aPath.removeSegment();
1066 // we know it's a folder -> don't need the final slash, but it's better for WB_PATHELLIPSIS
1067 aPath.removeFinalSlash();
1068 OUString aText( aPath.PathToFileName() ); //! (pb) MaxLen?
1069 m_pFileValEd->SetText( aText );
1071 else if ( aURL.GetProtocol() != INetProtocol::PrivSoffice )
1072 m_pFileValEd->SetText( aURL.GetPartBeforeLastName() );
1074 // handle access data
1075 bool m_bUseUserData = rInfoItem.IsUseUserData();
1076 const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
1077 m_pCreateValFt->SetText( ConvertDateTime_Impl( rInfoItem.getAuthor(),
1078 rInfoItem.getCreationDate(), rLocaleWrapper ) );
1079 util::DateTime aTime( rInfoItem.getModificationDate() );
1080 if ( aTime.Month > 0 )
1081 m_pChangeValFt->SetText( ConvertDateTime_Impl(
1082 rInfoItem.getModifiedBy(), aTime, rLocaleWrapper ) );
1083 aTime = rInfoItem.getPrintDate();
1084 if ( aTime.Month > 0 )
1085 m_pPrintValFt->SetText( ConvertDateTime_Impl( rInfoItem.getPrintedBy(),
1086 aTime, rLocaleWrapper ) );
1087 const long nTime = rInfoItem.getEditingDuration();
1088 if ( m_bUseUserData )
1090 const tools::Time aT( nTime/3600, (nTime%3600)/60, nTime%60 );
1091 m_pTimeLogValFt->SetText( rLocaleWrapper.getDuration( aT ) );
1092 m_pDocNoValFt->SetText( OUString::number(
1093 rInfoItem.getEditingCycles() ) );
1096 // Check for cmis properties where otherwise unavailable
1097 if ( rInfoItem.isCmisDocument( ) )
1099 uno::Sequence< document::CmisProperty > aCmisProps = rInfoItem.GetCmisProperties();
1100 for ( sal_Int32 i = 0; i < aCmisProps.getLength(); i++ )
1102 if ( aCmisProps[i].Id == "cmis:contentStreamLength" &&
1103 aSizeText == m_aUnknownSize )
1105 Sequence< sal_Int64 > seqValue;
1106 aCmisProps[i].Value >>= seqValue;
1107 SvNumberFormatter m_aNumberFormatter( ::comphelper::getProcessComponentContext(),
1108 Application::GetSettings().GetLanguageTag().getLanguageType() );
1109 sal_uInt32 nIndex = m_aNumberFormatter.GetFormatIndex( NF_NUMBER_SYSTEM );
1110 if ( seqValue.getLength( ) > 0 )
1112 OUString sValue;
1113 m_aNumberFormatter.GetInputLineString( seqValue[0], nIndex, sValue );
1114 m_pShowSizeFT->SetText( CreateSizeText( sValue.toInt64( ) ) );
1118 util::DateTime uDT;
1119 OUString emptyDate = ConvertDateTime_Impl( "", uDT, rLocaleWrapper );
1120 if ( aCmisProps[i].Id == "cmis:creationDate" &&
1121 (m_pCreateValFt->GetText() == emptyDate ||
1122 m_pCreateValFt->GetText().isEmpty()))
1124 Sequence< util::DateTime > seqValue;
1125 aCmisProps[i].Value >>= seqValue;
1126 if ( seqValue.getLength( ) > 0 )
1128 m_pCreateValFt->SetText( ConvertDateTime_Impl( "", seqValue[0], rLocaleWrapper ) );
1131 if ( aCmisProps[i].Id == "cmis:lastModificationDate" &&
1132 (m_pChangeValFt->GetText() == emptyDate ||
1133 m_pChangeValFt->GetText().isEmpty()))
1135 Sequence< util::DateTime > seqValue;
1136 aCmisProps[i].Value >>= seqValue;
1137 if ( seqValue.getLength( ) > 0 )
1139 m_pChangeValFt->SetText( ConvertDateTime_Impl( "", seqValue[0], rLocaleWrapper ) );
1145 m_pUseUserDataCB->SetState( static_cast<TriState>(m_bUseUserData) );
1146 m_pUseUserDataCB->SaveValue();
1147 m_pUseUserDataCB->Enable( bEnableUseUserData );
1148 bHandleDelete = false;
1149 m_pDeleteBtn->Enable( bEnableUseUserData );
1153 SfxDocumentInfoDialog::SfxDocumentInfoDialog( vcl::Window* pParent,
1154 const SfxItemSet& rItemSet )
1155 : SfxTabDialog(0, pParent, "DocumentPropertiesDialog",
1156 "sfx/ui/documentpropertiesdialog.ui", &rItemSet)
1157 , m_nDocInfoId(0)
1159 const SfxDocumentInfoItem& rInfoItem =
1160 static_cast<const SfxDocumentInfoItem &>(rItemSet.Get( SID_DOCINFO ));
1162 #ifdef DBG_UTIL
1163 SFX_ITEMSET_ARG( &rItemSet, pURLItem, SfxStringItem, SID_BASEURL, false );
1164 DBG_ASSERT( pURLItem, "No BaseURL provided for InternetTabPage!" );
1165 #endif
1167 // Determine the Titels
1168 const SfxPoolItem* pItem = 0;
1169 OUString aTitle( GetText() );
1170 if ( SfxItemState::SET !=
1171 rItemSet.GetItemState( SID_EXPLORER_PROPS_START, false, &pItem ) )
1173 // File name
1174 OUString aFile( rInfoItem.GetValue() );
1176 INetURLObject aURL;
1177 aURL.SetSmartProtocol( INetProtocol::File );
1178 aURL.SetSmartURL( aFile);
1179 if ( INetProtocol::PrivSoffice != aURL.GetProtocol() )
1181 OUString aLastName( aURL.GetLastName() );
1182 if ( !aLastName.isEmpty() )
1183 aTitle += aLastName;
1184 else
1185 aTitle += aFile;
1187 else
1188 aTitle += SfxResId( STR_NONAME ).toString();
1190 else
1192 DBG_ASSERT( pItem->IsA( TYPE( SfxStringItem ) ),
1193 "SfxDocumentInfoDialog:<SfxStringItem> expected" );
1194 aTitle += static_cast<const SfxStringItem*>(pItem)->GetValue();
1196 SetText( aTitle );
1198 // Property Pages
1199 m_nDocInfoId = AddTabPage("general", SfxDocumentPage::Create, 0);
1200 AddTabPage("description", SfxDocumentDescPage::Create, 0);
1201 AddTabPage("customprops", SfxCustomPropertiesPage::Create, 0);
1202 AddTabPage("cmisprops", SfxCmisPropertiesPage::Create, 0);
1203 AddTabPage("security", SfxSecurityPage::Create, 0);
1208 void SfxDocumentInfoDialog::PageCreated( sal_uInt16 nId, SfxTabPage &rPage )
1210 if ( m_nDocInfoId == nId )
1211 static_cast<SfxDocumentPage&>(rPage).EnableUseUserData();
1214 void SfxDocumentInfoDialog::AddFontTabPage()
1216 AddTabPage( FONT_PAGE_ID, SfxResId( STR_FONT_TABPAGE ).toString(), SfxDocumentFontsPage::Create, 0);
1219 // class CustomPropertiesYesNoButton -------------------------------------
1221 CustomPropertiesYesNoButton::CustomPropertiesYesNoButton( vcl::Window* pParent, const ResId& rResId ) :
1222 Control( pParent, rResId ),
1223 m_aYesButton( VclPtr<RadioButton>::Create(this, ResId( RB_PROPERTY_YES, *rResId.GetResMgr() )) ),
1224 m_aNoButton ( VclPtr<RadioButton>::Create(this, ResId( RB_PROPERTY_NO, *rResId.GetResMgr() )) )
1226 FreeResource();
1227 Wallpaper aWall( Color( COL_TRANSPARENT ) );
1228 SetBackground( aWall );
1229 SetBorderStyle( WindowBorderStyle::MONO );
1230 CheckNo();
1231 m_aYesButton->SetBackground( aWall );
1232 m_aNoButton->SetBackground( aWall );
1236 CustomPropertiesYesNoButton::~CustomPropertiesYesNoButton()
1238 disposeOnce();
1241 void CustomPropertiesYesNoButton::dispose()
1243 m_aYesButton.disposeAndClear();
1244 m_aNoButton.disposeAndClear();
1245 Control::dispose();
1248 class DurationDialog_Impl : public ModalDialog
1250 VclPtr<CheckBox> m_pNegativeCB;
1251 VclPtr<NumericField> m_pYearNF;
1252 VclPtr<NumericField> m_pMonthNF;
1253 VclPtr<NumericField> m_pDayNF;
1254 VclPtr<NumericField> m_pHourNF;
1255 VclPtr<NumericField> m_pMinuteNF;
1256 VclPtr<NumericField> m_pSecondNF;
1257 VclPtr<NumericField> m_pMSecondNF;
1259 public:
1261 DurationDialog_Impl( vcl::Window* pParent, const util::Duration& rDuration );
1262 virtual ~DurationDialog_Impl();
1263 virtual void dispose() SAL_OVERRIDE;
1264 util::Duration GetDuration() const;
1267 DurationDialog_Impl::DurationDialog_Impl(vcl::Window* pParent,
1268 const util::Duration& rDuration)
1269 : ModalDialog(pParent, "EditDurationDialog",
1270 "sfx/ui/editdurationdialog.ui")
1272 get(m_pNegativeCB, "negative");
1273 get(m_pYearNF, "years");
1274 get(m_pMonthNF, "months");
1275 get(m_pDayNF, "days");
1276 get(m_pHourNF, "hours");
1277 get(m_pMinuteNF, "minutes");
1278 get(m_pSecondNF, "seconds");
1279 get(m_pMSecondNF, "milliseconds");
1281 m_pNegativeCB->Check(rDuration.Negative);
1282 m_pYearNF->SetValue(rDuration.Years);
1283 m_pMonthNF->SetValue(rDuration.Months);
1284 m_pDayNF->SetValue(rDuration.Days);
1285 m_pHourNF->SetValue(rDuration.Hours);
1286 m_pMinuteNF->SetValue(rDuration.Minutes);
1287 m_pSecondNF->SetValue(rDuration.Seconds);
1288 m_pMSecondNF->SetValue(rDuration.NanoSeconds);
1291 DurationDialog_Impl::~DurationDialog_Impl()
1293 disposeOnce();
1296 void DurationDialog_Impl::dispose()
1298 m_pNegativeCB.clear();
1299 m_pYearNF.clear();
1300 m_pMonthNF.clear();
1301 m_pDayNF.clear();
1302 m_pHourNF.clear();
1303 m_pMinuteNF.clear();
1304 m_pSecondNF.clear();
1305 m_pMSecondNF.clear();
1306 ModalDialog::dispose();
1309 util::Duration DurationDialog_Impl::GetDuration() const
1311 util::Duration aRet;
1312 aRet.Negative = m_pNegativeCB->IsChecked();
1313 aRet.Years = m_pYearNF->GetValue();
1314 aRet.Months = m_pMonthNF->GetValue( );
1315 aRet.Days = m_pDayNF->GetValue( );
1316 aRet.Hours = m_pHourNF->GetValue( );
1317 aRet.Minutes = m_pMinuteNF->GetValue();
1318 aRet.Seconds = m_pSecondNF->GetValue();
1319 aRet.NanoSeconds = m_pMSecondNF->GetValue();
1320 return aRet;
1323 CustomPropertiesDurationField::CustomPropertiesDurationField(vcl::Window* pParent, WinBits nStyle,
1324 CustomPropertyLine* pLine)
1325 : Edit(pParent, nStyle)
1326 , m_pLine(pLine)
1329 SetDuration( util::Duration(false, 0, 0, 0, 0, 0, 0, 0) );
1332 void CustomPropertiesDurationField::RequestHelp( const HelpEvent& rHEvt )
1334 if ( rHEvt.GetMode() & HelpEventMode::QUICK )
1336 Size aSize( GetSizePixel() );
1337 Rectangle aItemRect( rHEvt.GetMousePosPixel(), aSize );
1338 if (Help::IsBalloonHelpEnabled())
1339 Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), GetText() );
1340 else
1341 Help::ShowQuickHelp( this, aItemRect, GetText(),
1342 QuickHelpFlags::Left|QuickHelpFlags::VCenter );
1346 void CustomPropertiesDurationField::SetDuration( const util::Duration& rDuration )
1348 m_aDuration = rDuration;
1349 OUString sText(rDuration.Negative ? OUString('-') : OUString('+'));
1350 sText += m_pLine->m_sDurationFormat;
1351 sText = sText.replaceFirst( "%1", OUString::number( rDuration.Years ) );
1352 sText = sText.replaceFirst( "%2", OUString::number( rDuration.Months ) );
1353 sText = sText.replaceFirst( "%3", OUString::number( rDuration.Days ) );
1354 sText = sText.replaceFirst( "%4", OUString::number( rDuration.Hours ) );
1355 sText = sText.replaceFirst( "%5", OUString::number( rDuration.Minutes) );
1356 sText = sText.replaceFirst( "%6", OUString::number( rDuration.Seconds) );
1357 SetText( sText );
1360 CustomPropertiesEditButton::CustomPropertiesEditButton(vcl::Window* pParent, WinBits nStyle,
1361 CustomPropertyLine* pLine)
1362 : PushButton(pParent, nStyle)
1363 , m_pLine(pLine)
1365 SetClickHdl( LINK( this, CustomPropertiesEditButton, ClickHdl ));
1368 IMPL_LINK_NOARG(CustomPropertiesEditButton, ClickHdl)
1370 VclPtrInstance< DurationDialog_Impl > pDurationDlg( this, m_pLine->m_aDurationField->GetDuration() );
1371 if ( RET_OK == pDurationDlg->Execute() )
1372 m_pLine->m_aDurationField->SetDuration( pDurationDlg->GetDuration() );
1373 return 1;
1376 void CustomPropertiesYesNoButton::Resize()
1378 const long nWidth = GetSizePixel().Width();
1379 const long n3Width = LogicToPixel( Size( 3, 3 ), MAP_APPFONT ).Width();
1380 const long nNewWidth = ( nWidth / 2 ) - n3Width - 2;
1381 Size aSize = m_aYesButton->GetSizePixel();
1382 const long nDelta = aSize.Width() - nNewWidth;
1383 aSize.Width() = nNewWidth;
1384 m_aYesButton->SetSizePixel( aSize );
1385 Point aPos = m_aNoButton->GetPosPixel();
1386 aPos.X() -= nDelta;
1387 m_aNoButton->SetPosSizePixel( aPos, aSize );
1390 // struct CustomPropertyLine ---------------------------------------------
1391 CustomPropertyLine::CustomPropertyLine( vcl::Window* pParent ) :
1392 m_aNameBox ( VclPtr<ComboBox>::Create(pParent, SfxResId( SFX_CB_PROPERTY_NAME )) ),
1393 m_aTypeBox ( VclPtr<CustomPropertiesTypeBox>::Create(pParent, SfxResId( SFX_LB_PROPERTY_TYPE ), this) ),
1394 m_aValueEdit ( VclPtr<CustomPropertiesEdit>::Create(pParent, WB_BORDER|WB_TABSTOP|WB_LEFT, this ) ),
1395 m_aDateField ( VclPtr<CustomPropertiesDateField>::Create(pParent, WB_BORDER|WB_TABSTOP|WB_SPIN|WB_LEFT, this ) ),
1396 m_aTimeField ( VclPtr<CustomPropertiesTimeField>::Create(pParent, WB_BORDER|WB_TABSTOP|WB_SPIN|WB_LEFT, this ) ),
1397 m_sDurationFormat( SfxResId( SFX_ST_DURATION_FORMAT ).toString() ),
1398 m_aDurationField( VclPtr<CustomPropertiesDurationField>::Create(pParent, WB_BORDER|WB_TABSTOP|WB_READONLY, this ) ),
1399 m_aEditButton ( VclPtr<CustomPropertiesEditButton>::Create(pParent, WB_TABSTOP, this) ),
1400 m_aYesNoButton ( VclPtr<CustomPropertiesYesNoButton>::Create(pParent, SfxResId( SFX_WIN_PROPERTY_YESNO )) ),
1401 m_aRemoveButton ( VclPtr<CustomPropertiesRemoveButton>::Create(pParent, 0, this) ),
1402 m_bIsDate ( false ),
1403 m_bIsRemoved ( false ),
1404 m_bTypeLostFocus( false )
1407 m_aTimeField->SetExtFormat( EXTTIMEF_24H_LONG );
1408 m_aDateField->SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YYYY );
1410 m_aRemoveButton->SetModeImage(Image(SfxResId(SFX_IMG_PROPERTY_REMOVE)));
1411 m_aRemoveButton->SetQuickHelpText(SfxResId(STR_SFX_REMOVE_PROPERTY).toString());
1413 m_aEditButton->SetText(SfxResId(SFX_ST_EDIT).toString());
1416 void CustomPropertyLine::SetRemoved()
1418 DBG_ASSERT( !m_bIsRemoved, "CustomPropertyLine::SetRemoved(): line already removed" );
1419 m_bIsRemoved = true;
1420 m_aNameBox->Hide();
1421 m_aTypeBox->Hide();
1422 m_aValueEdit->Hide();
1423 m_aDateField->Hide();
1424 m_aTimeField->Hide();
1425 m_aDurationField->Hide();
1426 m_aEditButton->Hide();
1427 m_aYesNoButton->Hide();
1428 m_aRemoveButton->Hide();
1431 CustomPropertiesWindow::CustomPropertiesWindow(vcl::Window* pParent,
1432 FixedText *pHeaderAccName,
1433 FixedText *pHeaderAccType,
1434 FixedText *pHeaderAccValue) :
1435 Window(pParent, WB_HIDE | WB_CLIPCHILDREN | WB_TABSTOP | WB_DIALOGCONTROL),
1436 m_pHeaderAccName(pHeaderAccName),
1437 m_pHeaderAccType(pHeaderAccType),
1438 m_pHeaderAccValue(pHeaderAccValue),
1439 m_aNameBox ( VclPtr<ComboBox>::Create( this, SfxResId( SFX_CB_PROPERTY_NAME ) ) ),
1440 m_aTypeBox ( VclPtr<ListBox>::Create( this, SfxResId( SFX_LB_PROPERTY_TYPE ) ) ),
1441 m_aValueEdit ( VclPtr<Edit>::Create( this, WB_BORDER|WB_TABSTOP|WB_LEFT ) ),
1442 m_aDateField ( VclPtr<DateField>::Create( this, WB_BORDER|WB_TABSTOP|WB_SPIN|WB_LEFT ) ),
1443 m_aTimeField ( VclPtr<TimeField>::Create( this, WB_BORDER|WB_TABSTOP|WB_SPIN|WB_LEFT ) ),
1444 m_aDurationField( VclPtr<Edit>::Create( this, WB_BORDER|WB_TABSTOP|WB_READONLY ) ),
1445 m_aEditButton ( VclPtr<PushButton>::Create( this, WB_TABSTOP ) ),
1446 m_aYesNoButton ( VclPtr<CustomPropertiesYesNoButton>::Create( this, SfxResId( SFX_WIN_PROPERTY_YESNO )) ),
1447 m_aRemoveButton ( VclPtr<ImageButton>::Create( this, 0 ) ),
1448 m_nScrollPos (0),
1449 m_pCurrentLine (NULL),
1450 m_aNumberFormatter( ::comphelper::getProcessComponentContext(),
1451 Application::GetSettings().GetLanguageTag().getLanguageType() )
1454 m_aEditButton->SetPosSizePixel(
1455 LogicToPixel(Point(159, 2), MAP_APPFONT),
1456 LogicToPixel(Size(RSC_CD_TEXTBOX_HEIGHT, RSC_CD_TEXTBOX_HEIGHT), MAP_APPFONT));
1457 m_aRemoveButton->SetSizePixel(LogicToPixel(Size(RSC_CD_PUSHBUTTON_HEIGHT, RSC_CD_PUSHBUTTON_HEIGHT), MAP_APPFONT));
1459 m_aValueEdit->SetPosSizePixel(
1460 LogicToPixel(Point(159, 2), MAP_APPFONT),
1461 LogicToPixel(Size(61, RSC_CD_TEXTBOX_HEIGHT), MAP_APPFONT));
1463 m_aEditLoseFocusIdle.SetPriority( SchedulerPriority::LOWEST );
1464 m_aEditLoseFocusIdle.SetIdleHdl( LINK( this, CustomPropertiesWindow, EditTimeoutHdl ) );
1465 m_aBoxLoseFocusIdle.SetPriority( SchedulerPriority::LOWEST );
1466 m_aBoxLoseFocusIdle.SetIdleHdl( LINK( this, CustomPropertiesWindow, BoxTimeoutHdl ) );
1468 m_aNameBox->add_mnemonic_label(m_pHeaderAccName);
1469 m_aNameBox->SetAccessibleName(m_pHeaderAccName->GetText());
1470 m_aTypeBox->add_mnemonic_label(m_pHeaderAccType);
1471 m_aTypeBox->SetAccessibleName(m_pHeaderAccType->GetText());
1472 m_aValueEdit->add_mnemonic_label(m_pHeaderAccValue);
1473 m_aValueEdit->SetAccessibleName(m_pHeaderAccValue->GetText());
1475 m_aNameBox->Hide();
1476 m_aTypeBox->Hide();
1477 m_aValueEdit->Hide();
1478 m_aDateField->Hide();
1479 m_aTimeField->Hide();
1480 m_aDurationField->Hide();
1481 m_aEditButton->Hide();
1482 m_aYesNoButton->Hide();
1483 m_aRemoveButton->Hide();
1485 m_nLineHeight =
1486 ( m_aRemoveButton->GetPosPixel().Y() * 2 ) + m_aRemoveButton->GetSizePixel().Height();
1489 CustomPropertiesWindow::~CustomPropertiesWindow()
1491 disposeOnce();
1494 void CustomPropertiesWindow::dispose()
1496 m_aEditLoseFocusIdle.Stop();
1497 m_aBoxLoseFocusIdle.Stop();
1498 ClearAllLines();
1499 m_aNameBox.disposeAndClear();
1500 m_aTypeBox.disposeAndClear();
1501 m_aValueEdit.disposeAndClear();
1502 m_aDateField.disposeAndClear();
1503 m_aTimeField.disposeAndClear();
1504 m_aDurationField.disposeAndClear();
1505 m_aEditButton.disposeAndClear();
1506 m_aYesNoButton.disposeAndClear();
1507 m_aRemoveButton.disposeAndClear();
1508 m_pHeaderAccName.clear();
1509 m_pHeaderAccType.clear();
1510 m_pHeaderAccValue.clear();
1511 vcl::Window::dispose();
1514 IMPL_STATIC_LINK(
1515 CustomPropertiesWindow, TypeHdl, CustomPropertiesTypeBox*, pBox )
1517 long nType = reinterpret_cast<long>( pBox->GetSelectEntryData() );
1518 CustomPropertyLine* pLine = pBox->GetLine();
1519 pLine->m_aValueEdit->Show( (CUSTOM_TYPE_TEXT == nType) || (CUSTOM_TYPE_NUMBER == nType) );
1520 pLine->m_aDateField->Show( (CUSTOM_TYPE_DATE == nType) || (CUSTOM_TYPE_DATETIME == nType) );
1521 pLine->m_aTimeField->Show( CUSTOM_TYPE_DATETIME == nType );
1522 pLine->m_aDurationField->Show( CUSTOM_TYPE_DURATION == nType );
1523 pLine->m_aEditButton->Show( CUSTOM_TYPE_DURATION == nType );
1524 pLine->m_aYesNoButton->Show( CUSTOM_TYPE_BOOLEAN == nType );
1526 //adjust positions of date and time controls
1527 if ( nType == CUSTOM_TYPE_DATE )
1529 pLine->m_bIsDate = true;
1530 pLine->m_aDateField->SetSizePixel( pLine->m_aValueEdit->GetSizePixel() );
1532 else if ( nType == CUSTOM_TYPE_DATETIME)
1534 // because m_aDateField and m_aTimeField have the same size for type "DateTime",
1535 // we just rely on m_aTimeField here.
1536 pLine->m_bIsDate = false;
1537 pLine->m_aDateField->SetSizePixel( pLine->m_aTimeField->GetSizePixel() );
1540 return 0;
1543 IMPL_LINK( CustomPropertiesWindow, RemoveHdl, CustomPropertiesRemoveButton*, pButton )
1545 CustomPropertyLine* pLine = pButton->GetLine();
1546 std::vector< CustomPropertyLine* >::iterator pFound =
1547 std::find( m_aCustomPropertiesLines.begin(), m_aCustomPropertiesLines.end(), pLine );
1548 if ( pFound != m_aCustomPropertiesLines.end() )
1550 pLine = *pFound;
1551 pLine->SetRemoved();
1552 std::vector< CustomPropertyLine* >::iterator pIter = pFound + 1;
1553 const long nDelta = GetLineHeight();
1554 for ( ; pIter != m_aCustomPropertiesLines.end(); ++pIter )
1556 pLine = *pIter;
1557 if ( pLine->m_bIsRemoved )
1558 continue;
1560 vcl::Window* pWindows[] = { pLine->m_aNameBox.get(), pLine->m_aTypeBox.get(), pLine->m_aValueEdit.get(),
1561 pLine->m_aDateField.get(), pLine->m_aTimeField.get(),
1562 pLine->m_aDurationField.get(), pLine->m_aEditButton.get(),
1563 pLine->m_aYesNoButton.get(), pLine->m_aRemoveButton.get(), NULL };
1564 vcl::Window** pCurrent = pWindows;
1565 while ( *pCurrent )
1567 Point aPos = (*pCurrent)->GetPosPixel();
1568 aPos.Y() -= nDelta;
1569 (*pCurrent)->SetPosPixel( aPos );
1570 pCurrent++;
1575 m_aRemovedHdl.Call(0);
1576 return 0;
1579 IMPL_LINK( CustomPropertiesWindow, EditLoseFocusHdl, CustomPropertiesEdit*, pEdit )
1581 if ( pEdit )
1583 CustomPropertyLine* pLine = pEdit->GetLine();
1584 if ( !pLine->m_bTypeLostFocus )
1586 m_pCurrentLine = pLine;
1587 m_aEditLoseFocusIdle.Start();
1589 else
1590 pLine->m_bTypeLostFocus = false;
1592 return 0;
1595 IMPL_LINK( CustomPropertiesWindow, BoxLoseFocusHdl, CustomPropertiesTypeBox*, pBox )
1597 if ( pBox )
1599 m_pCurrentLine = pBox->GetLine();
1600 m_aBoxLoseFocusIdle.Start();
1603 return 0;
1606 IMPL_LINK_NOARG_TYPED(CustomPropertiesWindow, EditTimeoutHdl, Idle *, void)
1608 ValidateLine( m_pCurrentLine, false );
1611 IMPL_LINK_NOARG_TYPED(CustomPropertiesWindow, BoxTimeoutHdl, Idle *, void)
1613 ValidateLine( m_pCurrentLine, true );
1616 bool CustomPropertiesWindow::IsLineValid( CustomPropertyLine* pLine ) const
1618 bool bIsValid = true;
1619 pLine->m_bTypeLostFocus = false;
1620 long nType = reinterpret_cast<long>(
1621 pLine->m_aTypeBox->GetSelectEntryData() );
1622 OUString sValue = pLine->m_aValueEdit->GetText();
1623 if ( sValue.isEmpty() )
1624 return true;
1626 sal_uInt32 nIndex = 0xFFFFFFFF;
1627 if ( CUSTOM_TYPE_NUMBER == nType )
1628 nIndex = const_cast< SvNumberFormatter& >(
1629 m_aNumberFormatter ).GetFormatIndex( NF_NUMBER_SYSTEM );
1630 else if ( CUSTOM_TYPE_DATE == nType )
1631 nIndex = const_cast< SvNumberFormatter& >(
1632 m_aNumberFormatter).GetFormatIndex( NF_DATE_SYS_DDMMYYYY );
1634 if ( nIndex != 0xFFFFFFFF )
1636 sal_uInt32 nTemp = nIndex;
1637 double fDummy = 0.0;
1638 bIsValid = const_cast< SvNumberFormatter& >(
1639 m_aNumberFormatter ).IsNumberFormat( sValue, nIndex, fDummy );
1640 if ( bIsValid && nTemp != nIndex )
1641 // sValue is a number but the format doesn't match the index
1642 bIsValid = false;
1645 return bIsValid;
1648 void CustomPropertiesWindow::ValidateLine( CustomPropertyLine* pLine, bool bIsFromTypeBox )
1650 if ( !IsLineValid( pLine ) )
1652 if ( bIsFromTypeBox ) // LoseFocus of TypeBox
1653 pLine->m_bTypeLostFocus = true;
1654 vcl::Window* pParent = GetParent()->GetParent();
1655 if (ScopedVclPtrInstance<MessageDialog>::Create(pParent, SfxResId(STR_SFX_QUERY_WRONG_TYPE), VCL_MESSAGE_QUESTION, VCL_BUTTONS_OK_CANCEL)->Execute() == RET_OK)
1656 pLine->m_aTypeBox->SelectEntryPos( m_aTypeBox->GetEntryPos( reinterpret_cast<void*>(CUSTOM_TYPE_TEXT) ) );
1657 else
1658 pLine->m_aValueEdit->GrabFocus();
1662 bool CustomPropertiesWindow::InitControls( HeaderBar* pHeaderBar, const ScrollBar* pScrollBar )
1664 bool bChanged = false;
1666 DBG_ASSERT( pHeaderBar, "CustomPropertiesWindow::InitControls(): invalid headerbar" );
1667 DBG_ASSERT( pScrollBar, "CustomPropertiesWindow::InitControls(): invalid scrollbar" );
1669 const long nOffset = 4;
1670 const long nScrollBarWidth = pScrollBar->GetSizePixel().Width();
1671 const long nButtonWidth = m_aRemoveButton->GetSizePixel().Width() + nScrollBarWidth + nOffset;
1672 long nTypeWidth = m_aTypeBox->CalcMinimumSize().Width() + ( 2 * nOffset );
1673 long nFullWidth = pHeaderBar->GetSizePixel().Width();
1674 long nItemWidth = ( nFullWidth - nTypeWidth - nButtonWidth ) / 2;
1675 pHeaderBar->SetItemSize( HI_NAME, nItemWidth );
1676 pHeaderBar->SetItemSize( HI_TYPE, nTypeWidth );
1677 pHeaderBar->SetItemSize( HI_VALUE, nItemWidth );
1678 pHeaderBar->SetItemSize( HI_ACTION, nButtonWidth );
1680 vcl::Window* pWindows[] = { m_aNameBox.get(), m_aTypeBox.get(), m_aValueEdit.get(), m_aRemoveButton.get(), NULL };
1681 vcl::Window** pCurrent = pWindows;
1682 sal_uInt16 nPos = 0;
1683 while ( *pCurrent )
1685 Rectangle aRect = pHeaderBar->GetItemRect( pHeaderBar->GetItemId( nPos++ ) );
1686 Size aOrigSize = (*pCurrent)->GetSizePixel();
1687 Point aOrigPos = (*pCurrent)->GetPosPixel();
1688 Size aSize(aOrigSize);
1689 Point aPos(aOrigPos);
1690 long nWidth = aRect.GetWidth() - nOffset;
1691 if ( *pCurrent == m_aRemoveButton.get() )
1692 nWidth -= pScrollBar->GetSizePixel().Width();
1693 aSize.Width() = nWidth;
1694 aPos.X() = aRect.getX() + ( nOffset / 2 );
1696 if (aOrigSize != aSize || aOrigPos != aPos)
1698 (*pCurrent)->SetPosSizePixel(aPos, aSize);
1699 bChanged = true;
1702 if ( *pCurrent == m_aValueEdit.get() )
1704 Point aDurationPos( aPos );
1705 m_aDurationField->SetPosPixel( aDurationPos );
1706 Size aDurationSize(aSize);
1707 aDurationSize.Width() -= (m_aEditButton->GetSizePixel().Width() + 3 );
1708 m_aDurationField->SetSizePixel(aDurationSize);
1709 aDurationPos.X() = aPos.X() - m_aEditButton->GetSizePixel().Width() + aSize.Width();
1710 m_aEditButton->SetPosPixel(aDurationPos);
1712 m_aYesNoButton->SetPosSizePixel( aPos, aSize );
1714 aSize.Width() /= 2;
1715 aSize.Width() -= 2;
1716 m_aDateField->SetPosSizePixel( aPos, aSize );
1717 aPos.X() += aSize.Width() + 4;
1718 m_aTimeField->SetPosSizePixel( aPos, aSize );
1721 pCurrent++;
1723 return bChanged;
1726 sal_uInt16 CustomPropertiesWindow::GetVisibleLineCount() const
1728 sal_uInt16 nCount = 0;
1729 std::vector< CustomPropertyLine* >::const_iterator pIter;
1730 for ( pIter = m_aCustomPropertiesLines.begin();
1731 pIter != m_aCustomPropertiesLines.end(); ++pIter )
1733 CustomPropertyLine* pLine = *pIter;
1734 if ( !pLine->m_bIsRemoved )
1735 nCount++;
1737 return nCount;
1740 void CustomPropertiesWindow::updateLineWidth()
1742 vcl::Window* pWindows[] = { m_aNameBox.get(), m_aTypeBox.get(), m_aValueEdit.get(),
1743 m_aDateField.get(), m_aTimeField.get(),
1744 m_aDurationField.get(), m_aEditButton.get(),
1745 m_aYesNoButton.get(), m_aRemoveButton.get(), NULL };
1747 for (std::vector< CustomPropertyLine* >::iterator aI =
1748 m_aCustomPropertiesLines.begin(), aEnd = m_aCustomPropertiesLines.end();
1749 aI != aEnd; ++aI)
1751 CustomPropertyLine* pNewLine = *aI;
1753 vcl::Window* pNewWindows[] =
1754 { pNewLine->m_aNameBox.get(), pNewLine->m_aTypeBox.get(), pNewLine->m_aValueEdit.get(),
1755 pNewLine->m_aDateField.get(), pNewLine->m_aTimeField.get(),
1756 pNewLine->m_aDurationField.get(), pNewLine->m_aEditButton.get(),
1757 pNewLine->m_aYesNoButton.get(), pNewLine->m_aRemoveButton.get(), NULL };
1759 vcl::Window** pCurrent = pWindows;
1760 vcl::Window** pNewCurrent = pNewWindows;
1761 while ( *pCurrent )
1763 Size aSize = (*pCurrent)->GetSizePixel();
1764 Point aPos = (*pCurrent)->GetPosPixel();
1765 aPos.Y() = (*pNewCurrent)->GetPosPixel().Y();
1766 (*pNewCurrent)->SetPosSizePixel( aPos, aSize );
1767 pCurrent++;
1768 pNewCurrent++;
1771 // if we have type "Date", we use the full width, not only the half
1772 if (pNewLine->m_bIsDate)
1773 pNewLine->m_aDateField->SetSizePixel( pNewLine->m_aValueEdit->GetSizePixel() );
1777 void CustomPropertiesWindow::AddLine( const OUString& sName, Any& rAny )
1779 CustomPropertyLine* pNewLine = new CustomPropertyLine( this );
1780 pNewLine->m_aTypeBox->SetSelectHdl( LINK( this, CustomPropertiesWindow, TypeHdl ) );
1781 pNewLine->m_aRemoveButton->SetClickHdl( LINK( this, CustomPropertiesWindow, RemoveHdl ) );
1782 pNewLine->m_aValueEdit->SetLoseFocusHdl( LINK( this, CustomPropertiesWindow, EditLoseFocusHdl ) );
1783 //add lose focus handlers of date/time fields
1785 pNewLine->m_aTypeBox->SetLoseFocusHdl( LINK( this, CustomPropertiesWindow, BoxLoseFocusHdl ) );
1787 pNewLine->m_aNameBox->add_mnemonic_label(m_pHeaderAccName);
1788 pNewLine->m_aNameBox->SetAccessibleName(m_pHeaderAccName->GetText());
1789 pNewLine->m_aTypeBox->add_mnemonic_label(m_pHeaderAccType);
1790 pNewLine->m_aTypeBox->SetAccessibleName(m_pHeaderAccType->GetText());
1791 pNewLine->m_aValueEdit->add_mnemonic_label(m_pHeaderAccValue);
1792 pNewLine->m_aValueEdit->SetAccessibleName(m_pHeaderAccValue->GetText());
1794 sal_Int32 nPos = GetVisibleLineCount() * GetLineHeight();
1795 m_aCustomPropertiesLines.push_back( pNewLine );
1796 vcl::Window* pWindows[] = { m_aNameBox.get(), m_aTypeBox.get(), m_aValueEdit.get(),
1797 m_aDateField.get(), m_aTimeField.get(),
1798 m_aDurationField.get(), m_aEditButton.get(),
1799 m_aYesNoButton.get(), m_aRemoveButton.get(), NULL };
1800 vcl::Window* pNewWindows[] =
1801 { pNewLine->m_aNameBox.get(), pNewLine->m_aTypeBox.get(), pNewLine->m_aValueEdit.get(),
1802 pNewLine->m_aDateField.get(), pNewLine->m_aTimeField.get(),
1803 pNewLine->m_aDurationField.get(), pNewLine->m_aEditButton.get(),
1804 pNewLine->m_aYesNoButton.get(), pNewLine->m_aRemoveButton.get(), NULL };
1805 vcl::Window** pCurrent = pWindows;
1806 vcl::Window** pNewCurrent = pNewWindows;
1807 while ( *pCurrent )
1809 Size aSize = (*pCurrent)->GetSizePixel();
1810 Point aPos = (*pCurrent)->GetPosPixel();
1811 aPos.Y() += nPos;
1812 aPos.Y() += m_nScrollPos;
1813 (*pNewCurrent)->SetPosSizePixel( aPos, aSize );
1814 (*pNewCurrent)->Show();
1815 pCurrent++;
1816 pNewCurrent++;
1819 double nTmpValue = 0;
1820 bool bTmpValue = false;
1821 OUString sTmpValue;
1822 util::DateTime aTmpDateTime;
1823 util::Date aTmpDate;
1824 util::DateTimeWithTimezone aTmpDateTimeTZ;
1825 util::DateWithTimezone aTmpDateTZ;
1826 util::Duration aTmpDuration;
1827 SvtSysLocale aSysLocale;
1828 const LocaleDataWrapper& rLocaleWrapper = aSysLocale.GetLocaleData();
1829 pNewLine->m_aNameBox->SetText( sName );
1830 sal_IntPtr nType = CUSTOM_TYPE_UNKNOWN;
1831 OUString sValue;
1833 if ( rAny >>= nTmpValue )
1835 sal_uInt32 nIndex = m_aNumberFormatter.GetFormatIndex( NF_NUMBER_SYSTEM );
1836 m_aNumberFormatter.GetInputLineString( nTmpValue, nIndex, sValue );
1837 pNewLine->m_aValueEdit->SetText( sValue );
1838 nType = CUSTOM_TYPE_NUMBER;
1840 else if ( rAny >>= bTmpValue )
1842 sValue = ( bTmpValue ? rLocaleWrapper.getTrueWord() : rLocaleWrapper.getFalseWord() );
1843 nType = CUSTOM_TYPE_BOOLEAN;
1845 else if ( rAny >>= sTmpValue )
1847 pNewLine->m_aValueEdit->SetText( sTmpValue );
1848 nType = CUSTOM_TYPE_TEXT;
1850 else if ( rAny >>= aTmpDate )
1852 pNewLine->m_aDateField->SetDate( Date( aTmpDate ) );
1853 nType = CUSTOM_TYPE_DATE;
1855 else if ( rAny >>= aTmpDateTime )
1857 pNewLine->m_aDateField->SetDate( Date( aTmpDateTime ) );
1858 pNewLine->m_aTimeField->SetTime( tools::Time( aTmpDateTime ) );
1859 pNewLine->m_aTimeField->m_isUTC = aTmpDateTime.IsUTC;
1860 nType = CUSTOM_TYPE_DATETIME;
1862 else if ( rAny >>= aTmpDateTZ )
1864 pNewLine->m_aDateField->SetDate( Date( aTmpDateTZ.DateInTZ.Day,
1865 aTmpDateTZ.DateInTZ.Month, aTmpDateTZ.DateInTZ.Year ) );
1866 pNewLine->m_aDateField->m_TZ = aTmpDateTZ.Timezone;
1867 nType = CUSTOM_TYPE_DATE;
1869 else if ( rAny >>= aTmpDateTimeTZ )
1871 util::DateTime const& rDT(aTmpDateTimeTZ.DateTimeInTZ);
1872 pNewLine->m_aDateField->SetDate( Date( rDT ) );
1873 pNewLine->m_aTimeField->SetTime( tools::Time( rDT ) );
1874 pNewLine->m_aTimeField->m_isUTC = rDT.IsUTC;
1875 pNewLine->m_aDateField->m_TZ = aTmpDateTimeTZ.Timezone;
1876 nType = CUSTOM_TYPE_DATETIME;
1878 else if ( rAny >>= aTmpDuration )
1880 nType = CUSTOM_TYPE_DURATION;
1881 pNewLine->m_aDurationField->SetDuration( aTmpDuration );
1884 if ( nType != CUSTOM_TYPE_UNKNOWN )
1886 if ( CUSTOM_TYPE_BOOLEAN == nType )
1888 if ( bTmpValue )
1889 pNewLine->m_aYesNoButton->CheckYes();
1890 else
1891 pNewLine->m_aYesNoButton->CheckNo();
1893 pNewLine->m_aTypeBox->SelectEntryPos( m_aTypeBox->GetEntryPos( reinterpret_cast<void*>(nType) ) );
1896 TypeHdl( nullptr, pNewLine->m_aTypeBox.get() );
1897 pNewLine->m_aNameBox->GrabFocus();
1900 bool CustomPropertiesWindow::AreAllLinesValid() const
1902 bool bRet = true;
1903 std::vector< CustomPropertyLine* >::const_iterator pIter;
1904 for ( pIter = m_aCustomPropertiesLines.begin();
1905 pIter != m_aCustomPropertiesLines.end(); ++pIter )
1907 CustomPropertyLine* pLine = *pIter;
1908 if ( !IsLineValid( pLine ) )
1910 bRet = false;
1911 break;
1915 return bRet;
1918 void CustomPropertiesWindow::ClearAllLines()
1920 std::vector< CustomPropertyLine* >::iterator pIter;
1921 for ( pIter = m_aCustomPropertiesLines.begin();
1922 pIter != m_aCustomPropertiesLines.end(); ++pIter )
1924 CustomPropertyLine* pLine = *pIter;
1925 pLine->SetRemoved();
1926 delete pLine;
1928 m_aCustomPropertiesLines.clear();
1929 m_nScrollPos = 0;
1932 void CustomPropertiesWindow::DoScroll( sal_Int32 nNewPos )
1934 m_nScrollPos += nNewPos;
1935 std::vector< CustomPropertyLine* >::iterator pIter;
1936 for ( pIter = m_aCustomPropertiesLines.begin();
1937 pIter != m_aCustomPropertiesLines.end(); ++pIter )
1939 CustomPropertyLine* pLine = *pIter;
1940 if ( pLine->m_bIsRemoved )
1941 continue;
1943 vcl::Window* pWindows[] = { pLine->m_aNameBox.get(), pLine->m_aTypeBox.get(), pLine->m_aValueEdit.get(), pLine->m_aDateField.get(), pLine->m_aTimeField.get(),
1944 pLine->m_aDurationField.get(), pLine->m_aEditButton.get(), pLine->m_aYesNoButton.get(), pLine->m_aRemoveButton.get(), NULL };
1945 vcl::Window** pCurrent = pWindows;
1946 while ( *pCurrent )
1948 Point aPos = (*pCurrent)->GetPosPixel();
1949 aPos.Y() += nNewPos;
1950 (*pCurrent)->SetPosPixel( aPos );
1951 pCurrent++;
1956 Sequence< beans::PropertyValue > CustomPropertiesWindow::GetCustomProperties() const
1958 Sequence< beans::PropertyValue > aPropertiesSeq( m_aCustomPropertiesLines.size() );
1959 sal_Int32 i = 0;
1960 std::vector< CustomPropertyLine* >::const_iterator pIter;
1961 for ( pIter = m_aCustomPropertiesLines.begin();
1962 pIter != m_aCustomPropertiesLines.end(); ++pIter, ++i )
1964 CustomPropertyLine* pLine = *pIter;
1965 if ( pLine->m_bIsRemoved )
1966 continue;
1968 OUString sPropertyName = pLine->m_aNameBox->GetText();
1969 if ( !sPropertyName.isEmpty() )
1971 aPropertiesSeq[i].Name = sPropertyName;
1972 long nType = reinterpret_cast<long>(
1973 pLine->m_aTypeBox->GetSelectEntryData() );
1974 if ( CUSTOM_TYPE_NUMBER == nType )
1976 double nValue = 0;
1977 sal_uInt32 nIndex = const_cast< SvNumberFormatter& >(
1978 m_aNumberFormatter ).GetFormatIndex( NF_NUMBER_SYSTEM );
1979 bool bIsNum = const_cast< SvNumberFormatter& >( m_aNumberFormatter ).
1980 IsNumberFormat( pLine->m_aValueEdit->GetText(), nIndex, nValue );
1981 if ( bIsNum )
1982 aPropertiesSeq[i].Value <<= makeAny( nValue );
1984 else if ( CUSTOM_TYPE_BOOLEAN == nType )
1986 bool bValue = pLine->m_aYesNoButton->IsYesChecked();
1987 aPropertiesSeq[i].Value <<= makeAny( bValue );
1989 else if ( CUSTOM_TYPE_DATETIME == nType )
1991 Date aTmpDate = pLine->m_aDateField->GetDate();
1992 tools::Time aTmpTime = pLine->m_aTimeField->GetTime();
1993 util::DateTime const aDateTime(aTmpTime.GetNanoSec(),
1994 aTmpTime.GetSec(), aTmpTime.GetMin(), aTmpTime.GetHour(),
1995 aTmpDate.GetDay(), aTmpDate.GetMonth(), aTmpDate.GetYear(),
1996 pLine->m_aTimeField->m_isUTC);
1997 if (pLine->m_aDateField->m_TZ.is_initialized())
1999 aPropertiesSeq[i].Value <<= util::DateTimeWithTimezone(
2000 aDateTime, pLine->m_aDateField->m_TZ.get());
2002 else
2004 aPropertiesSeq[i].Value <<= aDateTime;
2007 else if ( CUSTOM_TYPE_DATE == nType )
2009 Date aTmpDate = pLine->m_aDateField->GetDate();
2010 util::Date const aDate(aTmpDate.GetDay(), aTmpDate.GetMonth(),
2011 aTmpDate.GetYear());
2012 if (pLine->m_aDateField->m_TZ.is_initialized())
2014 aPropertiesSeq[i].Value <<= util::DateWithTimezone(
2015 aDate, pLine->m_aDateField->m_TZ.get());
2017 else
2019 aPropertiesSeq[i].Value <<= aDate;
2022 else if ( CUSTOM_TYPE_DURATION == nType )
2024 aPropertiesSeq[i].Value <<= pLine->m_aDurationField->GetDuration();
2026 else
2028 OUString sValue( pLine->m_aValueEdit->GetText() );
2029 aPropertiesSeq[i].Value <<= makeAny( sValue );
2034 return aPropertiesSeq;
2037 CustomPropertiesControl::CustomPropertiesControl(vcl::Window* pParent)
2038 : Window(pParent, WB_HIDE | WB_CLIPCHILDREN | WB_TABSTOP | WB_DIALOGCONTROL | WB_BORDER)
2039 , m_pVBox(NULL)
2040 , m_pHeaderBar(NULL)
2041 , m_pBody(NULL)
2042 , m_pPropertiesWin(NULL)
2043 , m_pVertScroll(NULL)
2044 , m_nThumbPos(0)
2048 void CustomPropertiesControl::Init(VclBuilderContainer& rBuilder)
2050 m_pVBox = VclPtr<VclVBox>::Create(this);
2051 m_pHeaderBar = VclPtr<HeaderBar>::Create(m_pVBox, WB_BUTTONSTYLE | WB_BOTTOMBORDER);
2052 m_pBody = VclPtr<VclHBox>::Create(m_pVBox);
2053 FixedText* pName = rBuilder.get<FixedText>("name");
2054 FixedText* pType = rBuilder.get<FixedText>("type");
2055 FixedText* pValue = rBuilder.get<FixedText>("value");
2056 OUString sName = pName->GetText();
2057 OUString sType = pType->GetText();
2058 OUString sValue = pValue->GetText();
2059 m_pPropertiesWin = VclPtr<CustomPropertiesWindow>::Create(m_pBody, pName, pType, pValue);
2060 m_pVertScroll = VclPtr<ScrollBar>::Create(m_pBody, WB_VERT);
2062 set_hexpand(true);
2063 set_vexpand(true);
2064 set_expand(true);
2065 set_fill(true);
2067 m_pVBox->set_hexpand(true);
2068 m_pVBox->set_vexpand(true);
2069 m_pVBox->set_expand(true);
2070 m_pVBox->set_fill(true);
2071 m_pVBox->Show();
2073 m_pBody->set_hexpand(true);
2074 m_pBody->set_vexpand(true);
2075 m_pBody->set_expand(true);
2076 m_pBody->set_fill(true);
2077 m_pBody->Show();
2079 m_pPropertiesWin->set_hexpand(true);
2080 m_pPropertiesWin->set_vexpand(true);
2081 m_pPropertiesWin->set_expand(true);
2082 m_pPropertiesWin->set_fill(true);
2083 m_pPropertiesWin->Show();
2085 m_pPropertiesWin->SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
2086 m_pVertScroll->EnableDrag();
2087 m_pVertScroll->Show();
2089 m_pHeaderBar->set_height_request(GetTextHeight() + 6);
2091 const HeaderBarItemBits nHeadBits = HeaderBarItemBits::VCENTER | HeaderBarItemBits::FIXED | HeaderBarItemBits::FIXEDPOS | HeaderBarItemBits::LEFT;
2093 m_pHeaderBar->InsertItem( HI_NAME, sName, 0, nHeadBits );
2094 m_pHeaderBar->InsertItem( HI_TYPE, sType, 0, nHeadBits );
2095 m_pHeaderBar->InsertItem( HI_VALUE, sValue, 0, nHeadBits );
2096 m_pHeaderBar->InsertItem( HI_ACTION, OUString(), 0, nHeadBits );
2097 m_pHeaderBar->Show();
2099 m_pPropertiesWin->SetRemovedHdl( LINK( this, CustomPropertiesControl, RemovedHdl ) );
2101 m_pVertScroll->SetRangeMin( 0 );
2102 m_pVertScroll->SetRangeMax( 0 );
2103 m_pVertScroll->SetVisibleSize( 0xFFFF );
2105 Link<> aScrollLink = LINK( this, CustomPropertiesControl, ScrollHdl );
2106 m_pVertScroll->SetScrollHdl( aScrollLink );
2109 void CustomPropertiesControl::Resize()
2111 Window::Resize();
2113 if (!m_pVBox)
2114 return;
2116 m_pVBox->SetSizePixel(GetSizePixel());
2118 bool bWidgetsResized = m_pPropertiesWin->InitControls( m_pHeaderBar, m_pVertScroll );
2119 sal_Int32 nScrollOffset = m_pPropertiesWin->GetLineHeight();
2120 sal_Int32 nVisibleEntries = m_pPropertiesWin->GetSizePixel().Height() / nScrollOffset;
2121 m_pVertScroll->SetPageSize( nVisibleEntries - 1 );
2122 m_pVertScroll->SetVisibleSize( nVisibleEntries );
2123 if (bWidgetsResized)
2125 m_pPropertiesWin->updateLineWidth();
2129 VCL_BUILDER_FACTORY(CustomPropertiesControl)
2131 CustomPropertiesControl::~CustomPropertiesControl()
2133 disposeOnce();
2136 void CustomPropertiesControl::dispose()
2138 m_pVertScroll.disposeAndClear();
2139 m_pPropertiesWin.disposeAndClear();
2140 m_pBody.disposeAndClear();
2141 m_pHeaderBar.disposeAndClear();
2142 m_pVBox.disposeAndClear();
2143 vcl::Window::dispose();
2146 IMPL_LINK( CustomPropertiesControl, ScrollHdl, ScrollBar*, pScrollBar )
2148 sal_Int32 nOffset = m_pPropertiesWin->GetLineHeight();
2149 nOffset *= ( m_nThumbPos - pScrollBar->GetThumbPos() );
2150 m_nThumbPos = pScrollBar->GetThumbPos();
2151 m_pPropertiesWin->DoScroll( nOffset );
2152 return 0;
2155 IMPL_LINK_NOARG(CustomPropertiesControl, RemovedHdl)
2157 long nLineCount = m_pPropertiesWin->GetVisibleLineCount();
2158 m_pVertScroll->SetRangeMax(nLineCount + 1);
2159 if ( m_pPropertiesWin->GetOutputSizePixel().Height() < nLineCount * m_pPropertiesWin->GetLineHeight() )
2160 m_pVertScroll->DoScrollAction ( SCROLL_LINEUP );
2161 return 0;
2164 void CustomPropertiesControl::AddLine( const OUString& sName, Any& rAny, bool bInteractive )
2166 m_pPropertiesWin->AddLine( sName, rAny );
2167 long nLineCount = m_pPropertiesWin->GetVisibleLineCount();
2168 m_pVertScroll->SetRangeMax(nLineCount + 1);
2169 if ( bInteractive && m_pPropertiesWin->GetOutputSizePixel().Height() < nLineCount * m_pPropertiesWin->GetLineHeight() )
2170 m_pVertScroll->DoScroll(nLineCount + 1);
2173 // class SfxCustomPropertiesPage -----------------------------------------
2174 SfxCustomPropertiesPage::SfxCustomPropertiesPage( vcl::Window* pParent, const SfxItemSet& rItemSet )
2175 : SfxTabPage(pParent, "CustomInfoPage", "sfx/ui/custominfopage.ui", &rItemSet)
2177 get(m_pPropertiesCtrl, "properties");
2178 m_pPropertiesCtrl->Init(*this);
2179 get<PushButton>("add")->SetClickHdl(LINK(this, SfxCustomPropertiesPage, AddHdl));
2182 SfxCustomPropertiesPage::~SfxCustomPropertiesPage()
2184 disposeOnce();
2187 void SfxCustomPropertiesPage::dispose()
2189 m_pPropertiesCtrl.clear();
2190 SfxTabPage::dispose();
2193 IMPL_LINK_NOARG(SfxCustomPropertiesPage, AddHdl)
2195 Any aAny;
2196 m_pPropertiesCtrl->AddLine( OUString(), aAny, true );
2197 return 0;
2200 bool SfxCustomPropertiesPage::FillItemSet( SfxItemSet* rSet )
2202 bool bModified = false;
2203 const SfxPoolItem* pItem = NULL;
2204 SfxDocumentInfoItem* pInfo = NULL;
2205 bool bMustDelete = false;
2207 if ( GetTabDialog() && GetTabDialog()->GetExampleSet() )
2209 if ( SfxItemState::SET !=
2210 GetTabDialog()->GetExampleSet()->GetItemState( SID_DOCINFO, true, &pItem ) )
2211 pInfo = const_cast<SfxDocumentInfoItem*>(&static_cast<const SfxDocumentInfoItem& >(rSet->Get( SID_DOCINFO )));
2212 else
2214 bMustDelete = true;
2215 pInfo = new SfxDocumentInfoItem( *static_cast<const SfxDocumentInfoItem*>(pItem) );
2219 if ( pInfo )
2221 // If it's a CMIS document, we can't save custom properties
2222 if ( pInfo->isCmisDocument( ) )
2224 if ( bMustDelete )
2225 delete pInfo;
2226 return false;
2229 pInfo->ClearCustomProperties();
2230 Sequence< beans::PropertyValue > aPropertySeq = m_pPropertiesCtrl->GetCustomProperties();
2231 sal_Int32 i = 0, nCount = aPropertySeq.getLength();
2232 for ( ; i < nCount; ++i )
2234 if ( !aPropertySeq[i].Name.isEmpty() )
2235 pInfo->AddCustomProperty( aPropertySeq[i].Name, aPropertySeq[i].Value );
2239 bModified = true; //!!!
2241 if (pInfo)
2243 if ( bModified )
2244 rSet->Put( *pInfo );
2245 if ( bMustDelete )
2246 delete pInfo;
2248 return bModified;
2251 void SfxCustomPropertiesPage::Reset( const SfxItemSet* rItemSet )
2253 m_pPropertiesCtrl->ClearAllLines();
2254 const SfxDocumentInfoItem& rInfoItem = static_cast<const SfxDocumentInfoItem &>(rItemSet->Get(SID_DOCINFO));
2255 std::vector< CustomProperty* > aCustomProps = rInfoItem.GetCustomProperties();
2256 for ( sal_uInt32 i = 0; i < aCustomProps.size(); i++ )
2258 m_pPropertiesCtrl->AddLine( aCustomProps[i]->m_sName, aCustomProps[i]->m_aValue, false );
2262 SfxTabPage::sfxpg SfxCustomPropertiesPage::DeactivatePage( SfxItemSet* /*pSet*/ )
2264 sfxpg nRet = LEAVE_PAGE;
2265 if ( !m_pPropertiesCtrl->AreAllLinesValid() )
2266 nRet = KEEP_PAGE;
2267 return nRet;
2270 VclPtr<SfxTabPage> SfxCustomPropertiesPage::Create( vcl::Window* pParent, const SfxItemSet* rItemSet )
2272 return VclPtr<SfxCustomPropertiesPage>::Create( pParent, *rItemSet );
2275 CmisValue::CmisValue( vcl::Window* pParent, const OUString& aStr )
2277 m_pUIBuilder = new VclBuilder( pParent, getUIRootDir(), "sfx/ui/cmisline.ui");
2278 get( m_aValueEdit, "value");
2279 m_aValueEdit->Show( true );
2280 m_aValueEdit->SetText( aStr );
2283 CmisDateTime::CmisDateTime( vcl::Window* pParent, const util::DateTime& aDateTime )
2285 m_pUIBuilder = new VclBuilder( pParent, getUIRootDir(), "sfx/ui/cmisline.ui");
2286 get( m_aDateField, "date");
2287 get( m_aTimeField, "time");
2288 m_aDateField->Show( true );
2289 m_aTimeField->Show( true );
2290 m_aDateField->SetDate( Date( aDateTime ) );
2291 m_aTimeField->SetTime( tools::Time( aDateTime ) );
2294 CmisYesNo::CmisYesNo( vcl::Window* pParent, bool bValue )
2296 m_pUIBuilder = new VclBuilder( pParent, getUIRootDir(), "sfx/ui/cmisline.ui");
2297 get( m_aYesButton, "yes");
2298 get( m_aNoButton, "no");
2299 m_aYesButton->Show( true );
2300 m_aNoButton->Show( true );
2301 if ( bValue )
2302 m_aYesButton->Check( );
2303 else
2304 m_aNoButton->Check( );
2307 // struct CmisPropertyLine ---------------------------------------------
2308 CmisPropertyLine::CmisPropertyLine(vcl::Window* pParent)
2309 : m_sType(CMIS_TYPE_STRING)
2310 , m_bUpdatable(false)
2311 , m_bRequired(false)
2312 , m_bMultiValued(false)
2313 , m_bOpenChoice(false)
2314 , m_nNumValue(1)
2316 m_pUIBuilder = new VclBuilder( pParent, getUIRootDir(), "sfx/ui/cmisline.ui");
2317 get( m_pFrame, "CmisFrame" );
2318 get( m_aName, "name" );
2319 get( m_aType, "type" );
2320 m_pFrame->Enable();
2323 CmisPropertyLine::~CmisPropertyLine( )
2325 std::vector< CmisValue* >::iterator pIter;
2326 for ( pIter = m_aValues.begin();
2327 pIter != m_aValues.end(); ++pIter )
2329 CmisValue* pValue = *pIter;
2330 delete pValue;
2332 m_aValues.clear();
2334 std::vector< CmisYesNo* >::iterator pIterYesNo;
2335 for ( pIterYesNo = m_aYesNos.begin();
2336 pIterYesNo != m_aYesNos.end(); ++pIterYesNo )
2338 CmisYesNo* pYesNo = *pIterYesNo;
2339 delete pYesNo;
2341 m_aYesNos.clear();
2343 std::vector< CmisDateTime* >::iterator pIterDateTime;
2344 for ( pIterDateTime = m_aDateTimes.begin();
2345 pIterDateTime != m_aDateTimes.end(); ++pIterDateTime )
2347 CmisDateTime* pDateTime = *pIterDateTime;
2348 delete pDateTime;
2350 m_aDateTimes.clear();
2354 long CmisPropertyLine::getItemHeight() const
2356 return VclContainer::getLayoutRequisition(*m_pFrame).Height();
2359 // class CmisPropertiesWindow -----------------------------------------
2361 CmisPropertiesWindow::CmisPropertiesWindow(SfxTabPage* pParent):
2362 m_aNumberFormatter( ::comphelper::getProcessComponentContext(),
2363 Application::GetSettings().GetLanguageTag().getLanguageType() )
2366 pParent->get(m_pBox, "CmisWindow");
2367 CmisPropertyLine aTemp( m_pBox );
2368 m_nItemHeight = aTemp.getItemHeight();
2371 CmisPropertiesWindow::~CmisPropertiesWindow()
2373 ClearAllLines();
2376 void CmisPropertiesWindow::ClearAllLines()
2378 std::vector< CmisPropertyLine* >::iterator pIter;
2379 for ( pIter = m_aCmisPropertiesLines.begin();
2380 pIter != m_aCmisPropertiesLines.end(); ++pIter )
2382 CmisPropertyLine* pLine = *pIter;
2383 delete pLine;
2385 m_aCmisPropertiesLines.clear();
2388 sal_uInt16 CmisPropertiesWindow::GetLineCount() const
2390 sal_uInt16 nCount = 0;
2391 std::vector< CmisPropertyLine* >::const_iterator pIter;
2392 for ( pIter = m_aCmisPropertiesLines.begin();
2393 pIter != m_aCmisPropertiesLines.end(); ++pIter )
2394 nCount += ( (*pIter)->m_nNumValue + 1 );
2395 return nCount;
2398 void CmisPropertiesWindow::AddLine( const OUString& sId, const OUString& sName,
2399 const OUString& sType, const bool bUpdatable,
2400 const bool bRequired, const bool bMultiValued,
2401 const bool bOpenChoice, Any& /*aChoices*/, Any& rAny )
2403 CmisPropertyLine* pNewLine = new CmisPropertyLine( m_pBox );
2405 pNewLine->m_sId = sId;
2406 pNewLine->m_sType = sType;
2407 pNewLine->m_bUpdatable = bUpdatable;
2408 pNewLine->m_bRequired = bRequired;
2409 pNewLine->m_bMultiValued = bMultiValued;
2410 pNewLine->m_bOpenChoice = bOpenChoice;
2412 if ( sType == CMIS_TYPE_INTEGER )
2414 Sequence< sal_Int64 > seqValue;
2415 rAny >>= seqValue;
2416 sal_uInt32 nIndex = m_aNumberFormatter.GetFormatIndex( NF_NUMBER_SYSTEM );
2417 sal_Int32 m_nNumValue = seqValue.getLength( );
2418 for ( sal_Int32 i = 0; i < m_nNumValue; ++i )
2420 OUString sValue;
2421 m_aNumberFormatter.GetInputLineString( seqValue[i], nIndex, sValue );
2422 CmisValue* pValue = new CmisValue( m_pBox, sValue );
2423 pValue->m_aValueEdit->SetReadOnly( !bUpdatable );
2424 pNewLine->m_aValues.push_back( pValue );
2427 else if ( sType == CMIS_TYPE_DECIMAL )
2429 Sequence< double > seqValue;
2430 rAny >>= seqValue;
2431 sal_uInt32 nIndex = m_aNumberFormatter.GetFormatIndex( NF_NUMBER_SYSTEM );
2432 sal_Int32 m_nNumValue = seqValue.getLength( );
2433 for ( sal_Int32 i = 0; i < m_nNumValue; ++i )
2435 OUString sValue;
2436 m_aNumberFormatter.GetInputLineString( seqValue[i], nIndex, sValue );
2437 CmisValue* pValue = new CmisValue( m_pBox, sValue );
2438 pValue->m_aValueEdit->SetReadOnly( !bUpdatable );
2439 pNewLine->m_aValues.push_back( pValue );
2443 else if ( sType == CMIS_TYPE_BOOL )
2445 Sequence<sal_Bool> seqValue;
2446 rAny >>= seqValue;
2447 sal_Int32 m_nNumValue = seqValue.getLength( );
2448 for ( sal_Int32 i = 0; i < m_nNumValue; ++i )
2450 CmisYesNo* pYesNo = new CmisYesNo( m_pBox, seqValue[i] );
2451 pYesNo->m_aYesButton->Enable( bUpdatable );
2452 pYesNo->m_aNoButton->Enable( bUpdatable );
2453 pNewLine->m_aYesNos.push_back( pYesNo );
2456 else if ( sType == CMIS_TYPE_STRING )
2458 Sequence< OUString > seqValue;
2459 rAny >>= seqValue;
2460 sal_Int32 m_nNumValue = seqValue.getLength( );
2461 for ( sal_Int32 i = 0; i < m_nNumValue; ++i )
2463 CmisValue* pValue = new CmisValue( m_pBox, seqValue[i] );
2464 pValue->m_aValueEdit->SetReadOnly( !bUpdatable );
2465 pNewLine->m_aValues.push_back( pValue );
2468 else if ( sType == CMIS_TYPE_DATETIME )
2470 Sequence< util::DateTime > seqValue;
2471 rAny >>= seqValue;
2472 sal_Int32 m_nNumValue = seqValue.getLength( );
2473 for ( sal_Int32 i = 0; i < m_nNumValue; ++i )
2475 CmisDateTime* pDateTime = new CmisDateTime( m_pBox, seqValue[i]);
2476 pDateTime->m_aDateField->SetReadOnly( !bUpdatable );
2477 pDateTime->m_aTimeField->SetReadOnly( !bUpdatable );
2478 pNewLine->m_aDateTimes.push_back( pDateTime );
2482 pNewLine->m_aName->SetText( sName );
2483 pNewLine->m_aName->Show( true );
2484 pNewLine->m_aType->SetText( sType );
2485 pNewLine->m_aType->Show( true );
2487 m_aCmisPropertiesLines.push_back( pNewLine );
2490 void CmisPropertiesWindow::DoScroll( sal_Int32 nNewPos )
2492 m_pBox->SetPosPixel(Point(0, nNewPos));
2495 Sequence< document::CmisProperty > CmisPropertiesWindow::GetCmisProperties() const
2497 Sequence< document::CmisProperty > aPropertiesSeq( m_aCmisPropertiesLines.size() );
2498 sal_Int32 i = 0;
2499 std::vector< CmisPropertyLine* >::const_iterator pIter;
2500 for ( pIter = m_aCmisPropertiesLines.begin();
2501 pIter != m_aCmisPropertiesLines.end(); ++pIter, ++i )
2503 CmisPropertyLine* pLine = *pIter;
2505 aPropertiesSeq[i].Id = pLine->m_sId;
2506 aPropertiesSeq[i].Type = pLine->m_sType;
2507 aPropertiesSeq[i].Updatable = pLine->m_bUpdatable;
2508 aPropertiesSeq[i].Required = pLine->m_bRequired;
2509 aPropertiesSeq[i].OpenChoice = pLine->m_bOpenChoice;
2510 aPropertiesSeq[i].MultiValued = pLine->m_bMultiValued;
2512 OUString sPropertyName = pLine->m_aName->GetText();
2513 if ( !sPropertyName.isEmpty() )
2515 aPropertiesSeq[i].Name = sPropertyName;
2516 OUString sType = pLine->m_aType->GetText( );
2517 if ( CMIS_TYPE_DECIMAL == sType )
2519 sal_uInt32 nIndex = const_cast< SvNumberFormatter& >(
2520 m_aNumberFormatter ).GetFormatIndex( NF_NUMBER_SYSTEM );
2521 Sequence< double > seqValue( pLine->m_aValues.size( ) );
2522 sal_Int32 k = 0;
2523 for ( std::vector< CmisValue*>::const_iterator it = pLine->m_aValues.begin();
2524 it != pLine->m_aValues.end(); ++it, ++k)
2526 double dValue = 0.0;
2527 OUString sValue( (*it)->m_aValueEdit->GetText() );
2528 bool bIsNum = const_cast< SvNumberFormatter& >( m_aNumberFormatter ).
2529 IsNumberFormat( sValue, nIndex, dValue );
2530 if ( bIsNum )
2531 seqValue[k] = dValue;
2533 aPropertiesSeq[i].Value <<= makeAny( seqValue );
2535 else if ( CMIS_TYPE_INTEGER == sType )
2537 sal_uInt32 nIndex = const_cast< SvNumberFormatter& >(
2538 m_aNumberFormatter ).GetFormatIndex( NF_NUMBER_SYSTEM );
2539 Sequence< sal_Int64 > seqValue( pLine->m_aValues.size( ) );
2540 sal_Int32 k = 0;
2541 for ( std::vector< CmisValue*>::const_iterator it = pLine->m_aValues.begin();
2542 it != pLine->m_aValues.end(); ++it, ++k)
2544 double dValue = 0;
2545 OUString sValue( (*it)->m_aValueEdit->GetText() );
2546 bool bIsNum = const_cast< SvNumberFormatter& >( m_aNumberFormatter ).
2547 IsNumberFormat( sValue, nIndex, dValue );
2548 if ( bIsNum )
2549 seqValue[k] = (sal_Int64) dValue;
2551 aPropertiesSeq[i].Value <<= makeAny( seqValue );
2553 else if ( CMIS_TYPE_BOOL == sType )
2555 Sequence<sal_Bool> seqValue( pLine->m_aYesNos.size( ) );
2556 sal_Int32 k = 0;
2557 for ( std::vector< CmisYesNo*>::const_iterator it = pLine->m_aYesNos.begin();
2558 it != pLine->m_aYesNos.end(); ++it, ++k)
2560 bool bValue = (*it)->m_aYesButton->IsChecked();
2561 seqValue[k] = bValue;
2563 aPropertiesSeq[i].Value <<= makeAny( seqValue );
2566 else if ( CMIS_TYPE_DATETIME == sType )
2568 Sequence< util::DateTime > seqValue( pLine->m_aDateTimes.size( ) );
2569 sal_Int32 k = 0;
2570 for ( std::vector< CmisDateTime*>::const_iterator it = pLine->m_aDateTimes.begin();
2571 it != pLine->m_aDateTimes.end(); ++it, ++k)
2573 Date aTmpDate = (*it)->m_aDateField->GetDate();
2574 tools::Time aTmpTime = (*it)->m_aTimeField->GetTime();
2575 util::DateTime aDateTime( aTmpTime.GetNanoSec(), aTmpTime.GetSec(),
2576 aTmpTime.GetMin(), aTmpTime.GetHour(),
2577 aTmpDate.GetDay(), aTmpDate.GetMonth(),
2578 aTmpDate.GetYear(), sal_True );
2579 seqValue[k] = aDateTime;
2581 aPropertiesSeq[i].Value <<= makeAny( seqValue );
2583 else
2585 Sequence< OUString > seqValue( pLine->m_aValues.size( ) );
2586 sal_Int32 k = 0;
2587 for ( std::vector< CmisValue*>::const_iterator it = pLine->m_aValues.begin();
2588 it != pLine->m_aValues.end(); ++it, ++k)
2590 OUString sValue( (*it)->m_aValueEdit->GetText() );
2591 seqValue[k] = sValue;
2593 aPropertiesSeq[i].Value <<= makeAny( seqValue );
2598 return aPropertiesSeq;
2601 CmisPropertiesControl::CmisPropertiesControl(SfxTabPage* pParent)
2602 : m_pPropertiesWin( pParent )
2603 , m_rScrolledWindow( *pParent->get<VclScrolledWindow>("CmisScroll"))
2604 , m_rVertScroll( m_rScrolledWindow.getVertScrollBar())
2606 m_rScrolledWindow.setUserManagedScrolling(true);
2607 m_rVertScroll.EnableDrag();
2608 m_rVertScroll.Show( m_rScrolledWindow.GetStyle() & WB_VSCROLL);
2609 m_rVertScroll.SetRangeMin(0);
2610 m_rVertScroll.SetVisibleSize( 0xFFFF );
2612 Link<> aScrollLink = LINK( this, CmisPropertiesControl, ScrollHdl );
2613 m_rVertScroll.SetScrollHdl( aScrollLink );
2616 void CmisPropertiesControl::ClearAllLines()
2618 m_pPropertiesWin.ClearAllLines();
2621 IMPL_LINK( CmisPropertiesControl, ScrollHdl, ScrollBar*, pScrollBar )
2623 sal_Int32 nOffset = m_pPropertiesWin.GetItemHeight();
2624 nOffset *= ( pScrollBar->GetThumbPos() );
2625 m_pPropertiesWin.DoScroll( -nOffset );
2626 return 0;
2629 void CmisPropertiesControl::checkAutoVScroll()
2631 WinBits nBits = m_rScrolledWindow.GetStyle();
2632 if (nBits & WB_VSCROLL)
2633 return;
2634 if (nBits & WB_AUTOVSCROLL)
2636 bool bShow = m_rVertScroll.GetRangeMax() > m_rVertScroll.GetVisibleSize();
2637 if (bShow != m_rVertScroll.IsVisible())
2638 m_rVertScroll.Show(bShow);
2642 void CmisPropertiesControl::setScrollRange()
2644 sal_Int32 nScrollOffset = m_pPropertiesWin.GetItemHeight();
2645 sal_Int32 nVisibleItems = m_rScrolledWindow.getVisibleChildSize().Height() / nScrollOffset;
2646 m_rVertScroll.SetPageSize( nVisibleItems - 1 );
2647 m_rVertScroll.SetVisibleSize( nVisibleItems );
2648 m_rVertScroll.Scroll();
2649 checkAutoVScroll();
2652 void CmisPropertiesControl::AddLine( const OUString& sId, const OUString& sName,
2653 const OUString& sType, const bool bUpdatable,
2654 const bool bRequired, const bool bMultiValued,
2655 const bool bOpenChoice, Any& aChoices, Any& rAny
2658 m_rVertScroll.SetRangeMax( m_pPropertiesWin.GetLineCount() + 1 );
2659 m_rVertScroll.DoScroll( m_pPropertiesWin.GetLineCount() + 1 );
2660 m_pPropertiesWin.AddLine( sId, sName, sType, bUpdatable, bRequired, bMultiValued,
2661 bOpenChoice, aChoices, rAny );
2662 checkAutoVScroll();
2665 // class SfxCmisPropertiesPage -----------------------------------------
2666 SfxCmisPropertiesPage::SfxCmisPropertiesPage( vcl::Window* pParent, const SfxItemSet& rItemSet )
2667 : SfxTabPage(pParent, "CmisInfoPage", "sfx/ui/cmisinfopage.ui", &rItemSet)
2668 , m_pPropertiesCtrl( this )
2672 bool SfxCmisPropertiesPage::FillItemSet( SfxItemSet* rSet )
2674 const SfxPoolItem* pItem = NULL;
2675 SfxDocumentInfoItem* pInfo = NULL;
2676 bool bMustDelete = false;
2678 if ( GetTabDialog() && GetTabDialog()->GetExampleSet() )
2680 if ( SfxItemState::SET !=
2681 GetTabDialog()->GetExampleSet()->GetItemState( SID_DOCINFO, true, &pItem ) )
2682 pInfo = const_cast<SfxDocumentInfoItem*>(&static_cast<const SfxDocumentInfoItem& >(rSet->Get( SID_DOCINFO )));
2683 else
2685 bMustDelete = true;
2686 pInfo = new SfxDocumentInfoItem( *static_cast<const SfxDocumentInfoItem*>(pItem) );
2690 sal_Int32 modifiedNum = 0;
2691 if ( pInfo )
2693 Sequence< document::CmisProperty > aOldProps = pInfo->GetCmisProperties( );
2694 Sequence< document::CmisProperty > aNewProps = m_pPropertiesCtrl.GetCmisProperties();
2696 std::vector< document::CmisProperty > changedProps;
2697 for ( sal_Int32 i = 0; i< aNewProps.getLength( ); ++i )
2699 if ( aOldProps[i].Updatable && !aNewProps[i].Id.isEmpty( ) )
2701 if ( aOldProps[i].Type == CMIS_TYPE_DATETIME )
2703 Sequence< util::DateTime > oldValue;
2704 aOldProps[i].Value >>= oldValue;
2705 // We only edit hours and minutes
2706 // don't compare NanoSeconds and Seconds
2707 for ( sal_Int32 ii = 0; ii < oldValue.getLength( ); ++ii )
2709 oldValue[ii].NanoSeconds = 0;
2710 oldValue[ii].Seconds = 0;
2712 Sequence< util::DateTime > newValue;
2713 aNewProps[i].Value >>= newValue;
2714 if ( oldValue != newValue )
2716 modifiedNum++;
2717 changedProps.push_back( aNewProps[i] );
2720 else if ( aOldProps[i].Value != aNewProps[i].Value )
2722 modifiedNum++;
2723 changedProps.push_back( aNewProps[i] );
2727 Sequence< document::CmisProperty> aModifiedProps( modifiedNum );
2728 sal_Int32 nCount = 0;
2729 for( std::vector< document::CmisProperty>::const_iterator pIter = changedProps.begin();
2730 pIter != changedProps.end( ); ++pIter )
2731 aModifiedProps[ nCount++ ] = *pIter;
2732 pInfo->SetCmisProperties( aModifiedProps );
2733 rSet->Put( *pInfo );
2734 if ( bMustDelete )
2735 delete pInfo;
2738 return modifiedNum;
2741 void SfxCmisPropertiesPage::Reset( const SfxItemSet* rItemSet )
2743 m_pPropertiesCtrl.ClearAllLines();
2744 const SfxDocumentInfoItem& rInfoItem = static_cast<const SfxDocumentInfoItem& >(rItemSet->Get(SID_DOCINFO));
2745 uno::Sequence< document::CmisProperty > aCmisProps = rInfoItem.GetCmisProperties();
2746 for ( sal_Int32 i = 0; i < aCmisProps.getLength(); i++ )
2748 m_pPropertiesCtrl.AddLine( aCmisProps[i].Id,
2749 aCmisProps[i].Name,
2750 aCmisProps[i].Type,
2751 aCmisProps[i].Updatable,
2752 aCmisProps[i].Required,
2753 aCmisProps[i].MultiValued,
2754 aCmisProps[i].OpenChoice,
2755 aCmisProps[i].Choices,
2756 aCmisProps[i].Value );
2758 m_pPropertiesCtrl.setScrollRange();
2761 SfxTabPage::sfxpg SfxCmisPropertiesPage::DeactivatePage( SfxItemSet* /*pSet*/ )
2763 return LEAVE_PAGE;
2766 VclPtr<SfxTabPage> SfxCmisPropertiesPage::Create( vcl::Window* pParent, const SfxItemSet* rItemSet )
2768 return VclPtr<SfxCmisPropertiesPage>::Create( pParent, *rItemSet );
2771 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */