Bump version to 4.1-6
[LibreOffice.git] / sfx2 / source / dialog / dinfdlg.cxx
blobfd4b537510b3754c8ecb4e51d029ff78024898db
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/msgbox.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/Time.hpp>
45 #include <com/sun/star/util/Duration.hpp>
46 #include <com/sun/star/document/XDocumentProperties.hpp>
48 #include <vcl/timer.hxx>
49 #include "sfx2/dinfdlg.hxx"
50 #include "sfx2/securitypage.hxx"
51 #include "sfxresid.hxx"
52 #include "dinfedt.hxx"
53 #include <sfx2/frame.hxx>
54 #include <sfx2/viewfrm.hxx>
55 #include <sfx2/request.hxx>
56 #include <sfx2/passwd.hxx>
57 #include <sfx2/filedlghelper.hxx>
58 #include "helper.hxx"
59 #include <sfx2/objsh.hxx>
60 #include <sfx2/docfile.hxx>
61 #include <comphelper/storagehelper.hxx>
63 #include "documentfontsdialog.hxx"
64 #include <sfx2/sfx.hrc>
65 #include "dinfdlg.hrc"
66 #include "../appl/app.hrc"
67 #include "sfxlocal.hrc"
68 #include <dialog.hrc>
69 #include <vcl/help.hxx>
71 #include <algorithm>
73 using namespace ::com::sun::star;
74 using namespace ::com::sun::star::lang;
75 using namespace ::com::sun::star::ui::dialogs;
76 using namespace ::com::sun::star::uno;
78 const sal_uInt16 FONT_PAGE_ID = 99;
80 struct CustomProperty
82 OUString m_sName;
83 com::sun::star::uno::Any m_aValue;
85 CustomProperty( const OUString& sName,
86 const com::sun::star::uno::Any& rValue ) :
87 m_sName( sName ), m_aValue( rValue ) {}
89 inline bool operator==( const CustomProperty& rProp )
90 { return m_sName.equals( rProp.m_sName ) && m_aValue == rProp.m_aValue; }
93 static
94 bool operator==(const util::DateTime &i_rLeft, const util::DateTime &i_rRight)
96 return i_rLeft.Year == i_rRight.Year
97 && i_rLeft.Month == i_rRight.Month
98 && i_rLeft.Day == i_rRight.Day
99 && i_rLeft.Hours == i_rRight.Hours
100 && i_rLeft.Minutes == i_rRight.Minutes
101 && i_rLeft.Seconds == i_rRight.Seconds
102 && i_rLeft.NanoSeconds == i_rRight.NanoSeconds
103 && i_rLeft.IsUTC == i_rRight.IsUTC;
106 // STATIC DATA -----------------------------------------------------------
107 TYPEINIT1_AUTOFACTORY(SfxDocumentInfoItem, SfxStringItem);
109 const sal_uInt16 HI_NAME = 1;
110 const sal_uInt16 HI_TYPE = 2;
111 const sal_uInt16 HI_VALUE = 3;
112 const sal_uInt16 HI_ACTION = 4;
114 static const char DOCUMENT_SIGNATURE_MENU_CMD[] = "Signature";
116 //------------------------------------------------------------------------
117 namespace {
119 String CreateSizeText( sal_Int64 nSize )
121 String aUnitStr = OUString(' ');
122 aUnitStr += SfxResId(STR_BYTES).toString();
123 sal_Int64 nSize1 = nSize;
124 sal_Int64 nSize2 = nSize1;
125 sal_Int64 nMega = 1024 * 1024;
126 sal_Int64 nGiga = nMega * 1024;
127 double fSize = nSize;
128 int nDec = 0;
130 if ( nSize1 >= 10000 && nSize1 < nMega )
132 nSize1 /= 1024;
133 aUnitStr = ' ';
134 aUnitStr += SfxResId(STR_KB).toString();
135 fSize /= 1024;
136 nDec = 0;
138 else if ( nSize1 >= nMega && nSize1 < nGiga )
140 nSize1 /= nMega;
141 aUnitStr = ' ';
142 aUnitStr += SfxResId(STR_MB).toString();
143 fSize /= nMega;
144 nDec = 2;
146 else if ( nSize1 >= nGiga )
148 nSize1 /= nGiga;
149 aUnitStr = ' ';
150 aUnitStr += SfxResId(STR_GB).toString();
151 fSize /= nGiga;
152 nDec = 3;
154 const SvtSysLocale aSysLocale;
155 const LocaleDataWrapper& rLocaleWrapper = aSysLocale.GetLocaleData();
156 String aSizeStr( rLocaleWrapper.getNum( nSize1, 0 ) );
157 aSizeStr += aUnitStr;
158 if ( nSize1 < nSize2 )
160 aSizeStr = ::rtl::math::doubleToUString( fSize,
161 rtl_math_StringFormat_F, nDec,
162 rLocaleWrapper.getNumDecimalSep()[0] );
163 aSizeStr += aUnitStr;
165 aSizeStr += " (";
166 aSizeStr += rLocaleWrapper.getNum( nSize2, 0 );
167 aSizeStr += ' ';
168 aSizeStr += SfxResId(STR_BYTES).toString();
169 aSizeStr += ')';
171 return aSizeStr;
174 String ConvertDateTime_Impl( const String& rName,
175 const util::DateTime& uDT, const LocaleDataWrapper& rWrapper )
177 Date aD(uDT.Day, uDT.Month, uDT.Year);
178 Time aT(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.NanoSeconds);
179 const String pDelim ( ", " );
180 String aStr( rWrapper.getDate( aD ) );
181 aStr += pDelim;
182 aStr += rWrapper.getTime( aT, sal_True, sal_False );
183 OUString aAuthor = comphelper::string::stripStart(rName, ' ');
184 if (!aAuthor.isEmpty())
186 aStr += pDelim;
187 aStr += aAuthor;
189 return aStr;
193 //------------------------------------------------------------------------
195 SfxDocumentInfoItem::SfxDocumentInfoItem()
196 : SfxStringItem()
197 , m_AutoloadDelay(0)
198 , m_AutoloadURL()
199 , m_isAutoloadEnabled(sal_False)
200 , m_DefaultTarget()
201 , m_TemplateName()
202 , m_Author()
203 , m_CreationDate()
204 , m_ModifiedBy()
205 , m_ModificationDate()
206 , m_PrintedBy()
207 , m_PrintDate()
208 , m_EditingCycles(0)
209 , m_EditingDuration(0)
210 , m_Description()
211 , m_Keywords()
212 , m_Subject()
213 , m_Title()
214 , m_bHasTemplate( sal_True )
215 , m_bDeleteUserData( sal_False )
216 , m_bUseUserData( sal_True )
220 //------------------------------------------------------------------------
222 SfxDocumentInfoItem::SfxDocumentInfoItem( const String& rFile,
223 const uno::Reference<document::XDocumentProperties>& i_xDocProps,
224 sal_Bool bIs )
225 : SfxStringItem( SID_DOCINFO, rFile )
226 , m_AutoloadDelay( i_xDocProps->getAutoloadSecs() )
227 , m_AutoloadURL( i_xDocProps->getAutoloadURL() )
228 , m_isAutoloadEnabled( (m_AutoloadDelay > 0) || !m_AutoloadURL.isEmpty() )
229 , m_DefaultTarget( i_xDocProps->getDefaultTarget() )
230 , m_TemplateName( i_xDocProps->getTemplateName() )
231 , m_Author( i_xDocProps->getAuthor() )
232 , m_CreationDate( i_xDocProps->getCreationDate() )
233 , m_ModifiedBy( i_xDocProps->getModifiedBy() )
234 , m_ModificationDate( i_xDocProps->getModificationDate() )
235 , m_PrintedBy( i_xDocProps->getPrintedBy() )
236 , m_PrintDate( i_xDocProps->getPrintDate() )
237 , m_EditingCycles( i_xDocProps->getEditingCycles() )
238 , m_EditingDuration( i_xDocProps->getEditingDuration() )
239 , m_Description( i_xDocProps->getDescription() )
240 , m_Keywords( ::comphelper::string::convertCommaSeparated(
241 i_xDocProps->getKeywords()) )
242 , m_Subject( i_xDocProps->getSubject() )
243 , m_Title( i_xDocProps->getTitle() )
244 , m_bHasTemplate( sal_True )
245 , m_bDeleteUserData( sal_False )
246 , m_bUseUserData( bIs )
250 Reference< beans::XPropertyContainer > xContainer = i_xDocProps->getUserDefinedProperties();
251 if ( xContainer.is() )
253 Reference < beans::XPropertySet > xSet( xContainer, UNO_QUERY );
254 const Sequence< beans::Property > lProps = xSet->getPropertySetInfo()->getProperties();
255 const beans::Property* pProps = lProps.getConstArray();
256 sal_Int32 nCount = lProps.getLength();
257 for ( sal_Int32 i = 0; i < nCount; ++i )
259 // "fix" property? => not a custom property => ignore it!
260 if (!(pProps[i].Attributes &
261 ::com::sun::star::beans::PropertyAttribute::REMOVABLE))
263 DBG_ASSERT(false, "non-removable user-defined property?");
264 continue;
267 uno::Any aValue = xSet->getPropertyValue(pProps[i].Name);
268 CustomProperty* pProp = new CustomProperty( pProps[i].Name, aValue );
269 m_aCustomProperties.push_back( pProp );
273 catch ( Exception& ) {}
276 //------------------------------------------------------------------------
278 SfxDocumentInfoItem::SfxDocumentInfoItem( const SfxDocumentInfoItem& rItem )
279 : SfxStringItem( rItem )
280 , m_AutoloadDelay( rItem.getAutoloadDelay() )
281 , m_AutoloadURL( rItem.getAutoloadURL() )
282 , m_isAutoloadEnabled( rItem.isAutoloadEnabled() )
283 , m_DefaultTarget( rItem.getDefaultTarget() )
284 , m_TemplateName( rItem.getTemplateName() )
285 , m_Author( rItem.getAuthor() )
286 , m_CreationDate( rItem.getCreationDate() )
287 , m_ModifiedBy( rItem.getModifiedBy() )
288 , m_ModificationDate( rItem.getModificationDate() )
289 , m_PrintedBy( rItem.getPrintedBy() )
290 , m_PrintDate( rItem.getPrintDate() )
291 , m_EditingCycles( rItem.getEditingCycles() )
292 , m_EditingDuration( rItem.getEditingDuration() )
293 , m_Description( rItem.getDescription() )
294 , m_Keywords( rItem.getKeywords() )
295 , m_Subject( rItem.getSubject() )
296 , m_Title( rItem.getTitle() )
297 , m_bHasTemplate( rItem.m_bHasTemplate )
298 , m_bDeleteUserData( rItem.m_bDeleteUserData )
299 , m_bUseUserData( rItem.m_bUseUserData )
301 for ( sal_uInt32 i = 0; i < rItem.m_aCustomProperties.size(); i++ )
303 CustomProperty* pProp = new CustomProperty( rItem.m_aCustomProperties[i]->m_sName,
304 rItem.m_aCustomProperties[i]->m_aValue );
305 m_aCustomProperties.push_back( pProp );
309 //------------------------------------------------------------------------
310 SfxDocumentInfoItem::~SfxDocumentInfoItem()
312 ClearCustomProperties();
315 //------------------------------------------------------------------------
316 SfxPoolItem* SfxDocumentInfoItem::Clone( SfxItemPool * ) const
318 return new SfxDocumentInfoItem( *this );
321 //------------------------------------------------------------------------
322 int SfxDocumentInfoItem::operator==( const SfxPoolItem& rItem) const
324 if (!(rItem.Type() == Type() && SfxStringItem::operator==(rItem)))
325 return false;
326 const SfxDocumentInfoItem& rInfoItem(static_cast<const SfxDocumentInfoItem&>(rItem));
328 return
329 m_AutoloadDelay == rInfoItem.m_AutoloadDelay &&
330 m_AutoloadURL == rInfoItem.m_AutoloadURL &&
331 m_isAutoloadEnabled == rInfoItem.m_isAutoloadEnabled &&
332 m_DefaultTarget == rInfoItem.m_DefaultTarget &&
333 m_Author == rInfoItem.m_Author &&
334 m_CreationDate == rInfoItem.m_CreationDate &&
335 m_ModifiedBy == rInfoItem.m_ModifiedBy &&
336 m_ModificationDate == rInfoItem.m_ModificationDate &&
337 m_PrintedBy == rInfoItem.m_PrintedBy &&
338 m_PrintDate == rInfoItem.m_PrintDate &&
339 m_EditingCycles == rInfoItem.m_EditingCycles &&
340 m_EditingDuration == rInfoItem.m_EditingDuration &&
341 m_Description == rInfoItem.m_Description &&
342 m_Keywords == rInfoItem.m_Keywords &&
343 m_Subject == rInfoItem.m_Subject &&
344 m_Title == rInfoItem.m_Title &&
345 m_aCustomProperties.size() == rInfoItem.m_aCustomProperties.size() &&
346 std::equal(m_aCustomProperties.begin(), m_aCustomProperties.end(),
347 rInfoItem.m_aCustomProperties.begin());
350 //------------------------------------------------------------------------
351 void SfxDocumentInfoItem::resetUserData(const OUString & i_rAuthor)
353 setAuthor(i_rAuthor);
354 DateTime now( DateTime::SYSTEM );
355 setCreationDate( util::DateTime(
356 now.GetNanoSec(), now.GetSec(), now.GetMin(), now.GetHour(),
357 now.GetDay(), now.GetMonth(), now.GetYear(), false) );
358 setModifiedBy(OUString());
359 setPrintedBy(OUString());
360 setModificationDate(util::DateTime());
361 setPrintDate(util::DateTime());
362 setEditingDuration(0);
363 setEditingCycles(1);
366 //------------------------------------------------------------------------
367 void SfxDocumentInfoItem::UpdateDocumentInfo(
368 const uno::Reference<document::XDocumentProperties>& i_xDocProps,
369 bool i_bDoNotUpdateUserDefined) const
371 if (isAutoloadEnabled()) {
372 i_xDocProps->setAutoloadSecs(getAutoloadDelay());
373 i_xDocProps->setAutoloadURL(getAutoloadURL());
374 } else {
375 i_xDocProps->setAutoloadSecs(0);
376 i_xDocProps->setAutoloadURL(OUString());
378 i_xDocProps->setDefaultTarget(getDefaultTarget());
379 i_xDocProps->setAuthor(getAuthor());
380 i_xDocProps->setCreationDate(getCreationDate());
381 i_xDocProps->setModifiedBy(getModifiedBy());
382 i_xDocProps->setModificationDate(getModificationDate());
383 i_xDocProps->setPrintedBy(getPrintedBy());
384 i_xDocProps->setPrintDate(getPrintDate());
385 i_xDocProps->setEditingCycles(getEditingCycles());
386 i_xDocProps->setEditingDuration(getEditingDuration());
387 i_xDocProps->setDescription(getDescription());
388 i_xDocProps->setKeywords(
389 ::comphelper::string::convertCommaSeparated(getKeywords()));
390 i_xDocProps->setSubject(getSubject());
391 i_xDocProps->setTitle(getTitle());
393 // this is necessary in case of replaying a recorded macro:
394 // in this case, the macro may contain the 4 old user-defined DocumentInfo
395 // fields, but not any of the DocumentInfo properties;
396 // as a consequence, most of the UserDefined properties of the
397 // DocumentProperties would be summarily deleted here, which does not
398 // seem like a good idea.
399 if (i_bDoNotUpdateUserDefined)
400 return;
404 Reference< beans::XPropertyContainer > xContainer = i_xDocProps->getUserDefinedProperties();
405 Reference < beans::XPropertySet > xSet( xContainer, UNO_QUERY );
406 Reference< beans::XPropertySetInfo > xSetInfo = xSet->getPropertySetInfo();
407 const Sequence< beans::Property > lProps = xSetInfo->getProperties();
408 const beans::Property* pProps = lProps.getConstArray();
409 sal_Int32 nCount = lProps.getLength();
410 for ( sal_Int32 j = 0; j < nCount; ++j )
412 if ((pProps[j].Attributes &
413 ::com::sun::star::beans::PropertyAttribute::REMOVABLE))
415 xContainer->removeProperty( pProps[j].Name );
419 for ( sal_uInt32 k = 0; k < m_aCustomProperties.size(); ++k )
423 xContainer->addProperty( m_aCustomProperties[k]->m_sName,
424 beans::PropertyAttribute::REMOVABLE, m_aCustomProperties[k]->m_aValue );
426 catch ( Exception& )
428 SAL_WARN( "sfx2.dialog", "SfxDocumentInfoItem::updateDocumentInfo(): exception while adding custom properties" );
432 catch ( Exception& )
434 SAL_WARN( "sfx2.dialog", "SfxDocumentInfoItem::updateDocumentInfo(): exception while removing custom properties" );
438 //------------------------------------------------------------------------
439 sal_Bool SfxDocumentInfoItem::IsDeleteUserData() const
441 return m_bDeleteUserData;
444 void SfxDocumentInfoItem::SetDeleteUserData( sal_Bool bSet )
446 m_bDeleteUserData = bSet;
449 sal_Bool SfxDocumentInfoItem::IsUseUserData() const
451 return m_bUseUserData;
454 void SfxDocumentInfoItem::SetUseUserData( sal_Bool bSet )
456 m_bUseUserData = bSet;
459 std::vector< CustomProperty* > SfxDocumentInfoItem::GetCustomProperties() const
461 std::vector< CustomProperty* > aRet;
462 for ( sal_uInt32 i = 0; i < m_aCustomProperties.size(); i++ )
464 CustomProperty* pProp = new CustomProperty( m_aCustomProperties[i]->m_sName,
465 m_aCustomProperties[i]->m_aValue );
466 aRet.push_back( pProp );
469 return aRet;
472 void SfxDocumentInfoItem::ClearCustomProperties()
474 for ( sal_uInt32 i = 0; i < m_aCustomProperties.size(); i++ )
475 delete m_aCustomProperties[i];
476 m_aCustomProperties.clear();
479 void SfxDocumentInfoItem::AddCustomProperty( const OUString& sName, const Any& rValue )
481 CustomProperty* pProp = new CustomProperty( sName, rValue );
482 m_aCustomProperties.push_back( pProp );
485 bool SfxDocumentInfoItem::QueryValue( Any& rVal, sal_uInt8 nMemberId ) const
487 String aValue;
488 sal_Int32 nValue = 0;
489 sal_Bool bValue = sal_False;
490 sal_Bool bIsInt = sal_False;
491 sal_Bool bIsString = sal_False;
492 nMemberId &= ~CONVERT_TWIPS;
493 switch ( nMemberId )
495 case MID_DOCINFO_USEUSERDATA:
496 bValue = IsUseUserData();
497 break;
498 case MID_DOCINFO_DELETEUSERDATA:
499 bValue = IsDeleteUserData();
500 break;
501 case MID_DOCINFO_AUTOLOADENABLED:
502 bValue = isAutoloadEnabled();
503 break;
504 case MID_DOCINFO_AUTOLOADSECS:
505 bIsInt = sal_True;
506 nValue = getAutoloadDelay();
507 break;
508 case MID_DOCINFO_AUTOLOADURL:
509 bIsString = sal_True;
510 aValue = getAutoloadURL();
511 break;
512 case MID_DOCINFO_DEFAULTTARGET:
513 bIsString = sal_True;
514 aValue = getDefaultTarget();
515 break;
516 case MID_DOCINFO_DESCRIPTION:
517 bIsString = sal_True;
518 aValue = getDescription();
519 break;
520 case MID_DOCINFO_KEYWORDS:
521 bIsString = sal_True;
522 aValue = getKeywords();
523 break;
524 case MID_DOCINFO_SUBJECT:
525 bIsString = sal_True;
526 aValue = getSubject();
527 break;
528 case MID_DOCINFO_TITLE:
529 bIsString = sal_True;
530 aValue = getTitle();
531 break;
532 default:
533 OSL_FAIL("Wrong MemberId!");
534 return sal_False;
537 if ( bIsString )
538 rVal <<= OUString( aValue );
539 else if ( bIsInt )
540 rVal <<= nValue;
541 else
542 rVal <<= bValue;
543 return true;
546 bool SfxDocumentInfoItem::PutValue( const Any& rVal, sal_uInt8 nMemberId )
548 OUString aValue;
549 sal_Int32 nValue=0;
550 sal_Bool bValue = sal_False;
551 bool bRet = false;
552 nMemberId &= ~CONVERT_TWIPS;
553 switch ( nMemberId )
555 case MID_DOCINFO_USEUSERDATA:
556 bRet = (rVal >>= bValue);
557 if ( bRet )
558 SetUseUserData( bValue );
559 break;
560 case MID_DOCINFO_DELETEUSERDATA:
561 // QUESTION: deleting user data was done here; seems to be superfluous!
562 bRet = (rVal >>= bValue);
563 if ( bRet )
564 SetDeleteUserData( bValue );
565 break;
566 case MID_DOCINFO_AUTOLOADENABLED:
567 bRet = (rVal >>= bValue);
568 if ( bRet )
569 setAutoloadEnabled(bValue);
570 break;
571 case MID_DOCINFO_AUTOLOADSECS:
572 bRet = (rVal >>= nValue);
573 if ( bRet )
574 setAutoloadDelay(nValue);
575 break;
576 case MID_DOCINFO_AUTOLOADURL:
577 bRet = (rVal >>= aValue);
578 if ( bRet )
579 setAutoloadURL(aValue);
580 break;
581 case MID_DOCINFO_DEFAULTTARGET:
582 bRet = (rVal >>= aValue);
583 if ( bRet )
584 setDefaultTarget(aValue);
585 break;
586 case MID_DOCINFO_DESCRIPTION:
587 bRet = (rVal >>= aValue);
588 if ( bRet )
589 setDescription(aValue);
590 break;
591 case MID_DOCINFO_KEYWORDS:
592 bRet = (rVal >>= aValue);
593 if ( bRet )
594 setKeywords(aValue);
595 break;
596 case MID_DOCINFO_SUBJECT:
597 bRet = (rVal >>= aValue);
598 if ( bRet )
599 setSubject(aValue);
600 break;
601 case MID_DOCINFO_TITLE:
602 bRet = (rVal >>= aValue);
603 if ( bRet )
604 setTitle(aValue);
605 break;
606 default:
607 OSL_FAIL("Wrong MemberId!");
608 return false;
611 return bRet;
614 //------------------------------------------------------------------------
615 SfxDocumentDescPage::SfxDocumentDescPage( Window * pParent, const SfxItemSet& rItemSet )
616 : SfxTabPage(pParent, "DescriptionInfoPage", "sfx/ui/descriptioninfopage.ui", rItemSet)
617 , m_pInfoItem ( NULL )
620 get(m_pTitleEd, "title");
621 get(m_pThemaEd, "subject");
622 get(m_pKeywordsEd, "keywords");
623 get(m_pCommentEd, "comments");
626 //------------------------------------------------------------------------
627 SfxTabPage *SfxDocumentDescPage::Create(Window *pParent, const SfxItemSet &rItemSet)
629 return new SfxDocumentDescPage(pParent, rItemSet);
632 //------------------------------------------------------------------------
633 sal_Bool SfxDocumentDescPage::FillItemSet(SfxItemSet &rSet)
635 // Test whether a change is present
636 const sal_Bool bTitleMod = m_pTitleEd->IsModified();
637 const sal_Bool bThemeMod = m_pThemaEd->IsModified();
638 const sal_Bool bKeywordsMod = m_pKeywordsEd->IsModified();
639 const sal_Bool bCommentMod = m_pCommentEd->IsModified();
640 if ( !( bTitleMod || bThemeMod || bKeywordsMod || bCommentMod ) )
642 return sal_False;
645 // Generating the output data
646 const SfxPoolItem* pItem = NULL;
647 SfxDocumentInfoItem* pInfo = NULL;
648 SfxTabDialog* pDlg = GetTabDialog();
649 const SfxItemSet* pExSet = NULL;
651 if ( pDlg )
652 pExSet = pDlg->GetExampleSet();
654 if ( pExSet && SFX_ITEM_SET != pExSet->GetItemState( SID_DOCINFO, sal_True, &pItem ) )
655 pInfo = m_pInfoItem;
656 else if ( pItem )
657 pInfo = new SfxDocumentInfoItem( *(const SfxDocumentInfoItem *)pItem );
659 if ( !pInfo )
661 SAL_WARN( "sfx2.dialog", "SfxDocumentDescPage::FillItemSet(): no item found" );
662 return sal_False;
665 if ( bTitleMod )
667 pInfo->setTitle( m_pTitleEd->GetText() );
669 if ( bThemeMod )
671 pInfo->setSubject( m_pThemaEd->GetText() );
673 if ( bKeywordsMod )
675 pInfo->setKeywords( m_pKeywordsEd->GetText() );
677 if ( bCommentMod )
679 pInfo->setDescription( m_pCommentEd->GetText() );
681 rSet.Put( SfxDocumentInfoItem( *pInfo ) );
682 if ( pInfo != m_pInfoItem )
684 delete pInfo;
687 return sal_True;
690 //------------------------------------------------------------------------
691 void SfxDocumentDescPage::Reset(const SfxItemSet &rSet)
693 m_pInfoItem = &(SfxDocumentInfoItem &)rSet.Get(SID_DOCINFO);
695 m_pTitleEd->SetText( m_pInfoItem->getTitle() );
696 m_pThemaEd->SetText( m_pInfoItem->getSubject() );
697 m_pKeywordsEd->SetText( m_pInfoItem->getKeywords() );
698 m_pCommentEd->SetText( m_pInfoItem->getDescription() );
700 SFX_ITEMSET_ARG( &rSet, pROItem, SfxBoolItem, SID_DOC_READONLY, sal_False );
701 if ( pROItem && pROItem->GetValue() )
703 m_pTitleEd->SetReadOnly( sal_True );
704 m_pThemaEd->SetReadOnly( sal_True );
705 m_pKeywordsEd->SetReadOnly( sal_True );
706 m_pCommentEd->SetReadOnly( sal_True );
710 //------------------------------------------------------------------------
711 namespace
713 String GetDateTimeString( sal_Int32 _nDate, sal_Int32 _nTime )
715 const LocaleDataWrapper& rWrapper( Application::GetSettings().GetLocaleDataWrapper() );
717 Date aDate( _nDate );
718 Time aTime( _nTime );
719 String aStr( rWrapper.getDate( aDate ) );
720 aStr.AppendAscii( ", " );
721 aStr += rWrapper.getTime( aTime );
722 return aStr;
725 // copy from xmlsecurity/source/dialog/resourcemanager.cxx
726 String GetContentPart( const String& _rRawString, const String& _rPartId )
728 String s;
730 xub_StrLen nContStart = _rRawString.Search( _rPartId );
731 if ( nContStart != STRING_NOTFOUND )
733 nContStart = nContStart + _rPartId.Len();
734 ++nContStart; // now it's start of content, directly after Id
736 xub_StrLen nContEnd = _rRawString.Search( sal_Unicode( ',' ), nContStart );
738 s = String( _rRawString, nContStart, nContEnd - nContStart );
741 return s;
745 SfxDocumentPage::SfxDocumentPage(Window* pParent, const SfxItemSet& rItemSet)
746 : SfxTabPage(pParent, "DocumentInfoPage", "sfx/ui/documentinfopage.ui", rItemSet)
747 , bEnableUseUserData( sal_False )
748 , bHandleDelete( sal_False )
750 get(m_pBmp, "icon");
751 get(m_pNameED, "nameed");
752 //FIXME m_pNameED->SetAccessibleName( SfxResId( EDIT_FILE_NAME ).toString() );
753 get(m_pChangePassBtn, "changepass");
755 get(m_pShowTypeFT, "showtype");
756 get(m_pReadOnlyCB, "readonlycb");
757 get(m_pFileValFt, "showlocation");
758 get(m_pShowSizeFT, "showsize");
759 m_aUnknownSize = m_pShowSizeFT->GetText();
760 m_pShowSizeFT->SetText(OUString());
762 get(m_pCreateValFt, "showcreate");
763 get(m_pChangeValFt, "showmodify");
764 get(m_pSignedValFt, "showsigned");
765 m_aMultiSignedStr = m_pSignedValFt->GetText();
766 m_pSignedValFt->SetText(OUString());
767 get(m_pSignatureBtn, "signature");
768 get(m_pPrintValFt, "showprint");
769 get(m_pTimeLogValFt, "showedittime");
770 get(m_pDocNoValFt, "showrevision");
772 get(m_pUseUserDataCB, "userdatacb");
773 get(m_pDeleteBtn, "reset");
775 get(m_pTemplFt, "templateft");
776 get(m_pTemplValFt, "showtemplate");
778 ImplUpdateSignatures();
779 ImplCheckPasswordState();
780 m_pChangePassBtn->SetClickHdl( LINK( this, SfxDocumentPage, ChangePassHdl ) );
781 m_pSignatureBtn->SetClickHdl( LINK( this, SfxDocumentPage, SignatureHdl ) );
782 m_pDeleteBtn->SetClickHdl( LINK( this, SfxDocumentPage, DeleteHdl ) );
784 // [i96288] Check if the document signature command is enabled
785 // on the main list enable/disable the pushbutton accordingly
786 SvtCommandOptions aCmdOptions;
787 if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED,
788 OUString( RTL_CONSTASCII_USTRINGPARAM( DOCUMENT_SIGNATURE_MENU_CMD ) ) ) )
789 m_pSignatureBtn->Disable();
792 //------------------------------------------------------------------------
794 IMPL_LINK_NOARG(SfxDocumentPage, DeleteHdl)
796 String aName;
797 if ( bEnableUseUserData && m_pUseUserDataCB->IsChecked() )
798 aName = SvtUserOptions().GetFullName();
799 const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
800 DateTime now( DateTime::SYSTEM );
801 util::DateTime uDT(
802 now.GetNanoSec(), now.GetSec(), now.GetMin(), now.GetHour(),
803 now.GetDay(), now.GetMonth(), now.GetYear(), false);
804 m_pCreateValFt->SetText( ConvertDateTime_Impl( aName, uDT, rLocaleWrapper ) );
805 OUString aEmpty;
806 m_pChangeValFt->SetText( aEmpty );
807 m_pPrintValFt->SetText( aEmpty );
808 const Time aTime( 0 );
809 m_pTimeLogValFt->SetText( rLocaleWrapper.getDuration( aTime ) );
810 m_pDocNoValFt->SetText(OUString('1'));
811 bHandleDelete = sal_True;
812 return 0;
815 IMPL_LINK_NOARG(SfxDocumentPage, SignatureHdl)
817 SfxObjectShell* pDoc = SfxObjectShell::Current();
818 if( pDoc )
820 pDoc->SignDocumentContent();
822 ImplUpdateSignatures();
825 return 0;
828 IMPL_LINK_NOARG(SfxDocumentPage, ChangePassHdl)
830 SfxObjectShell* pShell = SfxObjectShell::Current();
833 if (!pShell)
834 break;
835 SfxItemSet* pMedSet = pShell->GetMedium()->GetItemSet();
836 if (!pMedSet)
837 break;
838 const SfxFilter* pFilter = pShell->GetMedium()->GetFilter();
839 if (!pFilter)
840 break;
842 OUString aDocName;
843 sfx2::RequestPassword(pFilter, aDocName, pMedSet);
844 pShell->SetModified(true);
846 while (false);
847 return 0;
850 void SfxDocumentPage::ImplUpdateSignatures()
852 SfxObjectShell* pDoc = SfxObjectShell::Current();
853 if ( pDoc )
855 SfxMedium* pMedium = pDoc->GetMedium();
856 if ( pMedium && !pMedium->GetName().isEmpty() && pMedium->GetStorage().is() )
858 Reference< security::XDocumentDigitalSignatures > xD(
859 security::DocumentDigitalSignatures::createDefault(comphelper::getProcessComponentContext()) );
861 String s;
862 Sequence< security::DocumentSignatureInformation > aInfos;
863 aInfos = xD->verifyDocumentContentSignatures( pMedium->GetZipStorageToSign_Impl(),
864 uno::Reference< io::XInputStream >() );
865 if ( aInfos.getLength() > 1 )
866 s = m_aMultiSignedStr;
867 else if ( aInfos.getLength() == 1 )
869 OUString aCN_Id("CN");
870 const security::DocumentSignatureInformation& rInfo = aInfos[ 0 ];
871 s = GetDateTimeString( rInfo.SignatureDate, rInfo.SignatureTime );
872 s.AppendAscii( ", " );
873 s += GetContentPart( rInfo.Signer->getSubjectName(), aCN_Id );
875 m_pSignedValFt->SetText( s );
880 void SfxDocumentPage::ImplCheckPasswordState()
882 SfxObjectShell* pShell = SfxObjectShell::Current();
885 if (!pShell)
886 break;
887 SfxItemSet* pMedSet = pShell->GetMedium()->GetItemSet();
888 if (!pMedSet)
889 break;
890 SFX_ITEMSET_ARG( pMedSet, pEncryptionDataItem, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False);
891 uno::Sequence< beans::NamedValue > aEncryptionData;
892 if (pEncryptionDataItem)
893 pEncryptionDataItem->GetValue() >>= aEncryptionData;
894 else
895 break;
897 if (!aEncryptionData.getLength())
898 break;
899 m_pChangePassBtn->Enable();
900 return;
902 while (false);
903 m_pChangePassBtn->Disable();
906 //------------------------------------------------------------------------
908 SfxTabPage* SfxDocumentPage::Create( Window* pParent, const SfxItemSet& rItemSet )
910 return new SfxDocumentPage( pParent, rItemSet );
913 //------------------------------------------------------------------------
915 void SfxDocumentPage::EnableUseUserData()
917 bEnableUseUserData = sal_True;
918 m_pUseUserDataCB->Show();
919 m_pDeleteBtn->Show();
922 //------------------------------------------------------------------------
924 sal_Bool SfxDocumentPage::FillItemSet( SfxItemSet& rSet )
926 sal_Bool bRet = sal_False;
928 if ( !bHandleDelete && bEnableUseUserData &&
929 m_pUseUserDataCB->GetState() != m_pUseUserDataCB->GetSavedValue() &&
930 GetTabDialog() && GetTabDialog()->GetExampleSet() )
932 const SfxItemSet* pExpSet = GetTabDialog()->GetExampleSet();
933 const SfxPoolItem* pItem;
935 if ( pExpSet && SFX_ITEM_SET == pExpSet->GetItemState( SID_DOCINFO, sal_True, &pItem ) )
937 SfxDocumentInfoItem* m_pInfoItem = (SfxDocumentInfoItem*)pItem;
938 sal_Bool bUseData = ( STATE_CHECK == m_pUseUserDataCB->GetState() );
939 m_pInfoItem->SetUseUserData( bUseData );
940 rSet.Put( SfxDocumentInfoItem( *m_pInfoItem ) );
941 bRet = sal_True;
945 if ( bHandleDelete )
947 const SfxItemSet* pExpSet = GetTabDialog()->GetExampleSet();
948 const SfxPoolItem* pItem;
949 if ( pExpSet && SFX_ITEM_SET == pExpSet->GetItemState( SID_DOCINFO, sal_True, &pItem ) )
951 SfxDocumentInfoItem* m_pInfoItem = (SfxDocumentInfoItem*)pItem;
952 sal_Bool bUseAuthor = bEnableUseUserData && m_pUseUserDataCB->IsChecked();
953 SfxDocumentInfoItem newItem( *m_pInfoItem );
954 newItem.resetUserData( bUseAuthor
955 ? SvtUserOptions().GetFullName()
956 : OUString() );
957 m_pInfoItem->SetUseUserData( STATE_CHECK == m_pUseUserDataCB->GetState() );
958 newItem.SetUseUserData( STATE_CHECK == m_pUseUserDataCB->GetState() );
960 newItem.SetDeleteUserData( sal_True );
961 rSet.Put( newItem );
962 bRet = sal_True;
966 if ( m_pNameED->IsModified() && !m_pNameED->GetText().isEmpty() )
968 rSet.Put( SfxStringItem( ID_FILETP_TITLE, m_pNameED->GetText() ) );
969 bRet = sal_True;
972 if ( /* m_pReadOnlyCB->IsModified() */ sal_True )
974 rSet.Put( SfxBoolItem( ID_FILETP_READONLY, m_pReadOnlyCB->IsChecked() ) );
975 bRet = sal_True;
978 return bRet;
981 //------------------------------------------------------------------------
983 void SfxDocumentPage::Reset( const SfxItemSet& rSet )
985 // Determine the document information
986 const SfxDocumentInfoItem *m_pInfoItem =
987 &(const SfxDocumentInfoItem &)rSet.Get(SID_DOCINFO);
989 // template data
990 if ( m_pInfoItem->HasTemplate() )
991 m_pTemplValFt->SetText( m_pInfoItem->getTemplateName() );
992 else
994 m_pTemplFt->Hide();
995 m_pTemplValFt->Hide();
998 // determine file name
999 String aFile( m_pInfoItem->GetValue() );
1000 String aFactory( aFile );
1001 if ( aFile.Len() > 2 && aFile.GetChar(0) == '[' )
1003 sal_uInt16 nPos = aFile.Search( ']' );
1004 aFactory = aFile.Copy( 1, nPos-1 );
1005 aFile = aFile.Copy( nPos+1 );
1008 // determine name
1009 String aName;
1010 const SfxPoolItem* pItem = 0;
1011 if ( SFX_ITEM_SET != rSet.GetItemState( ID_FILETP_TITLE, sal_False, &pItem ) )
1013 INetURLObject aURL(aFile);
1014 aName = aURL.GetName( INetURLObject::DECODE_WITH_CHARSET );
1015 if ( !aName.Len() || aURL.GetProtocol() == INET_PROT_PRIVATE )
1016 aName = SfxResId( STR_NONAME ).toString();
1017 m_pNameED->SetReadOnly( sal_True );
1019 else
1021 DBG_ASSERT( pItem->IsA( TYPE( SfxStringItem ) ), "SfxDocumentPage:<SfxStringItem> expected" );
1022 aName = ( ( SfxStringItem* ) pItem )->GetValue();
1024 m_pNameED->SetText( aName );
1025 m_pNameED->ClearModifyFlag();
1027 // determine RO-Flag
1028 if ( SFX_ITEM_UNKNOWN == rSet.GetItemState( ID_FILETP_READONLY, sal_False, &pItem )
1029 || !pItem )
1030 m_pReadOnlyCB->Hide();
1031 else
1032 m_pReadOnlyCB->Check( ( (SfxBoolItem*)pItem )->GetValue() );
1034 // determine context symbol
1035 INetURLObject aURL;
1036 aURL.SetSmartProtocol( INET_PROT_FILE );
1037 aURL.SetSmartURL( aFactory);
1038 const String& rMainURL = aURL.GetMainURL( INetURLObject::NO_DECODE );
1039 m_pBmp->SetImage( SvFileInformationManager::GetImage( aURL, sal_True ) );
1041 // determine size and type
1042 String aSizeText( m_aUnknownSize );
1043 if ( aURL.GetProtocol() == INET_PROT_FILE )
1044 aSizeText = CreateSizeText( SfxContentHelper::GetSize( aURL.GetMainURL( INetURLObject::NO_DECODE ) ) );
1045 m_pShowSizeFT->SetText( aSizeText );
1047 String aDescription = SvFileInformationManager::GetDescription( INetURLObject(rMainURL) );
1048 if ( aDescription.Len() == 0 )
1049 aDescription = SfxResId( STR_SFX_NEWOFFICEDOC ).toString();
1050 m_pShowTypeFT->SetText( aDescription );
1052 // determine location
1053 aURL.SetSmartURL( aFile);
1054 if ( aURL.GetProtocol() == INET_PROT_FILE )
1056 INetURLObject aPath( aURL );
1057 aPath.setFinalSlash();
1058 aPath.removeSegment();
1059 // we know it's a folder -> don't need the final slash, but it's better for WB_PATHELLIPSIS
1060 aPath.removeFinalSlash();
1061 String aText( aPath.PathToFileName() ); //! (pb) MaxLen?
1062 m_pFileValFt->SetText( aText );
1064 else if ( aURL.GetProtocol() != INET_PROT_PRIVATE )
1065 m_pFileValFt->SetText( aURL.GetPartBeforeLastName() );
1067 // handle access data
1068 sal_Bool m_bUseUserData = m_pInfoItem->IsUseUserData();
1069 const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() );
1070 m_pCreateValFt->SetText( ConvertDateTime_Impl( m_pInfoItem->getAuthor(),
1071 m_pInfoItem->getCreationDate(), rLocaleWrapper ) );
1072 util::DateTime aTime( m_pInfoItem->getModificationDate() );
1073 if ( aTime.Month > 0 )
1074 m_pChangeValFt->SetText( ConvertDateTime_Impl(
1075 m_pInfoItem->getModifiedBy(), aTime, rLocaleWrapper ) );
1076 aTime = m_pInfoItem->getPrintDate();
1077 if ( aTime.Month > 0 )
1078 m_pPrintValFt->SetText( ConvertDateTime_Impl( m_pInfoItem->getPrintedBy(),
1079 aTime, rLocaleWrapper ) );
1080 const long nTime = m_pInfoItem->getEditingDuration();
1081 if ( m_bUseUserData )
1083 const Time aT( nTime/3600, (nTime%3600)/60, nTime%60 );
1084 m_pTimeLogValFt->SetText( rLocaleWrapper.getDuration( aT ) );
1085 m_pDocNoValFt->SetText( OUString::number(
1086 m_pInfoItem->getEditingCycles() ) );
1089 TriState eState = (TriState)m_bUseUserData;
1091 if ( STATE_DONTKNOW == eState )
1092 m_pUseUserDataCB->EnableTriState( sal_True );
1094 m_pUseUserDataCB->SetState( eState );
1095 m_pUseUserDataCB->SaveValue();
1096 m_pUseUserDataCB->Enable( bEnableUseUserData );
1097 bHandleDelete = sal_False;
1098 m_pDeleteBtn->Enable( bEnableUseUserData );
1101 //------------------------------------------------------------------------
1102 SfxDocumentInfoDialog::SfxDocumentInfoDialog( Window* pParent,
1103 const SfxItemSet& rItemSet )
1104 : SfxTabDialog(0, pParent, "DocumentPropertiesDialog",
1105 "sfx/ui/documentpropertiesdialog.ui", &rItemSet)
1106 , m_nDocInfoId(0)
1108 const SfxDocumentInfoItem* m_pInfoItem =
1109 &(const SfxDocumentInfoItem &)rItemSet.Get( SID_DOCINFO );
1111 #ifdef DBG_UTIL
1112 SFX_ITEMSET_ARG( &rItemSet, pURLItem, SfxStringItem, SID_BASEURL, sal_False );
1113 DBG_ASSERT( pURLItem, "No BaseURL provided for InternetTabPage!" );
1114 #endif
1116 // Determine the Titels
1117 const SfxPoolItem* pItem = 0;
1118 String aTitle( GetText() );
1119 if ( SFX_ITEM_SET !=
1120 rItemSet.GetItemState( SID_EXPLORER_PROPS_START, sal_False, &pItem ) )
1122 // File name
1123 String aFile( m_pInfoItem->GetValue() );
1125 INetURLObject aURL;
1126 aURL.SetSmartProtocol( INET_PROT_FILE );
1127 aURL.SetSmartURL( aFile);
1128 if ( INET_PROT_PRIV_SOFFICE != aURL.GetProtocol() )
1130 String aLastName( aURL.GetLastName() );
1131 if ( aLastName.Len() )
1132 aTitle += aLastName;
1133 else
1134 aTitle += aFile;
1136 else
1137 aTitle += SfxResId( STR_NONAME ).toString();
1139 else
1141 DBG_ASSERT( pItem->IsA( TYPE( SfxStringItem ) ),
1142 "SfxDocumentInfoDialog:<SfxStringItem> expected" );
1143 aTitle += ( ( SfxStringItem* ) pItem )->GetValue();
1145 SetText( aTitle );
1147 // Property Pages
1148 m_nDocInfoId = AddTabPage("general", SfxDocumentPage::Create, 0);
1149 AddTabPage("description", SfxDocumentDescPage::Create, 0);
1150 AddTabPage("customprops", SfxCustomPropertiesPage::Create, 0);
1151 AddTabPage("security", SfxSecurityPage::Create, 0);
1154 // -----------------------------------------------------------------------
1156 void SfxDocumentInfoDialog::PageCreated( sal_uInt16 nId, SfxTabPage &rPage )
1158 if ( m_nDocInfoId == nId )
1159 ( (SfxDocumentPage&)rPage ).EnableUseUserData();
1162 void SfxDocumentInfoDialog::AddFontTabPage()
1164 AddTabPage( FONT_PAGE_ID, SfxResId( STR_FONT_TABPAGE ).toString(), SfxDocumentFontsPage::Create, 0);
1167 // class CustomPropertiesYesNoButton -------------------------------------
1169 CustomPropertiesYesNoButton::CustomPropertiesYesNoButton( Window* pParent, const ResId& rResId ) :
1170 Control( pParent, rResId ),
1171 m_aYesButton( this, ResId( RB_PROPERTY_YES, *rResId.GetResMgr() ) ),
1172 m_aNoButton ( this, ResId( RB_PROPERTY_NO, *rResId.GetResMgr() ) )
1174 FreeResource();
1175 Wallpaper aWall( Color( COL_TRANSPARENT ) );
1176 SetBackground( aWall );
1177 SetBorderStyle( WINDOW_BORDER_MONO );
1178 CheckNo();
1179 m_aYesButton.SetBackground( aWall );
1180 m_aNoButton.SetBackground( aWall );
1182 class DurationDialog_Impl : public ModalDialog
1184 FixedLine aDurationFL;
1186 OKButton aOKPB;
1187 CancelButton aCancelPB;
1188 HelpButton aHelpPB;
1190 CheckBox aNegativeCB;
1191 FixedText aYearFT;
1192 NumericField aYearNF;
1193 FixedText aMonthFT;
1194 NumericField aMonthNF;
1195 FixedText aDayFT;
1196 NumericField aDayNF;
1197 FixedText aHourFT;
1198 NumericField aHourNF;
1199 FixedText aMinuteFT;
1200 NumericField aMinuteNF;
1201 FixedText aSecondFT;
1202 NumericField aSecondNF;
1203 FixedText aMSecondFT;
1204 NumericField aMSecondNF;
1206 public:
1208 DurationDialog_Impl( Window* pParent, const util::Duration& rDuration );
1209 ~DurationDialog_Impl();
1211 util::Duration GetDuration() const;
1214 DurationDialog_Impl::DurationDialog_Impl(
1215 Window* pParent, const util::Duration& rDuration)
1216 : ModalDialog( pParent, SfxResId( RID_EDIT_DURATIONS ) ),
1217 aDurationFL(this, SfxResId( FL_DURATION )),
1218 aOKPB( this, SfxResId( PB_OK )),
1219 aCancelPB( this, SfxResId( PB_CANCEL )),
1220 aHelpPB( this, SfxResId( PB_HELP )),
1221 aNegativeCB(this, SfxResId( CB_NEGATIVE )),
1222 aYearFT( this, SfxResId( FT_YEAR )),
1223 aYearNF( this, SfxResId( ED_YEAR )),
1224 aMonthFT( this, SfxResId( FT_MONTH )),
1225 aMonthNF( this, SfxResId( ED_MONTH )),
1226 aDayFT( this, SfxResId( FT_DAY )),
1227 aDayNF( this, SfxResId( ED_DAY )),
1228 aHourFT( this, SfxResId( FT_HOUR )),
1229 aHourNF( this, SfxResId( ED_HOUR )),
1230 aMinuteFT( this, SfxResId( FT_MINUTE )),
1231 aMinuteNF( this, SfxResId( ED_MINUTE )),
1232 aSecondFT( this, SfxResId( FT_SECOND )),
1233 aSecondNF( this, SfxResId( ED_SECOND )),
1234 aMSecondFT( this, SfxResId( FT_MSECOND )),
1235 aMSecondNF( this, SfxResId( ED_MSECOND ))
1237 FreeResource();
1238 aNegativeCB.Check(rDuration.Negative);
1239 aYearNF.SetValue(rDuration.Years);
1240 aMonthNF.SetValue(rDuration.Months );
1241 aDayNF.SetValue(rDuration.Days );
1242 aHourNF.SetValue(rDuration.Hours );
1243 aMinuteNF.SetValue(rDuration.Minutes);
1244 aSecondNF.SetValue(rDuration.Seconds);
1245 aMSecondNF.SetValue(rDuration.NanoSeconds);
1248 DurationDialog_Impl::~DurationDialog_Impl()
1252 util::Duration DurationDialog_Impl::GetDuration() const
1254 util::Duration aRet;
1255 aRet.Negative = aNegativeCB.IsChecked();
1256 aRet.Years = aYearNF.GetValue();
1257 aRet.Months = aMonthNF.GetValue( );
1258 aRet.Days = aDayNF.GetValue( );
1259 aRet.Hours = aHourNF.GetValue( );
1260 aRet.Minutes = aMinuteNF.GetValue();
1261 aRet.Seconds = aSecondNF.GetValue();
1262 aRet.NanoSeconds = aMSecondNF.GetValue();
1263 return aRet;
1266 CustomPropertiesDurationField::CustomPropertiesDurationField( Window* pParent, const ResId& rResId, CustomPropertyLine* pLine ) :
1267 Edit( pParent, rResId ), m_pLine( pLine )
1270 SetDuration( util::Duration(false, 0, 0, 0, 0, 0, 0, 0) );
1273 CustomPropertiesDurationField::~CustomPropertiesDurationField()
1277 void CustomPropertiesDurationField::RequestHelp( const HelpEvent& rHEvt )
1279 if ( rHEvt.GetMode() & HELPMODE_QUICK )
1281 Size aSize( GetSizePixel() );
1282 Rectangle aItemRect( rHEvt.GetMousePosPixel(), aSize );
1283 if (Help::IsBalloonHelpEnabled())
1284 Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), GetText() );
1285 else
1286 Help::ShowQuickHelp( this, aItemRect, GetText(),
1287 QUICKHELP_LEFT|QUICKHELP_VCENTER );
1291 void CustomPropertiesDurationField::SetDuration( const util::Duration& rDuration )
1293 m_aDuration = rDuration;
1294 String sText(rDuration.Negative ? OUString('-') : OUString('+'));
1295 sText += m_pLine->m_sDurationFormat;
1296 sText.SearchAndReplace(OUString("%1"), OUString::number( rDuration.Years ) );
1297 sText.SearchAndReplace(OUString("%2"), OUString::number( rDuration.Months ) );
1298 sText.SearchAndReplace(OUString("%3"), OUString::number( rDuration.Days ) );
1299 sText.SearchAndReplace(OUString("%4"), OUString::number( rDuration.Hours ) );
1300 sText.SearchAndReplace(OUString("%5"), OUString::number( rDuration.Minutes) );
1301 sText.SearchAndReplace(OUString("%6"), OUString::number( rDuration.Seconds) );
1302 SetText( sText );
1305 CustomPropertiesEditButton::CustomPropertiesEditButton( Window* pParent, const ResId& rResId, CustomPropertyLine* pLine ) :
1306 PushButton( pParent, rResId ), m_pLine( pLine )
1308 SetClickHdl( LINK( this, CustomPropertiesEditButton, ClickHdl ));
1311 CustomPropertiesEditButton::~CustomPropertiesEditButton()
1315 IMPL_LINK_NOARG(CustomPropertiesEditButton, ClickHdl)
1317 DurationDialog_Impl* pDurationDlg = new DurationDialog_Impl( this, m_pLine->m_aDurationField.GetDuration() );
1318 if ( RET_OK == pDurationDlg->Execute() )
1319 m_pLine->m_aDurationField.SetDuration( pDurationDlg->GetDuration() );
1320 delete pDurationDlg;
1321 return 1;
1323 //--------------------------------------------------------------------------
1324 void CustomPropertiesYesNoButton::Resize()
1326 const long nWidth = GetSizePixel().Width();
1327 const long n3Width = LogicToPixel( Size( 3, 3 ), MAP_APPFONT ).Width();
1328 const long nNewWidth = ( nWidth / 2 ) - n3Width - 2;
1329 Size aSize = m_aYesButton.GetSizePixel();
1330 const long nDelta = aSize.Width() - nNewWidth;
1331 aSize.Width() = nNewWidth;
1332 m_aYesButton.SetSizePixel( aSize );
1333 Point aPos = m_aNoButton.GetPosPixel();
1334 aPos.X() -= nDelta;
1335 m_aNoButton.SetPosSizePixel( aPos, aSize );
1338 // struct CustomPropertyLine ---------------------------------------------
1339 CustomPropertyLine::CustomPropertyLine( Window* pParent ) :
1340 m_aNameBox ( pParent, SfxResId( SFX_CB_PROPERTY_NAME ) ),
1341 m_aTypeBox ( pParent, SfxResId( SFX_LB_PROPERTY_TYPE ), this ),
1342 m_aValueEdit ( pParent, SfxResId( SFX_ED_PROPERTY_VALUE ), this ),
1343 m_aDateField ( pParent, SfxResId( SFX_FLD_DATE), this),
1344 m_aTimeField ( pParent, SfxResId( SFX_FLD_TIME), this),
1345 m_sDurationFormat( SfxResId( SFX_ST_DURATION_FORMAT ).toString() ),
1346 m_aDurationField( pParent, SfxResId( SFX_FLD_DURATION), this),
1347 m_aEditButton( pParent, SfxResId( SFX_PB_EDIT ), this),
1348 m_aYesNoButton ( pParent, SfxResId( SFX_WIN_PROPERTY_YESNO ) ),
1349 m_aRemoveButton ( pParent, SfxResId( SFX_PB_PROPERTY_REMOVE ), this ),
1350 m_bIsRemoved ( false ),
1351 m_bTypeLostFocus( false )
1354 m_aTimeField.SetExtFormat( EXTTIMEF_24H_LONG );
1355 m_aDateField.SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YYYY );
1357 m_aRemoveButton.SetModeImage( SfxResId( SFX_IMG_PROPERTY_REMOVE ) );
1360 void CustomPropertyLine::SetRemoved()
1362 DBG_ASSERT( !m_bIsRemoved, "CustomPropertyLine::SetRemoved(): line already removed" );
1363 m_bIsRemoved = true;
1364 m_aNameBox.Hide();
1365 m_aTypeBox.Hide();
1366 m_aValueEdit.Hide();
1367 m_aDateField.Hide();
1368 m_aTimeField.Hide();
1369 m_aDurationField.Hide();
1370 m_aEditButton.Hide();
1371 m_aYesNoButton.Hide();
1372 m_aRemoveButton.Hide();
1375 CustomPropertiesWindow::CustomPropertiesWindow(Window* pParent,
1376 const OUString &rHeaderAccName,
1377 const OUString &rHeaderAccType,
1378 const OUString &rHeaderAccValue) :
1379 Window(pParent),
1380 m_aNameBox ( this, SfxResId( SFX_CB_PROPERTY_NAME ) ),
1381 m_aTypeBox ( this, SfxResId( SFX_LB_PROPERTY_TYPE ) ),
1382 m_aValueEdit ( this, SfxResId( SFX_ED_PROPERTY_VALUE ) ),
1383 m_aDateField ( this, SfxResId( SFX_FLD_DATE) ),
1384 m_aTimeField ( this, SfxResId( SFX_FLD_TIME) ),
1385 m_aDurationField( this, SfxResId( SFX_FLD_DURATION) ),
1386 m_aEditButton( this, SfxResId( SFX_PB_EDIT )),
1387 m_aYesNoButton ( this, SfxResId( SFX_WIN_PROPERTY_YESNO ) ),
1388 m_aRemoveButton ( this, SfxResId( SFX_PB_PROPERTY_REMOVE ) ),
1389 m_nScrollPos (0),
1390 m_aNumberFormatter( ::comphelper::getProcessComponentContext(),
1391 Application::GetSettings().GetLanguageTag().getLanguageType() )
1394 m_aEditLoseFocusTimer.SetTimeout( 300 );
1395 m_aEditLoseFocusTimer.SetTimeoutHdl( LINK( this, CustomPropertiesWindow, EditTimeoutHdl ) );
1396 m_aBoxLoseFocusTimer.SetTimeout( 300 );
1397 m_aBoxLoseFocusTimer.SetTimeoutHdl( LINK( this, CustomPropertiesWindow, BoxTimeoutHdl ) );
1399 m_aNameBox.SetAccessibleName(rHeaderAccName);
1400 m_aTypeBox.SetAccessibleName(rHeaderAccType);
1401 m_aValueEdit.SetAccessibleName(rHeaderAccValue);
1403 m_aNameBox.Hide();
1404 m_aTypeBox.Hide();
1405 m_aValueEdit.Hide();
1406 m_aDateField.Hide();
1407 m_aTimeField.Hide();
1408 m_aDurationField.Hide();
1409 m_aEditButton.Hide();
1410 m_aYesNoButton.Hide();
1411 m_aRemoveButton.Hide();
1413 m_nLineHeight =
1414 ( m_aRemoveButton.GetPosPixel().Y() * 2 ) + m_aRemoveButton.GetSizePixel().Height();
1417 CustomPropertiesWindow::~CustomPropertiesWindow()
1419 m_aEditLoseFocusTimer.Stop();
1420 m_aBoxLoseFocusTimer.Stop();
1421 ClearAllLines();
1424 IMPL_LINK( CustomPropertiesWindow, TypeHdl, CustomPropertiesTypeBox*, pBox )
1426 sal_Int64 nType = sal_Int64( (long)pBox->GetEntryData( pBox->GetSelectEntryPos() ) );
1427 CustomPropertyLine* pLine = pBox->GetLine();
1428 pLine->m_aValueEdit.Show( (CUSTOM_TYPE_TEXT == nType) || (CUSTOM_TYPE_NUMBER == nType) );
1429 pLine->m_aDateField.Show( (CUSTOM_TYPE_DATE == nType) || (CUSTOM_TYPE_DATETIME == nType) );
1430 pLine->m_aTimeField.Show( CUSTOM_TYPE_DATETIME == nType );
1431 pLine->m_aDurationField.Show( CUSTOM_TYPE_DURATION == nType );
1432 pLine->m_aEditButton.Show( CUSTOM_TYPE_DURATION == nType );
1433 pLine->m_aYesNoButton.Show( CUSTOM_TYPE_BOOLEAN == nType );
1434 //adjust positions of date and time controls
1435 if ( nType == CUSTOM_TYPE_DATE )
1436 pLine->m_aDateField.SetPosSizePixel(pLine->m_aValueEdit.GetPosPixel(), pLine->m_aValueEdit.GetSizePixel());
1437 else if ( nType == CUSTOM_TYPE_DATETIME)
1439 pLine->m_aDateField.SetPosSizePixel( pLine->m_aDatePos, pLine->m_aDateTimeSize );
1440 pLine->m_aTimeField.SetPosSizePixel(pLine->m_aTimePos, pLine->m_aDateTimeSize );
1443 return 0;
1446 IMPL_LINK( CustomPropertiesWindow, RemoveHdl, CustomPropertiesRemoveButton*, pButton )
1448 CustomPropertyLine* pLine = pButton->GetLine();
1449 std::vector< CustomPropertyLine* >::iterator pFound =
1450 std::find( m_aCustomPropertiesLines.begin(), m_aCustomPropertiesLines.end(), pLine );
1451 if ( pFound != m_aCustomPropertiesLines.end() )
1453 pLine = *pFound;
1454 pLine->SetRemoved();
1455 std::vector< CustomPropertyLine* >::iterator pIter = pFound + 1;
1456 const long nDelta = GetLineHeight();
1457 for ( ; pIter != m_aCustomPropertiesLines.end(); ++pIter )
1459 pLine = *pIter;
1460 if ( pLine->m_bIsRemoved )
1461 continue;
1463 Window* pWindows[] = { &pLine->m_aNameBox, &pLine->m_aTypeBox, &pLine->m_aValueEdit,
1464 &pLine->m_aDateField, &pLine->m_aTimeField,
1465 &pLine->m_aDurationField, &pLine->m_aEditButton,
1466 &pLine->m_aYesNoButton, &pLine->m_aRemoveButton, NULL };
1467 Window** pCurrent = pWindows;
1468 while ( *pCurrent )
1470 Point aPos = (*pCurrent)->GetPosPixel();
1471 aPos.Y() -= nDelta;
1472 (*pCurrent)->SetPosPixel( aPos );
1473 pCurrent++;
1478 m_aRemovedHdl.Call(0);
1479 return 0;
1482 IMPL_LINK( CustomPropertiesWindow, EditLoseFocusHdl, CustomPropertiesEdit*, pEdit )
1484 if ( pEdit )
1486 CustomPropertyLine* pLine = pEdit->GetLine();
1487 if ( !pLine->m_bTypeLostFocus )
1489 m_pCurrentLine = pLine;
1490 m_aEditLoseFocusTimer.Start();
1492 else
1493 pLine->m_bTypeLostFocus = false;
1495 return 0;
1498 IMPL_LINK( CustomPropertiesWindow, BoxLoseFocusHdl, CustomPropertiesTypeBox*, pBox )
1500 if ( pBox )
1502 m_pCurrentLine = pBox->GetLine();
1503 m_aBoxLoseFocusTimer.Start();
1506 return 0;
1509 IMPL_LINK_NOARG(CustomPropertiesWindow, EditTimeoutHdl)
1511 ValidateLine( m_pCurrentLine, false );
1512 return 0;
1515 IMPL_LINK_NOARG(CustomPropertiesWindow, BoxTimeoutHdl)
1517 ValidateLine( m_pCurrentLine, true );
1518 return 0;
1521 bool CustomPropertiesWindow::IsLineValid( CustomPropertyLine* pLine ) const
1523 bool bIsValid = true;
1524 pLine->m_bTypeLostFocus = false;
1525 sal_Int64 nType = sal_Int64(
1526 (long)pLine->m_aTypeBox.GetEntryData( pLine->m_aTypeBox.GetSelectEntryPos() ) );
1527 String sValue = pLine->m_aValueEdit.GetText();
1528 if ( sValue.Len() == 0 )
1529 return true;
1531 sal_uInt32 nIndex = 0xFFFFFFFF;
1532 if ( CUSTOM_TYPE_NUMBER == nType )
1533 nIndex = const_cast< SvNumberFormatter& >(
1534 m_aNumberFormatter ).GetFormatIndex( NF_NUMBER_SYSTEM );
1535 else if ( CUSTOM_TYPE_DATE == nType )
1536 nIndex = const_cast< SvNumberFormatter& >(
1537 m_aNumberFormatter).GetFormatIndex( NF_DATE_SYS_DDMMYYYY );
1539 if ( nIndex != 0xFFFFFFFF )
1541 sal_uInt32 nTemp = nIndex;
1542 double fDummy = 0.0;
1543 bIsValid = const_cast< SvNumberFormatter& >(
1544 m_aNumberFormatter ).IsNumberFormat( sValue, nIndex, fDummy ) != sal_False;
1545 if ( bIsValid && nTemp != nIndex )
1546 // sValue is a number but the format doesn't match the index
1547 bIsValid = false;
1550 return bIsValid;
1553 void CustomPropertiesWindow::ValidateLine( CustomPropertyLine* pLine, bool bIsFromTypeBox )
1555 if ( !IsLineValid( pLine ) )
1557 if ( bIsFromTypeBox ) // LoseFocus of TypeBox
1558 pLine->m_bTypeLostFocus = true;
1559 Window* pParent = GetParent()->GetParent();
1560 if ( QueryBox( pParent, SfxResId( SFX_QB_WRONG_TYPE ) ).Execute() == RET_OK )
1561 pLine->m_aTypeBox.SelectEntryPos( m_aTypeBox.GetEntryPos( (void*)CUSTOM_TYPE_TEXT ) );
1562 else
1563 pLine->m_aValueEdit.GrabFocus();
1567 void CustomPropertiesWindow::InitControls( HeaderBar* pHeaderBar, const ScrollBar* pScrollBar )
1569 DBG_ASSERT( pHeaderBar, "CustomPropertiesWindow::InitControls(): invalid headerbar" );
1570 DBG_ASSERT( pScrollBar, "CustomPropertiesWindow::InitControls(): invalid scrollbar" );
1572 const long nOffset = 4;
1573 const long nScrollBarWidth = pScrollBar->GetSizePixel().Width();
1574 const long nButtonWidth = m_aRemoveButton.GetSizePixel().Width() + nScrollBarWidth + nOffset;
1575 long nTypeWidth = m_aTypeBox.CalcMinimumSize().Width() + ( 2 * nOffset );
1576 long nFullWidth = pHeaderBar->GetSizePixel().Width();
1577 long nItemWidth = ( nFullWidth - nTypeWidth - nButtonWidth ) / 2;
1578 pHeaderBar->SetItemSize( HI_NAME, nItemWidth );
1579 pHeaderBar->SetItemSize( HI_TYPE, nTypeWidth );
1580 pHeaderBar->SetItemSize( HI_VALUE, nItemWidth );
1581 pHeaderBar->SetItemSize( HI_ACTION, nButtonWidth );
1583 Window* pWindows[] = { &m_aNameBox, &m_aTypeBox, &m_aValueEdit, &m_aRemoveButton, NULL };
1584 Window** pCurrent = pWindows;
1585 sal_uInt16 nPos = 0;
1586 while ( *pCurrent )
1588 Rectangle aRect = pHeaderBar->GetItemRect( pHeaderBar->GetItemId( nPos++ ) );
1589 Size aSize = (*pCurrent)->GetSizePixel();
1590 Point aPos = (*pCurrent)->GetPosPixel();
1591 long nWidth = aRect.GetWidth() - nOffset;
1592 if ( *pCurrent == &m_aRemoveButton )
1593 nWidth -= pScrollBar->GetSizePixel().Width();
1594 aSize.Width() = nWidth;
1595 aPos.X() = aRect.getX() + ( nOffset / 2 );
1596 (*pCurrent)->SetPosSizePixel( aPos, aSize );
1598 if ( *pCurrent == &m_aValueEdit )
1600 Point aDurationPos( aPos );
1601 m_aDurationField.SetPosPixel( aDurationPos );
1602 Size aDurationSize(aSize);
1603 aDurationSize.Width() -= (m_aEditButton.GetSizePixel().Width() + 3 );
1604 m_aDurationField.SetSizePixel(aDurationSize);
1605 aDurationPos.X() = aPos.X() - m_aEditButton.GetSizePixel().Width() + aSize.Width();
1606 m_aEditButton.SetPosPixel(aDurationPos);
1607 aSize = m_aYesNoButton.GetSizePixel();
1608 aPos = m_aYesNoButton.GetPosPixel();
1609 aSize.Width() = nWidth;
1610 aPos.X() = aRect.getX() + ( nOffset / 2 );
1611 m_aYesNoButton.SetPosSizePixel( aPos, aSize );
1612 aSize.Width() /= 2;
1613 aSize.Width() -= 2;
1614 m_aDateField.SetPosSizePixel( aPos, aSize );
1615 aPos.X() += aSize.Width() + 4;
1616 m_aTimeField.SetPosSizePixel( aPos, aSize );
1619 pCurrent++;
1623 sal_uInt16 CustomPropertiesWindow::GetVisibleLineCount() const
1625 sal_uInt16 nCount = 0;
1626 std::vector< CustomPropertyLine* >::const_iterator pIter;
1627 for ( pIter = m_aCustomPropertiesLines.begin();
1628 pIter != m_aCustomPropertiesLines.end(); ++pIter )
1630 CustomPropertyLine* pLine = *pIter;
1631 if ( !pLine->m_bIsRemoved )
1632 nCount++;
1634 return nCount;
1637 void CustomPropertiesWindow::updateLineWidth()
1639 Window* pWindows[] = { &m_aNameBox, &m_aTypeBox, &m_aValueEdit,
1640 &m_aDateField, &m_aTimeField,
1641 &m_aDurationField, &m_aEditButton,
1642 &m_aYesNoButton, &m_aRemoveButton, NULL };
1644 for (std::vector< CustomPropertyLine* >::iterator aI =
1645 m_aCustomPropertiesLines.begin(), aEnd = m_aCustomPropertiesLines.end();
1646 aI != aEnd; ++aI)
1648 CustomPropertyLine* pNewLine = *aI;
1650 Window* pNewWindows[] =
1651 { &pNewLine->m_aNameBox, &pNewLine->m_aTypeBox, &pNewLine->m_aValueEdit,
1652 &pNewLine->m_aDateField, &pNewLine->m_aTimeField,
1653 &pNewLine->m_aDurationField, &pNewLine->m_aEditButton,
1654 &pNewLine->m_aYesNoButton, &pNewLine->m_aRemoveButton, NULL };
1656 Window** pCurrent = pWindows;
1657 Window** pNewCurrent = pNewWindows;
1658 while ( *pCurrent )
1660 Size aSize = (*pCurrent)->GetSizePixel();
1661 Point aPos = (*pCurrent)->GetPosPixel();
1662 aPos.Y() = (*pNewCurrent)->GetPosPixel().Y();
1663 (*pNewCurrent)->SetPosSizePixel( aPos, aSize );
1664 pCurrent++;
1665 pNewCurrent++;
1670 void CustomPropertiesWindow::AddLine( const OUString& sName, Any& rAny )
1672 CustomPropertyLine* pNewLine = new CustomPropertyLine( this );
1673 pNewLine->m_aTypeBox.SetSelectHdl( LINK( this, CustomPropertiesWindow, TypeHdl ) );
1674 pNewLine->m_aRemoveButton.SetClickHdl( LINK( this, CustomPropertiesWindow, RemoveHdl ) );
1675 pNewLine->m_aValueEdit.SetLoseFocusHdl( LINK( this, CustomPropertiesWindow, EditLoseFocusHdl ) );
1676 //add lose focus handlers of date/time fields
1678 pNewLine->m_aTypeBox.SetLoseFocusHdl( LINK( this, CustomPropertiesWindow, BoxLoseFocusHdl ) );
1680 pNewLine->m_aNameBox.SetAccessibleName(m_aNameBox.GetAccessibleName());
1681 pNewLine->m_aTypeBox.SetAccessibleName(m_aTypeBox.GetAccessibleName());
1682 pNewLine->m_aValueEdit.SetAccessibleName(m_aValueEdit.GetAccessibleName());
1684 long nPos = GetVisibleLineCount() * GetLineHeight();
1685 m_aCustomPropertiesLines.push_back( pNewLine );
1686 Window* pWindows[] = { &m_aNameBox, &m_aTypeBox, &m_aValueEdit,
1687 &m_aDateField, &m_aTimeField,
1688 &m_aDurationField, &m_aEditButton,
1689 &m_aYesNoButton, &m_aRemoveButton, NULL };
1690 Window* pNewWindows[] =
1691 { &pNewLine->m_aNameBox, &pNewLine->m_aTypeBox, &pNewLine->m_aValueEdit,
1692 &pNewLine->m_aDateField, &pNewLine->m_aTimeField,
1693 &pNewLine->m_aDurationField, &pNewLine->m_aEditButton,
1694 &pNewLine->m_aYesNoButton, &pNewLine->m_aRemoveButton, NULL };
1695 Window** pCurrent = pWindows;
1696 Window** pNewCurrent = pNewWindows;
1697 while ( *pCurrent )
1699 Size aSize = (*pCurrent)->GetSizePixel();
1700 Point aPos = (*pCurrent)->GetPosPixel();
1701 aPos.Y() += nPos;
1702 aPos.Y() += m_nScrollPos;
1703 (*pNewCurrent)->SetPosSizePixel( aPos, aSize );
1704 (*pNewCurrent)->Show();
1705 pCurrent++;
1706 pNewCurrent++;
1709 pNewLine->m_aDatePos = pNewLine->m_aDateField.GetPosPixel();
1710 pNewLine->m_aTimePos = pNewLine->m_aTimeField.GetPosPixel();
1711 pNewLine->m_aDateTimeSize = pNewLine->m_aDateField.GetSizePixel();
1713 double nTmpValue = 0;
1714 bool bTmpValue = false;
1715 OUString sTmpValue;
1716 util::DateTime aTmpDateTime;
1717 util::Date aTmpDate;
1718 util::Duration aTmpDuration;
1719 SvtSysLocale aSysLocale;
1720 const LocaleDataWrapper& rLocaleWrapper = aSysLocale.GetLocaleData();
1721 pNewLine->m_aNameBox.SetText( sName );
1722 sal_IntPtr nType = CUSTOM_TYPE_UNKNOWN;
1723 String sValue;
1725 if ( rAny >>= nTmpValue )
1727 sal_uInt32 nIndex = m_aNumberFormatter.GetFormatIndex( NF_NUMBER_SYSTEM );
1728 m_aNumberFormatter.GetInputLineString( nTmpValue, nIndex, sValue );
1729 pNewLine->m_aValueEdit.SetText( sValue );
1730 nType = CUSTOM_TYPE_NUMBER;
1732 else if ( rAny >>= bTmpValue )
1734 sValue = ( bTmpValue ? rLocaleWrapper.getTrueWord() : rLocaleWrapper.getFalseWord() );
1735 nType = CUSTOM_TYPE_BOOLEAN;
1737 else if ( rAny >>= sTmpValue )
1739 pNewLine->m_aValueEdit.SetText( sTmpValue );
1740 nType = CUSTOM_TYPE_TEXT;
1742 else if ( rAny >>= aTmpDate )
1744 nType = CUSTOM_TYPE_DATE;
1745 pNewLine->m_aDateField.SetDate( Date( aTmpDate.Day, aTmpDate.Month, aTmpDate.Year ) );
1748 else if ( rAny >>= aTmpDuration )
1750 nType = CUSTOM_TYPE_DURATION;
1751 pNewLine->m_aDurationField.SetDuration( aTmpDuration );
1753 else if ( rAny >>= aTmpDateTime )
1755 pNewLine->m_aDateField.SetDate( Date( aTmpDateTime.Day, aTmpDateTime.Month, aTmpDateTime.Year ) );
1756 pNewLine->m_aTimeField.SetTime( Time( aTmpDateTime.Hours, aTmpDateTime.Minutes, aTmpDateTime.Seconds, aTmpDateTime.NanoSeconds ) );
1758 nType = CUSTOM_TYPE_DATETIME;
1761 if ( nType != CUSTOM_TYPE_UNKNOWN )
1763 if ( CUSTOM_TYPE_BOOLEAN == nType )
1765 if ( bTmpValue )
1766 pNewLine->m_aYesNoButton.CheckYes();
1767 else
1768 pNewLine->m_aYesNoButton.CheckNo();
1770 pNewLine->m_aTypeBox.SelectEntryPos( m_aTypeBox.GetEntryPos( (void*)nType ) );
1773 TypeHdl( &pNewLine->m_aTypeBox );
1774 pNewLine->m_aNameBox.GrabFocus();
1777 bool CustomPropertiesWindow::AreAllLinesValid() const
1779 bool bRet = true;
1780 std::vector< CustomPropertyLine* >::const_iterator pIter;
1781 for ( pIter = m_aCustomPropertiesLines.begin();
1782 pIter != m_aCustomPropertiesLines.end(); ++pIter )
1784 CustomPropertyLine* pLine = *pIter;
1785 if ( !IsLineValid( pLine ) )
1787 bRet = false;
1788 break;
1792 return bRet;
1795 void CustomPropertiesWindow::ClearAllLines()
1797 std::vector< CustomPropertyLine* >::iterator pIter;
1798 for ( pIter = m_aCustomPropertiesLines.begin();
1799 pIter != m_aCustomPropertiesLines.end(); ++pIter )
1801 CustomPropertyLine* pLine = *pIter;
1802 pLine->SetRemoved();
1803 delete pLine;
1805 m_aCustomPropertiesLines.clear();
1806 m_nScrollPos = 0;
1809 void CustomPropertiesWindow::DoScroll( sal_Int32 nNewPos )
1811 m_nScrollPos += nNewPos;
1812 std::vector< CustomPropertyLine* >::iterator pIter;
1813 for ( pIter = m_aCustomPropertiesLines.begin();
1814 pIter != m_aCustomPropertiesLines.end(); ++pIter )
1816 CustomPropertyLine* pLine = *pIter;
1817 if ( pLine->m_bIsRemoved )
1818 continue;
1820 Window* pWindows[] = { &pLine->m_aNameBox, &pLine->m_aTypeBox, &pLine->m_aValueEdit, &pLine->m_aDateField, &pLine->m_aTimeField,
1821 &pLine->m_aDurationField, &pLine->m_aEditButton, &pLine->m_aYesNoButton, &pLine->m_aRemoveButton, NULL };
1822 Window** pCurrent = pWindows;
1823 while ( *pCurrent )
1825 Point aPos = (*pCurrent)->GetPosPixel();
1826 aPos.Y() += nNewPos;
1827 (*pCurrent)->SetPosPixel( aPos );
1828 pCurrent++;
1833 Sequence< beans::PropertyValue > CustomPropertiesWindow::GetCustomProperties() const
1835 Sequence< beans::PropertyValue > aPropertiesSeq( m_aCustomPropertiesLines.size() );
1836 sal_Int32 i = 0;
1837 std::vector< CustomPropertyLine* >::const_iterator pIter;
1838 for ( pIter = m_aCustomPropertiesLines.begin();
1839 pIter != m_aCustomPropertiesLines.end(); ++pIter, ++i )
1841 CustomPropertyLine* pLine = *pIter;
1842 if ( pLine->m_bIsRemoved )
1843 continue;
1845 String sPropertyName = pLine->m_aNameBox.GetText();
1846 if ( sPropertyName.Len() > 0 )
1848 aPropertiesSeq[i].Name = sPropertyName;
1849 sal_Int64 nType = sal_Int64(
1850 (long)pLine->m_aTypeBox.GetEntryData( pLine->m_aTypeBox.GetSelectEntryPos() ) );
1851 if ( CUSTOM_TYPE_NUMBER == nType )
1853 double nValue = 0;
1854 sal_uInt32 nIndex = const_cast< SvNumberFormatter& >(
1855 m_aNumberFormatter ).GetFormatIndex( NF_NUMBER_SYSTEM );
1856 sal_Bool bIsNum = const_cast< SvNumberFormatter& >( m_aNumberFormatter ).
1857 IsNumberFormat( pLine->m_aValueEdit.GetText(), nIndex, nValue );
1858 if ( bIsNum )
1859 aPropertiesSeq[i].Value <<= makeAny( nValue );
1861 else if ( CUSTOM_TYPE_BOOLEAN == nType )
1863 bool bValue = pLine->m_aYesNoButton.IsYesChecked();
1864 aPropertiesSeq[i].Value <<= makeAny( bValue );
1866 else if ( CUSTOM_TYPE_DATETIME == nType )
1868 Date aTmpDate = pLine->m_aDateField.GetDate();
1869 Time aTmpTime = pLine->m_aTimeField.GetTime();
1870 util::DateTime const aDateTime(aTmpTime.GetNanoSec(),
1871 aTmpTime.GetSec(), aTmpTime.GetMin(), aTmpTime.GetHour(),
1872 aTmpDate.GetDay(), aTmpDate.GetMonth(), aTmpDate.GetYear(),
1873 false);
1874 aPropertiesSeq[i].Value <<= aDateTime;
1876 else if ( CUSTOM_TYPE_DURATION == nType )
1878 aPropertiesSeq[i].Value <<= pLine->m_aDurationField.GetDuration();
1880 else if ( CUSTOM_TYPE_DATE == nType )
1882 Date aTmpDate = pLine->m_aDateField.GetDate();
1883 util::Date const aDate(aTmpDate.GetDay(), aTmpDate.GetMonth(),
1884 aTmpDate.GetYear());
1885 aPropertiesSeq[i].Value <<= aDate;
1888 else
1890 OUString sValue( pLine->m_aValueEdit.GetText() );
1891 aPropertiesSeq[i].Value <<= makeAny( sValue );
1896 return aPropertiesSeq;
1899 CustomPropertiesControl::CustomPropertiesControl(Window* pParent)
1900 : VclVBox(pParent)
1901 , m_nThumbPos(0)
1905 void CustomPropertiesControl::Init(VclBuilderContainer& rBuilder)
1907 m_pHeaderBar = new HeaderBar(this, WB_BUTTONSTYLE | WB_BOTTOMBORDER);
1908 m_pBody = new VclHBox(this);
1909 OUString sName = rBuilder.get<FixedText>("name")->GetText();
1910 OUString sType = rBuilder.get<FixedText>("type")->GetText();
1911 OUString sValue = rBuilder.get<FixedText>("value")->GetText();
1912 m_pPropertiesWin = new CustomPropertiesWindow(m_pBody, sName, sType, sValue);
1913 m_pVertScroll = new ScrollBar(m_pBody, WB_VERT);
1915 set_hexpand(true);
1916 set_vexpand(true);
1917 set_expand(true);
1918 set_fill(true);
1920 m_pBody->set_hexpand(true);
1921 m_pBody->set_vexpand(true);
1922 m_pBody->set_expand(true);
1923 m_pBody->set_fill(true);
1924 m_pBody->Show();
1926 m_pPropertiesWin->set_hexpand(true);
1927 m_pPropertiesWin->set_vexpand(true);
1928 m_pPropertiesWin->set_expand(true);
1929 m_pPropertiesWin->set_fill(true);
1930 m_pPropertiesWin->Show();
1932 m_pPropertiesWin->SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
1933 m_pVertScroll->EnableDrag();
1934 m_pVertScroll->Show();
1936 m_pHeaderBar->set_height_request(GetTextHeight() + 6);
1938 const HeaderBarItemBits nHeadBits = HIB_VCENTER | HIB_FIXED | HIB_FIXEDPOS | HIB_LEFT;
1940 m_pHeaderBar->InsertItem( HI_NAME, sName, 0, nHeadBits );
1941 m_pHeaderBar->InsertItem( HI_TYPE, sType, 0, nHeadBits );
1942 m_pHeaderBar->InsertItem( HI_VALUE, sValue, 0, nHeadBits );
1943 m_pHeaderBar->InsertItem( HI_ACTION, OUString(), 0, nHeadBits );
1944 m_pHeaderBar->Show();
1946 m_pPropertiesWin->SetRemovedHdl( LINK( this, CustomPropertiesControl, RemovedHdl ) );
1948 m_pVertScroll->SetRangeMin( 0 );
1949 m_pVertScroll->SetRangeMax( 0 );
1950 m_pVertScroll->SetVisibleSize( 0xFFFF );
1952 Link aScrollLink = LINK( this, CustomPropertiesControl, ScrollHdl );
1953 m_pVertScroll->SetScrollHdl( aScrollLink );
1956 void CustomPropertiesControl::setAllocation(const Size &rAllocation)
1958 VclVBox::setAllocation(rAllocation);
1960 m_pPropertiesWin->InitControls( m_pHeaderBar, m_pVertScroll );
1961 sal_Int32 nScrollOffset = m_pPropertiesWin->GetLineHeight();
1962 sal_Int32 nVisibleEntries = m_pPropertiesWin->GetSizePixel().Height() / nScrollOffset;
1963 m_pVertScroll->SetPageSize( nVisibleEntries - 1 );
1964 m_pVertScroll->SetVisibleSize( nVisibleEntries );
1965 m_pPropertiesWin->updateLineWidth();
1968 extern "C" SAL_DLLPUBLIC_EXPORT Window* SAL_CALL makeCustomPropertiesControl(Window *pParent,
1969 VclBuilder::stringmap &)
1971 return new CustomPropertiesControl(pParent);
1974 CustomPropertiesControl::~CustomPropertiesControl()
1976 delete m_pVertScroll;
1977 delete m_pPropertiesWin;
1978 delete m_pBody;
1979 delete m_pHeaderBar;
1982 IMPL_LINK( CustomPropertiesControl, ScrollHdl, ScrollBar*, pScrollBar )
1984 sal_Int32 nOffset = m_pPropertiesWin->GetLineHeight();
1985 nOffset *= ( m_nThumbPos - pScrollBar->GetThumbPos() );
1986 m_nThumbPos = pScrollBar->GetThumbPos();
1987 m_pPropertiesWin->DoScroll( nOffset );
1988 return 0;
1991 IMPL_LINK_NOARG(CustomPropertiesControl, RemovedHdl)
1993 m_pVertScroll->SetRangeMax( m_pPropertiesWin->GetVisibleLineCount() + 1 );
1994 if ( m_pPropertiesWin->GetOutputSizePixel().Height() < m_pPropertiesWin->GetVisibleLineCount() * m_pPropertiesWin->GetLineHeight() )
1995 m_pVertScroll->DoScrollAction ( SCROLL_LINEUP );
1996 return 0;
1999 void CustomPropertiesControl::AddLine( const OUString& sName, Any& rAny, bool bInteractive )
2001 m_pPropertiesWin->AddLine( sName, rAny );
2002 m_pVertScroll->SetRangeMax( m_pPropertiesWin->GetVisibleLineCount() + 1 );
2003 if ( bInteractive && m_pPropertiesWin->GetOutputSizePixel().Height() < m_pPropertiesWin->GetVisibleLineCount() * m_pPropertiesWin->GetLineHeight() )
2004 m_pVertScroll->DoScroll( m_pPropertiesWin->GetVisibleLineCount() + 1 );
2007 // class SfxCustomPropertiesPage -----------------------------------------
2008 SfxCustomPropertiesPage::SfxCustomPropertiesPage( Window* pParent, const SfxItemSet& rItemSet )
2009 : SfxTabPage(pParent, "CustomInfoPage", "sfx/ui/custominfopage.ui", rItemSet)
2011 get(m_pPropertiesCtrl, "properties");
2012 m_pPropertiesCtrl->Init(*this);
2013 get<PushButton>("add")->SetClickHdl(LINK(this, SfxCustomPropertiesPage, AddHdl));
2016 IMPL_LINK_NOARG(SfxCustomPropertiesPage, AddHdl)
2018 Any aAny;
2019 m_pPropertiesCtrl->AddLine( OUString(), aAny, true );
2020 return 0;
2023 sal_Bool SfxCustomPropertiesPage::FillItemSet( SfxItemSet& rSet )
2025 sal_Bool bModified = sal_False;
2026 const SfxPoolItem* pItem = NULL;
2027 SfxDocumentInfoItem* pInfo = NULL;
2028 bool bMustDelete = false;
2030 if ( GetTabDialog() && GetTabDialog()->GetExampleSet() )
2032 if ( SFX_ITEM_SET !=
2033 GetTabDialog()->GetExampleSet()->GetItemState( SID_DOCINFO, sal_True, &pItem ) )
2034 pInfo = &( SfxDocumentInfoItem& )rSet.Get( SID_DOCINFO );
2035 else
2037 bMustDelete = true;
2038 pInfo = new SfxDocumentInfoItem( *( const SfxDocumentInfoItem* ) pItem );
2042 if ( pInfo )
2044 pInfo->ClearCustomProperties();
2045 Sequence< beans::PropertyValue > aPropertySeq = m_pPropertiesCtrl->GetCustomProperties();
2046 sal_Int32 i = 0, nCount = aPropertySeq.getLength();
2047 for ( ; i < nCount; ++i )
2049 if ( !aPropertySeq[i].Name.isEmpty() )
2050 pInfo->AddCustomProperty( aPropertySeq[i].Name, aPropertySeq[i].Value );
2054 bModified = sal_True; //!!!
2055 if ( bModified )
2056 rSet.Put( *pInfo );
2057 if ( bMustDelete )
2058 delete pInfo;
2059 return bModified;
2062 void SfxCustomPropertiesPage::Reset( const SfxItemSet& rItemSet )
2064 m_pPropertiesCtrl->ClearAllLines();
2065 const SfxDocumentInfoItem* m_pInfoItem = &(const SfxDocumentInfoItem &)rItemSet.Get(SID_DOCINFO);
2066 std::vector< CustomProperty* > aCustomProps = m_pInfoItem->GetCustomProperties();
2067 for ( sal_uInt32 i = 0; i < aCustomProps.size(); i++ )
2069 m_pPropertiesCtrl->AddLine( aCustomProps[i]->m_sName, aCustomProps[i]->m_aValue, false );
2073 int SfxCustomPropertiesPage::DeactivatePage( SfxItemSet* /*pSet*/ )
2075 int nRet = LEAVE_PAGE;
2076 if ( !m_pPropertiesCtrl->AreAllLinesValid() )
2077 nRet = KEEP_PAGE;
2078 return nRet;
2081 SfxTabPage* SfxCustomPropertiesPage::Create( Window* pParent, const SfxItemSet& rItemSet )
2083 return new SfxCustomPropertiesPage( pParent, rItemSet );
2086 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */