xref: /trunk/main/sfx2/source/dialog/dinfdlg.cxx (revision 6cb2fd0368c0bfc9279c5d8c2b60b3bc454c530a)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 
31 #include <tools/urlobj.hxx>
32 #include <vcl/msgbox.hxx>
33 #include <svl/eitem.hxx>
34 #include <vcl/svapp.hxx>
35 #include <sfx2/filedlghelper.hxx>
36 #include <unotools/localedatawrapper.hxx>
37 #include <unotools/cmdoptions.hxx>
38 #include <comphelper/processfactory.hxx>
39 #include <svl/urihelper.hxx>
40 #include <unotools/useroptions.hxx>
41 #include <svtools/imagemgr.hxx>
42 #include <tools/datetime.hxx>
43 
44 #include <memory>
45 
46 #include <comphelper/string.hxx>
47 #include <comphelper/processfactory.hxx>
48 #include <com/sun/star/security/DocumentSignatureInformation.hpp>
49 #include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
50 #include <unotools/localedatawrapper.hxx>
51 #include <unotools/syslocale.hxx>
52 #include <rtl/math.hxx>
53 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
54 #include <com/sun/star/beans/PropertyAttribute.hpp>
55 #include <com/sun/star/beans/XPropertyContainer.hpp>
56 #include <com/sun/star/util/DateTime.hpp>
57 #include <com/sun/star/util/Date.hpp>
58 #include <com/sun/star/util/Time.hpp>
59 #include <com/sun/star/util/Duration.hpp>
60 #include <com/sun/star/document/XDocumentProperties.hpp>
61 
62 #include <vcl/timer.hxx>
63 #include "sfx2/dinfdlg.hxx"
64 #include "sfx2/securitypage.hxx"
65 #include "sfxresid.hxx"
66 #include "dinfedt.hxx"
67 #include <sfx2/frame.hxx>
68 #include <sfx2/viewfrm.hxx>
69 #include <sfx2/request.hxx>
70 //#include "exptypes.hxx"
71 #include "helper.hxx"
72 #include <sfx2/objsh.hxx>
73 #include <sfx2/docfile.hxx>
74 #include <comphelper/storagehelper.hxx>
75 
76 #include <sfx2/sfx.hrc>
77 #include "dinfdlg.hrc"
78 #include "sfxlocal.hrc"
79 #include <dialog.hrc>
80 #include <vcl/help.hxx>
81 
82 #include <algorithm>
83 
84 using namespace ::com::sun::star;
85 using namespace ::com::sun::star::lang;
86 using namespace ::com::sun::star::ui::dialogs;
87 using namespace ::com::sun::star::uno;
88 
89 
90 struct CustomProperty
91 {
92     ::rtl::OUString             m_sName;
93     com::sun::star::uno::Any    m_aValue;
94 
95     CustomProperty( const ::rtl::OUString& sName,
96             const com::sun::star::uno::Any& rValue ) :
97         m_sName( sName ), m_aValue( rValue ) {}
98 
99     inline bool operator==( const CustomProperty& rProp )
100     { return m_sName.equals( rProp.m_sName ) && m_aValue == rProp.m_aValue; }
101 };
102 
103 
104 static
105 bool operator==(const util::DateTime &i_rLeft, const util::DateTime &i_rRight)
106 {
107     return i_rLeft.Year             == i_rRight.Year
108         && i_rLeft.Month            == i_rRight.Month
109         && i_rLeft.Day              == i_rRight.Day
110         && i_rLeft.Hours            == i_rRight.Hours
111         && i_rLeft.Minutes          == i_rRight.Minutes
112         && i_rLeft.Seconds          == i_rRight.Seconds
113         && i_rLeft.HundredthSeconds == i_rRight.HundredthSeconds;
114 }
115 
116 // STATIC DATA -----------------------------------------------------------
117 
118 TYPEINIT1_AUTOFACTORY(SfxDocumentInfoItem, SfxStringItem);
119 
120 const sal_uInt16 HI_NAME = 1;
121 const sal_uInt16 HI_TYPE = 2;
122 const sal_uInt16 HI_VALUE = 3;
123 const sal_uInt16 HI_ACTION = 4;
124 
125 static const char DOCUMENT_SIGNATURE_MENU_CMD[]      = "Signature";
126 
127 //------------------------------------------------------------------------
128 String CreateSizeText( sal_uIntPtr nSize, sal_Bool bExtraBytes = sal_True, sal_Bool bSmartExtraBytes = sal_False );
129 String CreateSizeText( sal_uIntPtr nSize, sal_Bool bExtraBytes, sal_Bool bSmartExtraBytes )
130 {
131     String aUnitStr = ' ';
132     aUnitStr += String( SfxResId(STR_BYTES) );
133     sal_uIntPtr nSize1 = nSize;
134     sal_uIntPtr nSize2 = nSize1;
135     sal_uIntPtr nMega = 1024 * 1024;
136     sal_uIntPtr nGiga = nMega * 1024;
137     double fSize = nSize;
138     int nDec = 0;
139     sal_Bool bGB = sal_False;
140 
141     if ( nSize1 >= 10000 && nSize1 < nMega )
142     {
143         nSize1 /= 1024;
144         aUnitStr = ' ';
145         aUnitStr += String( SfxResId(STR_KB) );
146         fSize /= 1024;
147         nDec = 0;
148     }
149     else if ( nSize1 >= nMega && nSize1 < nGiga )
150     {
151         nSize1 /= nMega;
152         aUnitStr = ' ';
153         aUnitStr += String( SfxResId(STR_MB) );
154         fSize /= nMega;
155         nDec = 2;
156     }
157     else if ( nSize1 >= nGiga )
158     {
159         nSize1 /= nGiga;
160         aUnitStr = ' ';
161         aUnitStr += String( SfxResId(STR_GB) );
162         bGB = sal_True;
163         fSize /= nGiga;
164         nDec = 3;
165     }
166     const SvtSysLocale aSysLocale;
167     const LocaleDataWrapper& rLocaleWrapper = aSysLocale.GetLocaleData();
168     String aSizeStr( rLocaleWrapper.getNum( nSize1, 0 ) );
169     aSizeStr += aUnitStr;
170     if ( bExtraBytes && ( nSize1 < nSize2 ) )
171     {
172         aSizeStr = ::rtl::math::doubleToUString( fSize,
173                 rtl_math_StringFormat_F, nDec,
174                 rLocaleWrapper.getNumDecimalSep().GetChar(0) );
175         aSizeStr += aUnitStr;
176 
177         aSizeStr += DEFINE_CONST_UNICODE(" (");
178         aSizeStr += rLocaleWrapper.getNum( nSize2, 0 );
179         aSizeStr += ' ';
180         aSizeStr += String( SfxResId(STR_BYTES) );
181         aSizeStr += ')';
182     }
183     else if ( bGB && bSmartExtraBytes )
184     {
185         nSize1 = nSize / nMega;
186         aSizeStr = DEFINE_CONST_UNICODE(" (");
187         aSizeStr += rLocaleWrapper.getNum( nSize1, 0 );
188         aSizeStr += aUnitStr;
189         aSizeStr += ')';
190     }
191     return aSizeStr;
192 }
193 
194 String ConvertDateTime_Impl( const String& rName,
195     const util::DateTime& uDT, const LocaleDataWrapper& rWrapper )
196 {
197     Date aD(uDT.Day, uDT.Month, uDT.Year);
198     Time aT(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
199      const String pDelim ( DEFINE_CONST_UNICODE( ", "));
200      String aStr( rWrapper.getDate( aD ) );
201      aStr += pDelim;
202      aStr += rWrapper.getTime( aT, sal_True, sal_False );
203      String aAuthor = rName;
204      aAuthor.EraseLeadingChars();
205      if ( aAuthor.Len() )
206      {
207         aStr += pDelim;
208         aStr += aAuthor;
209      }
210      return aStr;
211 }
212 
213 //------------------------------------------------------------------------
214 
215 SfxDocumentInfoItem::SfxDocumentInfoItem()
216     : SfxStringItem()
217     , m_AutoloadDelay(0)
218     , m_AutoloadURL()
219     , m_isAutoloadEnabled(sal_False)
220     , m_DefaultTarget()
221     , m_TemplateName()
222     , m_Author()
223     , m_CreationDate()
224     , m_ModifiedBy()
225     , m_ModificationDate()
226     , m_PrintedBy()
227     , m_PrintDate()
228     , m_EditingCycles(0)
229     , m_EditingDuration(0)
230     , m_Description()
231     , m_Keywords()
232     , m_Subject()
233     , m_Title()
234     , m_bHasTemplate( sal_True )
235     , m_bDeleteUserData( sal_False )
236     , m_bUseUserData( sal_True )
237 {
238 }
239 
240 //------------------------------------------------------------------------
241 
242 SfxDocumentInfoItem::SfxDocumentInfoItem( const String& rFile,
243         const uno::Reference<document::XDocumentProperties>& i_xDocProps,
244         sal_Bool bIs )
245     : SfxStringItem( SID_DOCINFO, rFile )
246     , m_AutoloadDelay( i_xDocProps->getAutoloadSecs() )
247     , m_AutoloadURL( i_xDocProps->getAutoloadURL() )
248     , m_isAutoloadEnabled( (m_AutoloadDelay > 0) || m_AutoloadURL.getLength() )
249     , m_DefaultTarget( i_xDocProps->getDefaultTarget() )
250     , m_TemplateName( i_xDocProps->getTemplateName() )
251     , m_Author( i_xDocProps->getAuthor() )
252     , m_CreationDate( i_xDocProps->getCreationDate() )
253     , m_ModifiedBy( i_xDocProps->getModifiedBy() )
254     , m_ModificationDate( i_xDocProps->getModificationDate() )
255     , m_PrintedBy( i_xDocProps->getPrintedBy() )
256     , m_PrintDate( i_xDocProps->getPrintDate() )
257     , m_EditingCycles( i_xDocProps->getEditingCycles() )
258     , m_EditingDuration( i_xDocProps->getEditingDuration() )
259     , m_Description( i_xDocProps->getDescription() )
260     , m_Keywords( ::comphelper::string::convertCommaSeparated(
261                     i_xDocProps->getKeywords()) )
262     , m_Subject( i_xDocProps->getSubject() )
263     , m_Title( i_xDocProps->getTitle() )
264     , m_bHasTemplate( sal_True )
265     , m_bDeleteUserData( sal_False )
266     , m_bUseUserData( bIs )
267 {
268     try
269     {
270         Reference< beans::XPropertyContainer > xContainer = i_xDocProps->getUserDefinedProperties();
271         if ( xContainer.is() )
272         {
273             Reference < beans::XPropertySet > xSet( xContainer, UNO_QUERY );
274             const Sequence< beans::Property > lProps = xSet->getPropertySetInfo()->getProperties();
275             const beans::Property* pProps = lProps.getConstArray();
276             sal_Int32 nCount = lProps.getLength();
277             for ( sal_Int32 i = 0; i < nCount; ++i )
278             {
279                 // "fix" property? => not a custom property => ignore it!
280                 if (!(pProps[i].Attributes &
281                         ::com::sun::star::beans::PropertyAttribute::REMOVABLE))
282                 {
283                     DBG_ASSERT(false, "non-removable user-defined property?");
284                     continue;
285                 }
286 
287                 uno::Any aValue = xSet->getPropertyValue(pProps[i].Name);
288                 CustomProperty* pProp = new CustomProperty( pProps[i].Name, aValue );
289                 m_aCustomProperties.push_back( pProp );
290             }
291         }
292     }
293     catch ( Exception& ) {}
294 }
295 
296 //------------------------------------------------------------------------
297 
298 SfxDocumentInfoItem::SfxDocumentInfoItem( const SfxDocumentInfoItem& rItem )
299     : SfxStringItem( rItem )
300     , m_AutoloadDelay( rItem.getAutoloadDelay() )
301     , m_AutoloadURL( rItem.getAutoloadURL() )
302     , m_isAutoloadEnabled( rItem.isAutoloadEnabled() )
303     , m_DefaultTarget( rItem.getDefaultTarget() )
304     , m_TemplateName( rItem.getTemplateName() )
305     , m_Author( rItem.getAuthor() )
306     , m_CreationDate( rItem.getCreationDate() )
307     , m_ModifiedBy( rItem.getModifiedBy() )
308     , m_ModificationDate( rItem.getModificationDate() )
309     , m_PrintedBy( rItem.getPrintedBy() )
310     , m_PrintDate( rItem.getPrintDate() )
311     , m_EditingCycles( rItem.getEditingCycles() )
312     , m_EditingDuration( rItem.getEditingDuration() )
313     , m_Description( rItem.getDescription() )
314     , m_Keywords( rItem.getKeywords() )
315     , m_Subject( rItem.getSubject() )
316     , m_Title( rItem.getTitle() )
317     , m_bHasTemplate( rItem.m_bHasTemplate )
318     , m_bDeleteUserData( rItem.m_bDeleteUserData )
319     , m_bUseUserData( rItem.m_bUseUserData )
320 {
321     for ( sal_uInt32 i = 0; i < rItem.m_aCustomProperties.size(); i++ )
322     {
323         CustomProperty* pProp = new CustomProperty( rItem.m_aCustomProperties[i]->m_sName,
324                                                     rItem.m_aCustomProperties[i]->m_aValue );
325         m_aCustomProperties.push_back( pProp );
326     }
327 }
328 
329 //------------------------------------------------------------------------
330 
331 SfxDocumentInfoItem::~SfxDocumentInfoItem()
332 {
333     ClearCustomProperties();
334 }
335 
336 //------------------------------------------------------------------------
337 
338 SfxPoolItem* SfxDocumentInfoItem::Clone( SfxItemPool * ) const
339 {
340     return new SfxDocumentInfoItem( *this );
341 }
342 
343 //------------------------------------------------------------------------
344 
345 int SfxDocumentInfoItem::operator==( const SfxPoolItem& rItem) const
346 {
347     if (!(rItem.Type() == Type() && SfxStringItem::operator==(rItem))) {
348         return false;
349     }
350     const SfxDocumentInfoItem& rInfoItem(
351         static_cast<const SfxDocumentInfoItem&>(rItem));
352 
353     return
354          m_AutoloadDelay        == rInfoItem.m_AutoloadDelay     &&
355          m_AutoloadURL          == rInfoItem.m_AutoloadURL       &&
356          m_isAutoloadEnabled    == rInfoItem.m_isAutoloadEnabled &&
357          m_DefaultTarget        == rInfoItem.m_DefaultTarget     &&
358          m_Author               == rInfoItem.m_Author            &&
359          m_CreationDate         == rInfoItem.m_CreationDate      &&
360          m_ModifiedBy           == rInfoItem.m_ModifiedBy        &&
361          m_ModificationDate     == rInfoItem.m_ModificationDate  &&
362          m_PrintedBy            == rInfoItem.m_PrintedBy         &&
363          m_PrintDate            == rInfoItem.m_PrintDate         &&
364          m_EditingCycles        == rInfoItem.m_EditingCycles     &&
365          m_EditingDuration      == rInfoItem.m_EditingDuration   &&
366          m_Description          == rInfoItem.m_Description       &&
367          m_Keywords             == rInfoItem.m_Keywords          &&
368          m_Subject              == rInfoItem.m_Subject           &&
369          m_Title                == rInfoItem.m_Title             &&
370          m_aCustomProperties.size() == rInfoItem.m_aCustomProperties.size() &&
371          std::equal(m_aCustomProperties.begin(), m_aCustomProperties.end(),
372             rInfoItem.m_aCustomProperties.begin());
373 }
374 
375 //------------------------------------------------------------------------
376 
377 void SfxDocumentInfoItem::resetUserData(const ::rtl::OUString & i_rAuthor)
378 {
379     setAuthor(i_rAuthor);
380     DateTime now;
381     setCreationDate( util::DateTime(
382         now.Get100Sec(), now.GetSec(), now.GetMin(), now.GetHour(),
383         now.GetDay(), now.GetMonth(), now.GetYear() ) );
384     setModifiedBy(::rtl::OUString());
385     setPrintedBy(::rtl::OUString());
386     setModificationDate(util::DateTime());
387     setPrintDate(util::DateTime());
388     setEditingDuration(0);
389     setEditingCycles(1);
390 }
391 
392 //------------------------------------------------------------------------
393 
394 void SfxDocumentInfoItem::UpdateDocumentInfo(
395         const uno::Reference<document::XDocumentProperties>& i_xDocProps,
396         bool i_bDoNotUpdateUserDefined) const
397 {
398     if (isAutoloadEnabled()) {
399         i_xDocProps->setAutoloadSecs(getAutoloadDelay());
400         i_xDocProps->setAutoloadURL(getAutoloadURL());
401     } else {
402         i_xDocProps->setAutoloadSecs(0);
403         i_xDocProps->setAutoloadURL(::rtl::OUString());
404     }
405     i_xDocProps->setDefaultTarget(getDefaultTarget());
406 //    i_xDocProps->setTemplateName(getTemplateName());
407     i_xDocProps->setAuthor(getAuthor());
408     i_xDocProps->setCreationDate(getCreationDate());
409     i_xDocProps->setModifiedBy(getModifiedBy());
410     i_xDocProps->setModificationDate(getModificationDate());
411     i_xDocProps->setPrintedBy(getPrintedBy());
412     i_xDocProps->setPrintDate(getPrintDate());
413     i_xDocProps->setEditingCycles(getEditingCycles());
414     i_xDocProps->setEditingDuration(getEditingDuration());
415     i_xDocProps->setDescription(getDescription());
416     i_xDocProps->setKeywords(
417         ::comphelper::string::convertCommaSeparated(getKeywords()));
418     i_xDocProps->setSubject(getSubject());
419     i_xDocProps->setTitle(getTitle());
420 
421     // this is necessary in case of replaying a recorded macro:
422     // in this case, the macro may contain the 4 old user-defined DocumentInfo
423     // fields, but not any of the DocumentInfo properties;
424     // as a consequence, most of the UserDefined properties of the
425     // DocumentProperties would be summarily deleted here, which does not
426     // seem like a good idea.
427     if (i_bDoNotUpdateUserDefined)
428         return;
429 
430     try
431     {
432         Reference< beans::XPropertyContainer > xContainer = i_xDocProps->getUserDefinedProperties();
433         Reference < beans::XPropertySet > xSet( xContainer, UNO_QUERY );
434         Reference< beans::XPropertySetInfo > xSetInfo = xSet->getPropertySetInfo();
435         const Sequence< beans::Property > lProps = xSetInfo->getProperties();
436         const beans::Property* pProps = lProps.getConstArray();
437         sal_Int32 nCount = lProps.getLength();
438         for ( sal_Int32 j = 0; j < nCount; ++j )
439         {
440             if ((pProps[j].Attributes &
441                     ::com::sun::star::beans::PropertyAttribute::REMOVABLE))
442             {
443                 xContainer->removeProperty( pProps[j].Name );
444             }
445         }
446 
447         for ( sal_uInt32 k = 0; k < m_aCustomProperties.size(); ++k )
448         {
449             try
450             {
451                 xContainer->addProperty( m_aCustomProperties[k]->m_sName,
452                     beans::PropertyAttribute::REMOVABLE, m_aCustomProperties[k]->m_aValue );
453             }
454             catch ( Exception& )
455             {
456                 DBG_ERRORFILE( "SfxDocumentInfoItem::updateDocumentInfo(): exception while adding custom properties" );
457             }
458         }
459     }
460     catch ( Exception& )
461     {
462         DBG_ERRORFILE( "SfxDocumentInfoItem::updateDocumentInfo(): exception while removing custom properties" );
463     }
464 }
465 
466 //------------------------------------------------------------------------
467 
468 sal_Bool SfxDocumentInfoItem::IsDeleteUserData() const
469 {
470     return m_bDeleteUserData;
471 }
472 
473 void SfxDocumentInfoItem::SetDeleteUserData( sal_Bool bSet )
474 {
475     m_bDeleteUserData = bSet;
476 }
477 
478 sal_Bool SfxDocumentInfoItem::IsUseUserData() const
479 {
480     return m_bUseUserData;
481 }
482 
483 void SfxDocumentInfoItem::SetUseUserData( sal_Bool bSet )
484 {
485     m_bUseUserData = bSet;
486 }
487 
488 std::vector< CustomProperty* > SfxDocumentInfoItem::GetCustomProperties() const
489 {
490     std::vector< CustomProperty* > aRet;
491     for ( sal_uInt32 i = 0; i < m_aCustomProperties.size(); i++ )
492     {
493         CustomProperty* pProp = new CustomProperty( m_aCustomProperties[i]->m_sName,
494                                                     m_aCustomProperties[i]->m_aValue );
495         aRet.push_back( pProp );
496     }
497 
498     return aRet;
499 }
500 
501 void SfxDocumentInfoItem::ClearCustomProperties()
502 {
503     for ( sal_uInt32 i = 0; i < m_aCustomProperties.size(); i++ )
504         delete m_aCustomProperties[i];
505     m_aCustomProperties.clear();
506 }
507 
508 void SfxDocumentInfoItem::AddCustomProperty( const ::rtl::OUString& sName, const Any& rValue )
509 {
510     CustomProperty* pProp = new CustomProperty( sName, rValue );
511     m_aCustomProperties.push_back( pProp );
512 }
513 
514 sal_Bool SfxDocumentInfoItem::QueryValue( Any& rVal, sal_uInt8 nMemberId ) const
515 {
516     String aValue;
517     sal_Int32 nValue = 0;
518     sal_Bool bValue = sal_False;
519     sal_Bool bIsInt = sal_False;
520     sal_Bool bIsString = sal_False;
521     nMemberId &= ~CONVERT_TWIPS;
522     switch ( nMemberId )
523     {
524         case MID_DOCINFO_USEUSERDATA:
525             bValue = IsUseUserData();
526             break;
527         case MID_DOCINFO_DELETEUSERDATA:
528             bValue = IsDeleteUserData();
529             break;
530         case MID_DOCINFO_AUTOLOADENABLED:
531             bValue = isAutoloadEnabled();
532             break;
533         case MID_DOCINFO_AUTOLOADSECS:
534             bIsInt = sal_True;
535             nValue = getAutoloadDelay();
536             break;
537         case MID_DOCINFO_AUTOLOADURL:
538             bIsString = sal_True;
539             aValue = getAutoloadURL();
540             break;
541         case MID_DOCINFO_DEFAULTTARGET:
542             bIsString = sal_True;
543             aValue = getDefaultTarget();
544             break;
545         case MID_DOCINFO_DESCRIPTION:
546             bIsString = sal_True;
547             aValue = getDescription();
548             break;
549         case MID_DOCINFO_KEYWORDS:
550             bIsString = sal_True;
551             aValue = getKeywords();
552             break;
553         case MID_DOCINFO_SUBJECT:
554             bIsString = sal_True;
555             aValue = getSubject();
556             break;
557         case MID_DOCINFO_TITLE:
558             bIsString = sal_True;
559             aValue = getTitle();
560             break;
561         default:
562             DBG_ERROR("Wrong MemberId!");
563             return sal_False;
564      }
565 
566     if ( bIsString )
567         rVal <<= ::rtl::OUString( aValue );
568     else if ( bIsInt )
569         rVal <<= nValue;
570     else
571         rVal <<= bValue;
572     return sal_True;
573 }
574 
575 sal_Bool SfxDocumentInfoItem::PutValue( const Any& rVal, sal_uInt8 nMemberId )
576 {
577     ::rtl::OUString aValue;
578     sal_Int32 nValue=0;
579     sal_Bool bValue = sal_False;
580     sal_Bool bRet = sal_False;
581     nMemberId &= ~CONVERT_TWIPS;
582     switch ( nMemberId )
583     {
584         case MID_DOCINFO_USEUSERDATA:
585             bRet = (rVal >>= bValue);
586             if ( bRet )
587                 SetUseUserData( bValue );
588             break;
589         case MID_DOCINFO_DELETEUSERDATA:
590             // QUESTION: deleting user data was done here; seems to be superfluous!
591             bRet = (rVal >>= bValue);
592             if ( bRet )
593                 SetDeleteUserData( bValue );
594             break;
595         case MID_DOCINFO_AUTOLOADENABLED:
596             bRet = (rVal >>= bValue);
597             if ( bRet )
598                 setAutoloadEnabled(bValue);
599             break;
600         case MID_DOCINFO_AUTOLOADSECS:
601             bRet = (rVal >>= nValue);
602             if ( bRet )
603                 setAutoloadDelay(nValue);
604             break;
605         case MID_DOCINFO_AUTOLOADURL:
606             bRet = (rVal >>= aValue);
607             if ( bRet )
608                 setAutoloadURL(aValue);
609             break;
610         case MID_DOCINFO_DEFAULTTARGET:
611             bRet = (rVal >>= aValue);
612             if ( bRet )
613                 setDefaultTarget(aValue);
614             break;
615         case MID_DOCINFO_DESCRIPTION:
616             bRet = (rVal >>= aValue);
617             if ( bRet )
618                 setDescription(aValue);
619             break;
620         case MID_DOCINFO_KEYWORDS:
621             bRet = (rVal >>= aValue);
622             if ( bRet )
623                 setKeywords(aValue);
624             break;
625         case MID_DOCINFO_SUBJECT:
626             bRet = (rVal >>= aValue);
627             if ( bRet )
628                 setSubject(aValue);
629             break;
630         case MID_DOCINFO_TITLE:
631             bRet = (rVal >>= aValue);
632             if ( bRet )
633                 setTitle(aValue);
634             break;
635         default:
636             DBG_ERROR("Wrong MemberId!");
637             return sal_False;
638     }
639 
640     return bRet;
641 }
642 
643 //------------------------------------------------------------------------
644 
645 SfxDocumentDescPage::SfxDocumentDescPage( Window * pParent, const SfxItemSet& rItemSet )  :
646 
647     SfxTabPage( pParent, SfxResId( TP_DOCINFODESC ), rItemSet ),
648 
649     aTitleFt    ( this, SfxResId( FT_TITLE ) ),
650     aTitleEd    ( this, SfxResId( ED_TITLE ) ),
651     aThemaFt    ( this, SfxResId( FT_THEMA ) ),
652     aThemaEd    ( this, SfxResId( ED_THEMA ) ),
653     aKeywordsFt ( this, SfxResId( FT_KEYWORDS ) ),
654     aKeywordsEd ( this, SfxResId( ED_KEYWORDS ) ),
655     aCommentFt  ( this, SfxResId( FT_COMMENT ) ),
656     aCommentEd  ( this, SfxResId( ED_COMMENT ) ),
657 
658     pInfoItem   ( NULL )
659 
660 {
661     FreeResource();
662 }
663 
664 //------------------------------------------------------------------------
665 
666 SfxTabPage *SfxDocumentDescPage::Create(Window *pParent, const SfxItemSet &rItemSet)
667 {
668      return new SfxDocumentDescPage(pParent, rItemSet);
669 }
670 
671 //------------------------------------------------------------------------
672 
673 sal_Bool SfxDocumentDescPage::FillItemSet(SfxItemSet &rSet)
674 {
675     // Pruefung, ob eine Aenderung vorliegt
676     const sal_Bool bTitleMod = aTitleEd.IsModified();
677     const sal_Bool bThemeMod = aThemaEd.IsModified();
678     const sal_Bool bKeywordsMod = aKeywordsEd.IsModified();
679     const sal_Bool bCommentMod = aCommentEd.IsModified();
680     if( !( bTitleMod || bThemeMod || bKeywordsMod || bCommentMod ) )
681     {
682         return sal_False;
683     }
684 
685     // Erzeugung der Ausgabedaten
686     const SfxPoolItem* pItem = NULL;
687     SfxDocumentInfoItem* pInfo = NULL;
688     SfxTabDialog* pDlg = GetTabDialog();
689     const SfxItemSet* pExSet = NULL;
690 
691     if ( pDlg )
692         pExSet = pDlg->GetExampleSet();
693 
694     if ( pExSet && SFX_ITEM_SET != pExSet->GetItemState( SID_DOCINFO, sal_True, &pItem ) )
695         pInfo = pInfoItem;
696     else if ( pItem )
697         pInfo = new SfxDocumentInfoItem( *(const SfxDocumentInfoItem *)pItem );
698 
699     if ( !pInfo )
700     {
701         DBG_ERRORFILE( "SfxDocumentDescPage::FillItemSet(): no item found" );
702         return sal_False;
703     }
704 
705     if( bTitleMod )
706     {
707         pInfo->setTitle( aTitleEd.GetText() );
708     }
709     if( bThemeMod )
710     {
711         pInfo->setSubject( aThemaEd.GetText() );
712     }
713     if( bKeywordsMod )
714     {
715         pInfo->setKeywords( aKeywordsEd.GetText() );
716     }
717     if( bCommentMod )
718     {
719         pInfo->setDescription( aCommentEd.GetText() );
720     }
721     rSet.Put( SfxDocumentInfoItem( *pInfo ) );
722     if( pInfo != pInfoItem )
723     {
724         delete pInfo;
725     }
726 
727     return sal_True;
728 }
729 
730 //------------------------------------------------------------------------
731 
732 void SfxDocumentDescPage::Reset(const SfxItemSet &rSet)
733 {
734      pInfoItem = &(SfxDocumentInfoItem &)rSet.Get(SID_DOCINFO);
735 
736      aTitleEd.SetText( pInfoItem->getTitle() );
737      aThemaEd.SetText( pInfoItem->getSubject() );
738      aKeywordsEd.SetText( pInfoItem->getKeywords() );
739      aCommentEd.SetText( pInfoItem->getDescription() );
740 
741      SFX_ITEMSET_ARG( &rSet, pROItem, SfxBoolItem, SID_DOC_READONLY, sal_False );
742      if ( pROItem && pROItem->GetValue() )
743      {
744         aTitleEd.SetReadOnly( sal_True );
745         aThemaEd.SetReadOnly( sal_True );
746         aKeywordsEd.SetReadOnly( sal_True );
747         aCommentEd.SetReadOnly( sal_True );
748     }
749 }
750 
751 //------------------------------------------------------------------------
752 
753 namespace
754 {
755     String GetDateTimeString( sal_Int32 _nDate, sal_Int32 _nTime )
756     {
757         LocaleDataWrapper aWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() );
758 
759         Date aDate( _nDate );
760         Time aTime( _nTime );
761         String aStr( aWrapper.getDate( aDate ) );
762         aStr.AppendAscii( ", " );
763         aStr += aWrapper.getTime( aTime );
764         return aStr;
765     }
766 
767     // copy from xmlsecurity/source/dialog/resourcemanager.cxx
768     String GetContentPart( const String& _rRawString, const String& _rPartId )
769     {
770         String      s;
771 
772         xub_StrLen  nContStart = _rRawString.Search( _rPartId );
773         if( nContStart != STRING_NOTFOUND )
774         {
775             nContStart = nContStart + _rPartId.Len();
776             ++nContStart;                   // now it's start of content, directly after Id
777 
778             xub_StrLen  nContEnd = _rRawString.Search( sal_Unicode( ',' ), nContStart );
779 
780             s = String( _rRawString, nContStart, nContEnd - nContStart );
781         }
782 
783         return s;
784     }
785 
786 }
787 
788 SfxDocumentPage::SfxDocumentPage( Window* pParent, const SfxItemSet& rItemSet ) :
789 
790     SfxTabPage( pParent, SfxResId( TP_DOCINFODOC ), rItemSet ),
791 
792     aBmp1           ( this, SfxResId( BMP_FILE_1 ) ),
793     aNameED         ( this, SfxResId( ED_FILE_NAME ) ),
794 
795     aLine1FL        ( this, SfxResId( FL_FILE_1 ) ),
796     aTypeFT         ( this, SfxResId( FT_FILE_TYP ) ),
797     aShowTypeFT     ( this, SfxResId( FT_FILE_SHOW_TYP ) ),
798     aReadOnlyCB     ( this, SfxResId( CB_FILE_READONLY ) ),
799     aFileFt         ( this, SfxResId( FT_FILE ) ),
800     aFileValFt      ( this, SfxResId( FT_FILE_VAL ) ),
801     aSizeFT         ( this, SfxResId( FT_FILE_SIZE ) ),
802     aShowSizeFT     ( this, SfxResId( FT_FILE_SHOW_SIZE ) ),
803 
804     aLine2FL        ( this, SfxResId( FL_FILE_2 ) ),
805     aCreateFt       ( this, SfxResId( FT_CREATE ) ),
806     aCreateValFt    ( this, SfxResId( FT_CREATE_VAL ) ),
807     aChangeFt       ( this, SfxResId( FT_CHANGE ) ),
808     aChangeValFt    ( this, SfxResId( FT_CHANGE_VAL ) ),
809     aSignedFt       ( this, SfxResId( FT_SIGNED ) ),
810     aSignedValFt    ( this, SfxResId( FT_SIGNED_VAL ) ),
811     aSignatureBtn   ( this, SfxResId( BTN_SIGNATURE ) ),
812     aPrintFt        ( this, SfxResId( FT_PRINT ) ),
813     aPrintValFt     ( this, SfxResId( FT_PRINT_VAL ) ),
814     aTimeLogFt      ( this, SfxResId( FT_TIMELOG ) ),
815     aTimeLogValFt   ( this, SfxResId( FT_TIMELOG_VAL ) ),
816     aDocNoFt        ( this, SfxResId( FT_DOCNO ) ),
817     aDocNoValFt     ( this, SfxResId( FT_DOCNO_VAL ) ),
818     aUseUserDataCB  ( this, SfxResId( CB_USE_USERDATA ) ),
819     aDeleteBtn      ( this, SfxResId( BTN_DELETE ) ),
820 
821     aLine3FL        ( this, SfxResId( FL_FILE_3 ) ),
822     aTemplFt        ( this, SfxResId( FT_TEMPL ) ),
823     aTemplValFt     ( this, SfxResId( FT_TEMPL_VAL ) ),
824 
825     aUnknownSize    ( SfxResId( STR_UNKNOWNSIZE ) ),
826     aMultiSignedStr ( SfxResId( STR_MULTSIGNED ) ),
827 
828     bEnableUseUserData  ( sal_False ),
829     bHandleDelete       ( sal_False )
830 
831 {
832     aNameED.SetAccessibleName(String(SfxResId(EDIT_FILE_NAME)));
833     FreeResource();
834 
835     ImplUpdateSignatures();
836     aDeleteBtn.SetClickHdl( LINK( this, SfxDocumentPage, DeleteHdl ) );
837     aSignatureBtn.SetClickHdl( LINK( this, SfxDocumentPage, SignatureHdl ) );
838 
839     // if the button text is too wide, then broaden it
840     const long nOffset = 12;
841     String sText = aSignatureBtn.GetText();
842     long nTxtW = aSignatureBtn.GetTextWidth( sText );
843     if ( sText.Search( '~' ) == STRING_NOTFOUND )
844         nTxtW += nOffset;
845     long nBtnW = aSignatureBtn.GetSizePixel().Width();
846     if ( nTxtW >= nBtnW )
847     {
848         long nDelta = Max( nTxtW - nBtnW, nOffset/3 );
849         Size aNewSize = aSignatureBtn.GetSizePixel();
850         aNewSize.Width() += nDelta;
851         aSignatureBtn.SetSizePixel( aNewSize );
852         aDeleteBtn.SetSizePixel( aNewSize );
853         // and give them a new position
854         Point aNewPos = aSignatureBtn.GetPosPixel();
855         aNewPos.X() -= nDelta;
856         aSignatureBtn.SetPosPixel( aNewPos );
857         aNewPos = aDeleteBtn.GetPosPixel();
858         aNewPos.X() -= nDelta;
859         aDeleteBtn.SetPosPixel( aNewPos );
860 
861         aNewSize = aSignedValFt.GetSizePixel();
862         aNewSize.Width() -= nDelta;
863         aSignedValFt.SetSizePixel( aNewSize );
864         aNewSize = aUseUserDataCB.GetSizePixel();
865         aNewSize.Width() -= nDelta;
866         aUseUserDataCB.SetSizePixel( aNewSize );
867     }
868     // See i96288
869     // Check if the document signature command is enabled
870     // on the main list enable/disable the pushbutton accordingly
871     SvtCommandOptions aCmdOptions;
872     if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED,
873                              rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( DOCUMENT_SIGNATURE_MENU_CMD ) ) ) )
874         aSignatureBtn.Disable();
875 }
876 
877 //------------------------------------------------------------------------
878 
879 IMPL_LINK( SfxDocumentPage, DeleteHdl, PushButton*, EMPTYARG )
880 {
881     String aName;
882     if ( bEnableUseUserData && aUseUserDataCB.IsChecked() )
883         aName = SvtUserOptions().GetFullName();
884     LocaleDataWrapper aLocaleWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() );
885     DateTime now;
886     util::DateTime uDT(
887         now.Get100Sec(), now.GetSec(), now.GetMin(), now.GetHour(),
888         now.GetDay(), now.GetMonth(), now.GetYear() );
889     aCreateValFt.SetText( ConvertDateTime_Impl( aName, uDT, aLocaleWrapper ) );
890     XubString aEmpty;
891     aChangeValFt.SetText( aEmpty );
892     aPrintValFt.SetText( aEmpty );
893     const Time aTime( 0 );
894     aTimeLogValFt.SetText( aLocaleWrapper.getDuration( aTime ) );
895     aDocNoValFt.SetText( '1' );
896     bHandleDelete = sal_True;
897     return 0;
898 }
899 
900 IMPL_LINK( SfxDocumentPage, SignatureHdl, PushButton*, EMPTYARG )
901 {
902     SfxObjectShell* pDoc = SfxObjectShell::Current();
903     if( pDoc )
904     {
905         pDoc->SignDocumentContent();
906 
907         ImplUpdateSignatures();
908     }
909 
910     return 0;
911 }
912 
913 void SfxDocumentPage::ImplUpdateSignatures()
914 {
915     SfxObjectShell* pDoc = SfxObjectShell::Current();
916     if( pDoc )
917     {
918         SfxMedium* pMedium = pDoc->GetMedium();
919         if ( pMedium && pMedium->GetName().Len() && pMedium->GetStorage().is() )
920         {
921             Reference< security::XDocumentDigitalSignatures > xD(
922                 comphelper::getProcessServiceFactory()->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) ) ), uno::UNO_QUERY );
923 
924             if( xD.is() )
925             {
926                 String s;
927                 Sequence< security::DocumentSignatureInformation > aInfos;
928                 aInfos = xD->verifyDocumentContentSignatures( pMedium->GetZipStorageToSign_Impl(),
929                                                                 uno::Reference< io::XInputStream >() );
930                 if( aInfos.getLength() > 1 )
931                 {
932                     s = aMultiSignedStr;
933                 }
934                 else if( aInfos.getLength() == 1 )
935                 {
936                     String aCN_Id( String::CreateFromAscii( "CN" ) );
937                     const security::DocumentSignatureInformation& rInfo = aInfos[ 0 ];
938                     s = GetDateTimeString( rInfo.SignatureDate, rInfo.SignatureTime );
939                     s.AppendAscii( ", " );
940                     s += GetContentPart( rInfo.Signer->getSubjectName(), aCN_Id );
941                 }
942                 aSignedValFt.SetText( s );
943             }
944         }
945     }
946 }
947 
948 //------------------------------------------------------------------------
949 
950 SfxTabPage* SfxDocumentPage::Create( Window* pParent, const SfxItemSet& rItemSet )
951 {
952      return new SfxDocumentPage( pParent, rItemSet );
953 }
954 
955 //------------------------------------------------------------------------
956 
957 void SfxDocumentPage::EnableUseUserData()
958 {
959     bEnableUseUserData = sal_True;
960     aUseUserDataCB.Show();
961     aDeleteBtn.Show();
962 }
963 
964 //------------------------------------------------------------------------
965 
966 sal_Bool SfxDocumentPage::FillItemSet( SfxItemSet& rSet )
967 {
968     sal_Bool bRet = sal_False;
969 
970     if ( !bHandleDelete && bEnableUseUserData &&
971          aUseUserDataCB.GetState() != aUseUserDataCB.GetSavedValue() &&
972          GetTabDialog() && GetTabDialog()->GetExampleSet() )
973     {
974         const SfxItemSet* pExpSet = GetTabDialog()->GetExampleSet();
975         const SfxPoolItem* pItem;
976 
977         if ( pExpSet && SFX_ITEM_SET == pExpSet->GetItemState( SID_DOCINFO, sal_True, &pItem ) )
978         {
979             SfxDocumentInfoItem* pInfoItem = (SfxDocumentInfoItem*)pItem;
980             sal_Bool bUseData = ( STATE_CHECK == aUseUserDataCB.GetState() );
981             pInfoItem->SetUseUserData( bUseData );
982 /*
983             if ( !bUseData )
984             {
985                 // "Benutzerdaten verwenden" ausgeschaltet ->
986                 // den Benutzer aus den Stamps l"oschen
987                 String aEmptyUser;
988                 aInfo.SetCreated(
989                     SfxStamp( aEmptyUser, aInfo.GetCreated().GetTime() ) );
990                 aInfo.SetChanged(
991                     SfxStamp( aEmptyUser, aInfo.GetChanged().GetTime() ) );
992                 aInfo.SetPrinted(
993                     SfxStamp( aEmptyUser, aInfo.GetPrinted().GetTime() ) );
994             }
995 */
996             rSet.Put( SfxDocumentInfoItem( *pInfoItem ) );
997             bRet = sal_True;
998         }
999     }
1000 
1001     if ( bHandleDelete )
1002     {
1003         const SfxItemSet* pExpSet = GetTabDialog()->GetExampleSet();
1004         const SfxPoolItem* pItem;
1005         if ( pExpSet && SFX_ITEM_SET == pExpSet->GetItemState( SID_DOCINFO, sal_True, &pItem ) )
1006         {
1007             SfxDocumentInfoItem* pInfoItem = (SfxDocumentInfoItem*)pItem;
1008             sal_Bool bUseAuthor = bEnableUseUserData && aUseUserDataCB.IsChecked();
1009             SfxDocumentInfoItem newItem( *pInfoItem );
1010             newItem.resetUserData( bUseAuthor
1011                 ? SvtUserOptions().GetFullName()
1012                 : ::rtl::OUString() );
1013             pInfoItem->SetUseUserData( STATE_CHECK == aUseUserDataCB.GetState() );
1014             newItem.SetUseUserData( STATE_CHECK == aUseUserDataCB.GetState() );
1015 
1016             newItem.SetDeleteUserData( sal_True );
1017             rSet.Put( newItem );
1018             bRet = sal_True;
1019         }
1020     }
1021 
1022     if ( aNameED.IsModified() && aNameED.GetText().Len() )
1023     {
1024         rSet.Put( SfxStringItem( ID_FILETP_TITLE, aNameED.GetText() ) );
1025         bRet = sal_True;
1026     }
1027 
1028     if ( /* aReadOnlyCB.IsModified() */ sal_True )
1029     {
1030         rSet.Put( SfxBoolItem( ID_FILETP_READONLY, aReadOnlyCB.IsChecked() ) );
1031         bRet = sal_True;
1032     }
1033 
1034     return bRet;
1035 }
1036 
1037 //------------------------------------------------------------------------
1038 
1039 void SfxDocumentPage::Reset( const SfxItemSet& rSet )
1040 {
1041     // Bestimmung der Dokumentinformationen
1042     const SfxDocumentInfoItem *pInfoItem =
1043         &(const SfxDocumentInfoItem &)rSet.Get(SID_DOCINFO);
1044 
1045     // template data
1046     if ( pInfoItem->HasTemplate() )
1047     {
1048         aTemplValFt.SetText( pInfoItem->getTemplateName() );
1049     }
1050     else
1051     {
1052         aTemplFt.Hide();
1053         aTemplValFt.Hide();
1054     }
1055 
1056     // determine file name
1057     String aFile( pInfoItem->GetValue() );
1058     String aFactory( aFile );
1059     if ( aFile.Len() > 2 && aFile.GetChar(0) == '[' )
1060     {
1061         sal_uInt16 nPos = aFile.Search( ']' );
1062         aFactory = aFile.Copy( 1, nPos-1  );
1063         aFile = aFile.Copy( nPos+1 );
1064     }
1065 
1066     // determine name
1067     String aName;
1068     const SfxPoolItem* pItem = 0;
1069     if ( SFX_ITEM_SET != rSet.GetItemState( ID_FILETP_TITLE, sal_False, &pItem ) )
1070     {
1071         INetURLObject aURL(aFile);
1072         aName = aURL.GetName( INetURLObject::DECODE_WITH_CHARSET );
1073         if ( !aName.Len() || aURL.GetProtocol() == INET_PROT_PRIVATE )
1074             aName = String( SfxResId( STR_NONAME ) );
1075         aNameED.SetReadOnly( sal_True );
1076     }
1077     else
1078     {
1079         DBG_ASSERT( pItem->IsA( TYPE( SfxStringItem ) ), "SfxDocumentPage:<SfxStringItem> erwartet" );
1080         aName = ( ( SfxStringItem* ) pItem )->GetValue();
1081     }
1082     aNameED.SetText( aName );
1083     aNameED.ClearModifyFlag();
1084 
1085     // determine RO-Flag
1086     if ( SFX_ITEM_UNKNOWN == rSet.GetItemState( ID_FILETP_READONLY, sal_False, &pItem )
1087          || !pItem )
1088         aReadOnlyCB.Hide();
1089     else
1090         aReadOnlyCB.Check( ( (SfxBoolItem*)pItem )->GetValue() );
1091 
1092     // determine context symbol
1093     INetURLObject aURL;
1094     aURL.SetSmartProtocol( INET_PROT_FILE );
1095     aURL.SetSmartURL( aFactory);
1096     const String& rMainURL = aURL.GetMainURL( INetURLObject::NO_DECODE );
1097     aBmp1.SetImage( SvFileInformationManager::GetImage( aURL, sal_True ) );
1098 
1099     // determine size and type
1100     String aSizeText( aUnknownSize );
1101     if ( aURL.GetProtocol() == INET_PROT_FILE )
1102         aSizeText = CreateSizeText( SfxContentHelper::GetSize( aURL.GetMainURL( INetURLObject::NO_DECODE ) ) );
1103     aShowSizeFT.SetText( aSizeText );
1104 
1105     String aDescription = SvFileInformationManager::GetDescription( INetURLObject(rMainURL) );
1106     if ( aDescription.Len() == 0 )
1107         aDescription = String( SfxResId( STR_SFX_NEWOFFICEDOC ) );
1108     aShowTypeFT.SetText( aDescription );
1109 
1110     // determine location
1111     aURL.SetSmartURL( aFile);
1112     if ( aURL.GetProtocol() == INET_PROT_FILE )
1113     {
1114         INetURLObject aPath( aURL );
1115         aPath.setFinalSlash();
1116         aPath.removeSegment();
1117         // we know it's a folder -> don't need the final slash, but it's better for WB_PATHELLIPSIS
1118         aPath.removeFinalSlash();
1119         String aText( aPath.PathToFileName() ); //! (pb) MaxLen?
1120         aFileValFt.SetText( aText );
1121     }
1122     else if ( aURL.GetProtocol() != INET_PROT_PRIVATE )
1123         aFileValFt.SetText( aURL.GetPartBeforeLastName() );
1124 
1125     // handle access data
1126     sal_Bool m_bUseUserData = pInfoItem->IsUseUserData();
1127     LocaleDataWrapper aLocaleWrapper( ::comphelper::getProcessServiceFactory(), Application::GetSettings().GetLocale() );
1128     aCreateValFt.SetText( ConvertDateTime_Impl( pInfoItem->getAuthor(),
1129         pInfoItem->getCreationDate(), aLocaleWrapper ) );
1130     util::DateTime aTime( pInfoItem->getModificationDate() );
1131 //  if ( aTime.IsValid() )
1132     if ( aTime.Month > 0 )
1133         aChangeValFt.SetText( ConvertDateTime_Impl(
1134             pInfoItem->getModifiedBy(), aTime, aLocaleWrapper ) );
1135     aTime = pInfoItem->getPrintDate();
1136 //  if ( aTime.IsValid())
1137     if ( aTime.Month > 0 )
1138         aPrintValFt.SetText( ConvertDateTime_Impl( pInfoItem->getPrintedBy(),
1139             aTime, aLocaleWrapper ) );
1140     const long nTime = pInfoItem->getEditingDuration();
1141     if ( m_bUseUserData )
1142     {
1143         const Time aT( nTime/3600, (nTime%3600)/60, nTime%60 );
1144         aTimeLogValFt.SetText( aLocaleWrapper.getDuration( aT ) );
1145         aDocNoValFt.SetText( String::CreateFromInt32(
1146             pInfoItem->getEditingCycles() ) );
1147     }
1148 
1149     TriState eState = (TriState)m_bUseUserData;
1150 
1151     if ( STATE_DONTKNOW == eState )
1152         aUseUserDataCB.EnableTriState( sal_True );
1153 
1154     aUseUserDataCB.SetState( eState );
1155     aUseUserDataCB.SaveValue();
1156     aUseUserDataCB.Enable( bEnableUseUserData );
1157     bHandleDelete = sal_False;
1158     aDeleteBtn.Enable( bEnableUseUserData );
1159 }
1160 
1161 //------------------------------------------------------------------------
1162 
1163 SfxInternetPage::SfxInternetPage( Window* pParent, const SfxItemSet& rItemSet ) :
1164 
1165     SfxTabPage( pParent, SfxResId( TP_DOCINFORELOAD ), rItemSet ),
1166 
1167     aRBNoAutoUpdate     ( this, SfxResId( RB_NOAUTOUPDATE       ) ),
1168 
1169     aRBReloadUpdate     ( this, SfxResId( RB_RELOADUPDATE       ) ),
1170 
1171     aRBForwardUpdate    ( this, SfxResId( RB_FORWARDUPDATE      ) ),
1172     aFTEvery            ( this, SfxResId( FT_EVERY              ) ),
1173     aNFReload           ( this, SfxResId( ED_RELOAD         ) ),
1174     aFTReloadSeconds    ( this, SfxResId( FT_RELOADSECS     ) ),
1175     aFTAfter            ( this, SfxResId( FT_AFTER              ) ),
1176     aNFAfter            ( this, SfxResId( ED_FORWARD            ) ),
1177     aFTAfterSeconds     ( this, SfxResId( FT_FORWARDSECS        ) ),
1178     aFTURL              ( this, SfxResId( FT_URL                ) ),
1179     aEDForwardURL       ( this, SfxResId( ED_URL                ) ),
1180     aPBBrowseURL        ( this, SfxResId( PB_BROWSEURL          ) ),
1181     aFTFrame            ( this, SfxResId( FT_FRAME              ) ),
1182     aCBFrame            ( this, SfxResId( CB_FRAME              ) ),
1183 
1184     aForwardErrorMessg  (       SfxResId( STR_FORWARD_ERRMSSG   ) ),
1185     pInfoItem           ( NULL ),
1186     pFileDlg            ( NULL ),
1187     eState              ( S_Init )
1188 
1189 {
1190     FreeResource();
1191     pInfoItem = &( SfxDocumentInfoItem& ) rItemSet.Get( SID_DOCINFO );
1192     TargetList          aList;
1193     SfxViewFrame*       pFrame = SfxViewFrame::Current();
1194     if( pFrame )
1195     {
1196         pFrame = pFrame->GetTopViewFrame();
1197         if( pFrame )
1198         {
1199             pFrame->GetTargetList( aList );
1200 
1201             String*         pObj;
1202             for( sal_uInt16 nPos = ( sal_uInt16 ) aList.Count() ; nPos ; )
1203             {
1204                 pObj = aList.GetObject( --nPos );
1205                 aCBFrame.InsertEntry( *pObj );
1206                 delete pObj;
1207             }
1208         }
1209     }
1210 
1211     aRBNoAutoUpdate.SetClickHdl( LINK( this, SfxInternetPage, ClickHdlNoUpdate ) );
1212     aRBReloadUpdate.SetClickHdl( LINK( this, SfxInternetPage, ClickHdlReload ) );
1213     aRBForwardUpdate.SetClickHdl( LINK( this, SfxInternetPage, ClickHdlForward ) );
1214     aPBBrowseURL.SetClickHdl( LINK( this, SfxInternetPage, ClickHdlBrowseURL ) );
1215 
1216     aForwardErrorMessg.SearchAndReplaceAscii( "%PLACEHOLDER%", aRBForwardUpdate.GetText() );
1217 
1218     ChangeState( S_NoUpdate );
1219 }
1220 
1221 //------------------------------------------------------------------------
1222 
1223 SfxInternetPage::~SfxInternetPage()
1224 {
1225     delete pFileDlg;
1226 }
1227 
1228 //------------------------------------------------------------------------
1229 
1230 void SfxInternetPage::ChangeState( STATE eNewState )
1231 {
1232     DBG_ASSERT( eNewState != S_Init, "*SfxInternetPage::ChangeState(): new state init is supposed to not work here!" );
1233 
1234     if( eState == eNewState  )
1235         return;
1236 
1237     switch( eState )
1238     {
1239         case S_Init:
1240             EnableNoUpdate( sal_True );
1241             EnableReload( sal_False );
1242             EnableForward( sal_False );
1243             break;
1244         case S_NoUpdate:
1245             EnableNoUpdate( sal_False );
1246             if( eNewState == S_Reload )
1247                 EnableReload( sal_True );
1248             else
1249                 EnableForward( sal_True );
1250             break;
1251         case S_Reload:
1252             EnableReload( sal_False );
1253             if( eNewState == S_NoUpdate )
1254                 EnableNoUpdate( sal_True );
1255             else
1256                 EnableForward( sal_True );
1257             break;
1258         case S_Forward:
1259             EnableForward( sal_False );
1260             if( eNewState == S_NoUpdate )
1261                 EnableNoUpdate( sal_True );
1262             else
1263                 EnableReload( sal_True );
1264             break;
1265         default:
1266             DBG_ERROR( "*SfxInternetPage::SetState(): unhandled state!" );
1267     }
1268 
1269     eState = eNewState;
1270 }
1271 
1272 //------------------------------------------------------------------------
1273 
1274 void SfxInternetPage::EnableNoUpdate( sal_Bool bEnable )
1275 {
1276     if( bEnable )
1277         aRBNoAutoUpdate.Check();
1278 }
1279 
1280 //------------------------------------------------------------------------
1281 
1282 void SfxInternetPage::EnableReload( sal_Bool bEnable )
1283 {
1284     aFTEvery.Enable( bEnable );
1285     aNFReload.Enable( bEnable );
1286     aFTReloadSeconds.Enable( bEnable );
1287 
1288     if( bEnable )
1289         aRBReloadUpdate.Check();
1290 }
1291 
1292 //------------------------------------------------------------------------
1293 
1294 void SfxInternetPage::EnableForward( sal_Bool bEnable )
1295 {
1296     aFTAfter.Enable( bEnable );
1297     aNFAfter.Enable( bEnable );
1298     aFTAfterSeconds.Enable( bEnable );
1299     aFTURL.Enable( bEnable );
1300     aEDForwardURL.Enable( bEnable );
1301     aPBBrowseURL.Enable( bEnable );
1302     aFTFrame.Enable( bEnable );
1303     aCBFrame.Enable( bEnable );
1304 
1305     if( bEnable )
1306         aRBForwardUpdate.Check();
1307 }
1308 
1309 //------------------------------------------------------------------------
1310 
1311 IMPL_LINK( SfxInternetPage, ClickHdlNoUpdate, Control*, pCtrl )
1312 {
1313     (void)pCtrl; //unused
1314     ChangeState( S_NoUpdate );
1315     return 0;
1316 }
1317 
1318 //------------------------------------------------------------------------
1319 
1320 IMPL_LINK( SfxInternetPage, ClickHdlReload, Control*, pCtrl )
1321 {
1322     (void)pCtrl; //unused
1323     ChangeState( S_Reload );
1324     return 0;
1325 }
1326 
1327 //------------------------------------------------------------------------
1328 
1329 IMPL_LINK( SfxInternetPage, ClickHdlForward, Control*, pCtrl )
1330 {
1331     (void)pCtrl; //unused
1332     ChangeState( S_Forward );
1333     return 0;
1334 }
1335 
1336 //------------------------------------------------------------------------
1337 
1338 IMPL_LINK( SfxInternetPage, ClickHdlBrowseURL, PushButton*, EMPTYARG )
1339 {
1340     if ( !pFileDlg )
1341         pFileDlg = new sfx2::FileDialogHelper( TemplateDescription::FILEOPEN_SIMPLE, WB_OPEN );
1342     pFileDlg->SetDisplayDirectory( aEDForwardURL.GetText() );
1343     pFileDlg->StartExecuteModal( LINK( this, SfxInternetPage, DialogClosedHdl ) );
1344 
1345     return 0;
1346 }
1347 
1348 //------------------------------------------------------------------------
1349 
1350 IMPL_LINK( SfxInternetPage, DialogClosedHdl, sfx2::FileDialogHelper*, EMPTYARG )
1351 {
1352     DBG_ASSERT( pFileDlg, "SfxInternetPage::DialogClosedHdl(): no file dialog" );
1353 
1354     if ( ERRCODE_NONE == pFileDlg->GetError() )
1355         aEDForwardURL.SetText( pFileDlg->GetPath() );
1356 
1357     return 0;
1358 }
1359 
1360 //------------------------------------------------------------------------
1361 
1362 sal_Bool SfxInternetPage::FillItemSet( SfxItemSet& rSet )
1363 {
1364     const SfxPoolItem*          pItem = NULL;
1365     SfxDocumentInfoItem*        pInfo = NULL;
1366     SfxTabDialog*               pDlg = GetTabDialog();
1367     const SfxItemSet*           pExSet = NULL;
1368 
1369     if( pDlg )
1370         pExSet = pDlg->GetExampleSet();
1371 
1372     if( pExSet && SFX_ITEM_SET != pExSet->GetItemState( SID_DOCINFO, sal_True, &pItem ) )
1373         pInfo = pInfoItem;
1374     else if ( pItem )
1375         pInfo = new SfxDocumentInfoItem( *(const SfxDocumentInfoItem*)pItem );
1376 
1377     if ( !pInfo )
1378     {
1379         DBG_ERRORFILE( "SfxInternetPage::FillItemSet(): no item found" );
1380         return sal_False;
1381     }
1382 
1383     DBG_ASSERT( eState != S_Init, "*SfxInternetPage::FillItemSet(): state init is not acceptable at this point!" );
1384 
1385     sal_Bool                        bEnableReload = sal_False;
1386     ::std::auto_ptr< String >   aURL( NULL );
1387     ::std::auto_ptr< String >   aFrame( NULL );
1388     sal_uIntPtr                     nDelay = 0;
1389 
1390     switch( eState )
1391     {
1392         case S_NoUpdate:
1393             break;
1394         case S_Reload:
1395             bEnableReload = sal_True;
1396             aURL = ::std::auto_ptr< String >( new String() );
1397             aFrame = ::std::auto_ptr< String >( new String() );
1398             nDelay = static_cast<sal_uIntPtr>(aNFReload.GetValue());
1399             break;
1400         case S_Forward:
1401             DBG_ASSERT( aEDForwardURL.GetText().Len(), "+SfxInternetPage::FillItemSet(): empty URL should be not possible for forward option!" );
1402 
1403             bEnableReload = sal_True;
1404             aURL = ::std::auto_ptr< String >( new String( URIHelper::SmartRel2Abs( INetURLObject(aBaseURL), aEDForwardURL.GetText(), URIHelper::GetMaybeFileHdl(), true ) ) );
1405             aFrame = ::std::auto_ptr< String >( new String( aCBFrame.GetText() ) );
1406             nDelay = static_cast<sal_uIntPtr>(aNFAfter.GetValue());
1407             break;
1408               default:
1409                   break;
1410     }
1411 
1412     pInfo->setAutoloadEnabled( bEnableReload );
1413 
1414     if( bEnableReload )
1415     {
1416         pInfo->setAutoloadURL( *aURL.get() );
1417         pInfo->setDefaultTarget( *aFrame.get() );
1418         pInfo->setAutoloadDelay( nDelay );
1419     }
1420 
1421     rSet.Put( *pInfo );
1422     if( pInfo != pInfoItem )
1423         delete pInfo;
1424     return sal_True;
1425 }
1426 
1427 //------------------------------------------------------------------------
1428 
1429 SfxTabPage *SfxInternetPage::Create( Window* pParent, const SfxItemSet& rItemSet )
1430 {
1431     return new SfxInternetPage(pParent, rItemSet);
1432 }
1433 
1434 //------------------------------------------------------------------------
1435 
1436 void SfxInternetPage::Reset( const SfxItemSet& rSet )
1437 {
1438     pInfoItem = &( SfxDocumentInfoItem& ) rSet.Get( SID_DOCINFO );
1439     SFX_ITEMSET_ARG( &rSet, pURLItem, SfxStringItem, SID_BASEURL, sal_False );
1440     DBG_ASSERT( pURLItem, "No BaseURL provided for InternetTabPage!" );
1441     if ( pURLItem )
1442         aBaseURL = pURLItem->GetValue();
1443 
1444     STATE               eNewState = S_NoUpdate;
1445 
1446     if( pInfoItem->isAutoloadEnabled() )
1447     {
1448         const String&   rURL = pInfoItem->getAutoloadURL();
1449 
1450         if( rURL.Len() )
1451         {
1452             aNFAfter.SetValue( pInfoItem->getAutoloadDelay() );
1453             aEDForwardURL.SetText( rURL );
1454             aCBFrame.SetText( pInfoItem->getDefaultTarget() );
1455             eNewState = S_Forward;
1456         }
1457         else
1458         {
1459             aNFReload.SetValue( pInfoItem->getAutoloadDelay() );
1460             eNewState = S_Reload;
1461         }
1462     }
1463 
1464     ChangeState( eNewState );
1465 
1466     // #102907# ------------------------
1467     SFX_ITEMSET_ARG( &rSet, pROItem, SfxBoolItem, SID_DOC_READONLY, sal_False );
1468     if ( pROItem && pROItem->GetValue() )
1469     {
1470         aRBNoAutoUpdate.Disable();
1471         aRBReloadUpdate.Disable();
1472         aRBForwardUpdate.Disable();
1473         aNFReload.Disable();
1474         aNFAfter.Disable();
1475         aEDForwardURL.Disable();
1476         aPBBrowseURL.Disable();
1477         aCBFrame.Disable();
1478         aFTEvery.Disable();
1479         aFTReloadSeconds.Disable();
1480         aFTAfter.Disable();
1481         aFTAfterSeconds.Disable();
1482         aFTURL.Disable();
1483         aFTFrame.Disable();
1484     }
1485 }
1486 
1487 //------------------------------------------------------------------------
1488 
1489 int SfxInternetPage::DeactivatePage( SfxItemSet* /*pSet*/ )
1490 {
1491     int             nRet = LEAVE_PAGE;
1492 
1493     if( eState == S_Forward && !aEDForwardURL.GetText().Len() )
1494     {
1495         ErrorBox    aErrBox( this, WB_OK, aForwardErrorMessg );
1496         aErrBox.Execute();
1497 
1498         nRet = KEEP_PAGE;
1499     }
1500 
1501     return nRet;
1502 }
1503 
1504 //------------------------------------------------------------------------
1505 
1506 SfxDocumentInfoDialog::SfxDocumentInfoDialog( Window* pParent,
1507                                               const SfxItemSet& rItemSet ) :
1508 
1509     SfxTabDialog( 0, pParent, SfxResId( SID_DOCINFO ), &rItemSet )
1510 
1511 {
1512     FreeResource();
1513 
1514      const SfxDocumentInfoItem* pInfoItem =
1515         &(const SfxDocumentInfoItem &)rItemSet.Get( SID_DOCINFO );
1516 
1517 #ifdef DBG_UTIL
1518     SFX_ITEMSET_ARG( &rItemSet, pURLItem, SfxStringItem, SID_BASEURL, sal_False );
1519     DBG_ASSERT( pURLItem, "No BaseURL provided for InternetTabPage!" );
1520 #endif
1521 
1522      // Bestimmung des Titels
1523     const SfxPoolItem* pItem = 0;
1524     String aTitle( GetText() );
1525     if ( SFX_ITEM_SET !=
1526          rItemSet.GetItemState( SID_EXPLORER_PROPS_START, sal_False, &pItem ) )
1527     {
1528         // Dateiname
1529         String aFile( pInfoItem->GetValue() );
1530 
1531         INetURLObject aURL;
1532         aURL.SetSmartProtocol( INET_PROT_FILE );
1533         aURL.SetSmartURL( aFile);
1534         if ( INET_PROT_PRIV_SOFFICE != aURL.GetProtocol() )
1535         {
1536             String aLastName( aURL.GetLastName() );
1537             if ( aLastName.Len() )
1538                 aTitle += aLastName;
1539             else
1540                 aTitle += aFile;
1541         }
1542         else
1543             aTitle += String( SfxResId( STR_NONAME ) );
1544     }
1545     else
1546     {
1547         DBG_ASSERT( pItem->IsA( TYPE( SfxStringItem ) ),
1548                     "SfxDocumentInfoDialog:<SfxStringItem> erwartet" );
1549         aTitle += ( ( SfxStringItem* ) pItem )->GetValue();
1550     }
1551     SetText( aTitle );
1552 
1553     // Eigenschaftenseiten
1554     AddTabPage(TP_DOCINFODESC, SfxDocumentDescPage::Create, 0);
1555     AddTabPage(TP_DOCINFODOC, SfxDocumentPage::Create, 0);
1556     AddTabPage(TP_CUSTOMPROPERTIES, SfxCustomPropertiesPage::Create, 0);
1557     AddTabPage(TP_DOCINFORELOAD, SfxInternetPage::Create, 0);
1558     AddTabPage(TP_DOCINFOSECURITY, SfxSecurityPage::Create, 0);
1559 }
1560 
1561 // -----------------------------------------------------------------------
1562 
1563 void SfxDocumentInfoDialog::PageCreated( sal_uInt16 nId, SfxTabPage &rPage )
1564 {
1565     if ( TP_DOCINFODOC == nId )
1566         ( (SfxDocumentPage&)rPage ).EnableUseUserData();
1567 }
1568 
1569 // class CustomPropertiesYesNoButton -------------------------------------
1570 
1571 CustomPropertiesYesNoButton::CustomPropertiesYesNoButton( Window* pParent, const ResId& rResId ) :
1572     Control( pParent, rResId ),
1573     m_aYesButton( this, ResId( RB_PROPERTY_YES, *rResId.GetResMgr() ) ),
1574     m_aNoButton ( this, ResId( RB_PROPERTY_NO, *rResId.GetResMgr() ) )
1575 {
1576     FreeResource();
1577     Wallpaper aWall( Color( COL_TRANSPARENT ) );
1578     SetBackground( aWall );
1579     SetBorderStyle( WINDOW_BORDER_MONO  );
1580     CheckNo();
1581     m_aYesButton.SetBackground( aWall );
1582     m_aNoButton.SetBackground( aWall );
1583 }
1584 class DurationDialog_Impl : public ModalDialog
1585 {
1586     FixedLine       aDurationFL;
1587 
1588     OKButton        aOKPB;
1589     CancelButton    aCancelPB;
1590     HelpButton      aHelpPB;
1591 
1592     CheckBox        aNegativeCB;
1593     FixedText       aYearFT;
1594     NumericField    aYearNF;
1595     FixedText       aMonthFT;
1596     NumericField    aMonthNF;
1597     FixedText       aDayFT;
1598     NumericField    aDayNF;
1599     FixedText       aHourFT;
1600     NumericField    aHourNF;
1601     FixedText       aMinuteFT;
1602     NumericField    aMinuteNF;
1603     FixedText       aSecondFT;
1604     NumericField    aSecondNF;
1605     FixedText       aMSecondFT;
1606     NumericField    aMSecondNF;
1607 
1608 public:
1609 
1610     DurationDialog_Impl( Window* pParent, const util::Duration& rDuration );
1611     ~DurationDialog_Impl();
1612 
1613     util::Duration  GetDuration() const;
1614 };
1615 /*-- 20.11.2009 15:40:46---------------------------------------------------
1616 
1617   -----------------------------------------------------------------------*/
1618 DurationDialog_Impl::DurationDialog_Impl(
1619     Window* pParent, const util::Duration& rDuration)
1620         :   ModalDialog( pParent, SfxResId( RID_EDIT_DURATIONS ) ),
1621             aDurationFL(this, SfxResId( FL_DURATION       )),
1622             aOKPB(      this, SfxResId( PB_OK       )),
1623             aCancelPB(  this, SfxResId( PB_CANCEL   )),
1624             aHelpPB(    this, SfxResId( PB_HELP     )),
1625             aNegativeCB(this, SfxResId( CB_NEGATIVE     )),
1626             aYearFT(    this, SfxResId( FT_YEAR         )),
1627             aYearNF(    this, SfxResId( ED_YEAR         )),
1628             aMonthFT(   this, SfxResId( FT_MONTH        )),
1629             aMonthNF(   this, SfxResId( ED_MONTH        )),
1630             aDayFT(     this, SfxResId( FT_DAY          )),
1631             aDayNF(     this, SfxResId( ED_DAY          )),
1632             aHourFT(    this, SfxResId( FT_HOUR         )),
1633             aHourNF(    this, SfxResId( ED_HOUR         )),
1634             aMinuteFT(  this, SfxResId( FT_MINUTE       )),
1635             aMinuteNF(  this, SfxResId( ED_MINUTE       )),
1636             aSecondFT(  this, SfxResId( FT_SECOND       )),
1637             aSecondNF(  this, SfxResId( ED_SECOND       )),
1638             aMSecondFT( this, SfxResId( FT_MSECOND      )),
1639             aMSecondNF( this, SfxResId( ED_MSECOND      ))
1640 {
1641     FreeResource();
1642     aNegativeCB.Check(rDuration.Negative);
1643     aYearNF.SetValue(rDuration.Years);
1644     aMonthNF.SetValue(rDuration.Months );
1645     aDayNF.SetValue(rDuration.Days   );
1646     aHourNF.SetValue(rDuration.Hours  );
1647     aMinuteNF.SetValue(rDuration.Minutes);
1648     aSecondNF.SetValue(rDuration.Seconds);
1649     aMSecondNF.SetValue(rDuration.MilliSeconds);
1650 }
1651 /*-- 20.11.2009 16:08:55---------------------------------------------------
1652 
1653   -----------------------------------------------------------------------*/
1654 DurationDialog_Impl::~DurationDialog_Impl()
1655 {
1656 }
1657 /*-- 20.11.2009 15:41:47---------------------------------------------------
1658 
1659   -----------------------------------------------------------------------*/
1660 util::Duration  DurationDialog_Impl::GetDuration() const
1661 {
1662     util::Duration  aRet;
1663     aRet.Negative = aNegativeCB.IsChecked();
1664     aRet.Years = aYearNF.GetValue();
1665     aRet.Months = aMonthNF.GetValue( );
1666     aRet.Days = aDayNF.GetValue(   );
1667     aRet.Hours  = aHourNF.GetValue( );
1668     aRet.Minutes = aMinuteNF.GetValue();
1669     aRet.Seconds = aSecondNF.GetValue();
1670     aRet.MilliSeconds = aMSecondNF.GetValue();
1671     return aRet;
1672 }
1673 
1674 /*-- 20.11.2009 15:30:58---------------------------------------------------
1675 
1676   -----------------------------------------------------------------------*/
1677 CustomPropertiesDurationField::CustomPropertiesDurationField( Window* pParent, const ResId& rResId, CustomPropertyLine* pLine ) :
1678         Edit( pParent, rResId ), m_pLine( pLine )
1679 
1680 {
1681     SetDuration( util::Duration(false, 0, 0, 0, 0, 0, 0, 0) );
1682 }
1683 /*-- 23.11.2009 08:46:02---------------------------------------------------
1684 
1685   -----------------------------------------------------------------------*/
1686 CustomPropertiesDurationField::~CustomPropertiesDurationField()
1687 {
1688 }
1689 /*-- 23.11.2009 09:23:35---------------------------------------------------
1690 
1691   -----------------------------------------------------------------------*/
1692 void CustomPropertiesDurationField::RequestHelp( const HelpEvent& rHEvt )
1693 {
1694     if( rHEvt.GetMode() & HELPMODE_QUICK )
1695     {
1696         Size aSize( GetSizePixel() );
1697         Rectangle aItemRect( rHEvt.GetMousePosPixel(), aSize );
1698         if(Help::IsBalloonHelpEnabled())
1699             Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), GetText() );
1700         else
1701             Help::ShowQuickHelp( this, aItemRect, GetText(),
1702                 QUICKHELP_LEFT|QUICKHELP_VCENTER );
1703     }
1704 }
1705 /*-- 20.11.2009 15:30:58---------------------------------------------------
1706 
1707   -----------------------------------------------------------------------*/
1708 void CustomPropertiesDurationField::SetDuration( const util::Duration& rDuration )
1709 {
1710     m_aDuration = rDuration;
1711     String sText(rDuration.Negative ? '-' : '+');
1712     sText += m_pLine->m_sDurationFormat;
1713     sText.SearchAndReplace(String::CreateFromAscii( "%1"), String::CreateFromInt32( rDuration.Years ) );
1714     sText.SearchAndReplace(String::CreateFromAscii( "%2"), String::CreateFromInt32( rDuration.Months ) );
1715     sText.SearchAndReplace(String::CreateFromAscii( "%3"), String::CreateFromInt32( rDuration.Days   ) );
1716     sText.SearchAndReplace(String::CreateFromAscii( "%4"), String::CreateFromInt32( rDuration.Hours  ) );
1717     sText.SearchAndReplace(String::CreateFromAscii( "%5"), String::CreateFromInt32( rDuration.Minutes) );
1718     sText.SearchAndReplace(String::CreateFromAscii( "%6"), String::CreateFromInt32( rDuration.Seconds) );
1719     SetText( sText );
1720 }
1721 /*-- 23.11.2009 08:51:15---------------------------------------------------
1722 
1723   -----------------------------------------------------------------------*/
1724 CustomPropertiesEditButton::CustomPropertiesEditButton( Window* pParent, const ResId& rResId, CustomPropertyLine* pLine ) :
1725         PushButton( pParent, rResId ), m_pLine( pLine )
1726 {
1727     SetClickHdl( LINK( this, CustomPropertiesEditButton, ClickHdl ));
1728 }
1729 /*-- 23.11.2009 08:51:15---------------------------------------------------
1730 
1731   -----------------------------------------------------------------------*/
1732 CustomPropertiesEditButton::~CustomPropertiesEditButton()
1733 {
1734 }
1735 /*-- 23.11.2009 08:47:37---------------------------------------------------
1736 
1737   -----------------------------------------------------------------------*/
1738 IMPL_LINK( CustomPropertiesEditButton, ClickHdl, PushButton*, EMPTYARG )
1739 {
1740     DurationDialog_Impl* pDurationDlg = new DurationDialog_Impl( this, m_pLine->m_aDurationField.GetDuration() );
1741     if( RET_OK == pDurationDlg->Execute() )
1742         m_pLine->m_aDurationField.SetDuration( pDurationDlg->GetDuration() );
1743     delete pDurationDlg;
1744     return 1;
1745 }
1746 //--------------------------------------------------------------------------
1747 void CustomPropertiesYesNoButton::Resize()
1748 {
1749     const long nWidth = GetSizePixel().Width();
1750     const long n3Width = LogicToPixel( Size( 3, 3 ), MAP_APPFONT ).Width();
1751     const long nNewWidth = ( nWidth / 2 ) - n3Width - 2;
1752     Size aSize = m_aYesButton.GetSizePixel();
1753     const long nDelta = aSize.Width() - nNewWidth;
1754     aSize.Width() = nNewWidth;
1755     m_aYesButton.SetSizePixel( aSize );
1756     Point aPos = m_aNoButton.GetPosPixel();
1757     aPos.X() -= nDelta;
1758     m_aNoButton.SetPosSizePixel( aPos, aSize );
1759 }
1760 
1761 // struct CustomPropertyLine ---------------------------------------------
1762 
1763 CustomPropertyLine::CustomPropertyLine( Window* pParent ) :
1764     m_aNameBox      ( pParent, SfxResId( SFX_CB_PROPERTY_NAME ) ),
1765     m_aTypeBox      ( pParent, SfxResId( SFX_LB_PROPERTY_TYPE ), this ),
1766     m_aValueEdit    ( pParent, SfxResId( SFX_ED_PROPERTY_VALUE ), this ),
1767     m_aDateField    ( pParent, SfxResId( SFX_FLD_DATE), this),
1768     m_aTimeField    ( pParent, SfxResId( SFX_FLD_TIME), this),
1769     m_sDurationFormat( SfxResId( SFX_ST_DURATION_FORMAT )),
1770     m_aDurationField( pParent, SfxResId( SFX_FLD_DURATION), this),
1771     m_aEditButton(    pParent, SfxResId( SFX_PB_EDIT ), this),
1772     m_aYesNoButton  ( pParent, SfxResId( SFX_WIN_PROPERTY_YESNO ) ),
1773     m_aRemoveButton ( pParent, SfxResId( SFX_PB_PROPERTY_REMOVE ), this ),
1774     m_bIsRemoved    ( false ),
1775     m_bTypeLostFocus( false )
1776 
1777 {
1778     m_aTimeField.SetExtFormat( EXTTIMEF_24H_LONG );
1779     m_aDateField.SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YYYY );
1780 
1781     m_aRemoveButton.SetModeImage( SfxResId( SFX_IMG_PROPERTY_REMOVE ), BMP_COLOR_NORMAL );
1782     m_aRemoveButton.SetModeImage( SfxResId( SFX_IMG_PROPERTY_REMOVE_HC ), BMP_COLOR_HIGHCONTRAST );
1783 }
1784 
1785 void CustomPropertyLine::SetRemoved()
1786 {
1787     DBG_ASSERT( !m_bIsRemoved, "CustomPropertyLine::SetRemoved(): line already removed" );
1788     m_bIsRemoved = true;
1789     m_aNameBox.Hide();
1790     m_aTypeBox.Hide();
1791     m_aValueEdit.Hide();
1792     m_aDateField.Hide();
1793     m_aTimeField.Hide();
1794     m_aDurationField.Hide();
1795     m_aEditButton.Hide();
1796     m_aYesNoButton.Hide();
1797     m_aRemoveButton.Hide();
1798 }
1799 
1800 // class CustomPropertiesWindow ------------------------------------------
1801 
1802 CustomPropertiesWindow::CustomPropertiesWindow( Window* pParent, const ResId& rResId ) :
1803 
1804     Window( pParent, rResId ),
1805     m_aNameBox      ( this, SfxResId( SFX_CB_PROPERTY_NAME ) ),
1806     m_aTypeBox      ( this, SfxResId( SFX_LB_PROPERTY_TYPE ) ),
1807     m_aValueEdit    ( this, SfxResId( SFX_ED_PROPERTY_VALUE ) ),
1808     m_aDateField    ( this, SfxResId( SFX_FLD_DATE) ),
1809     m_aTimeField    ( this, SfxResId( SFX_FLD_TIME) ),
1810     m_aDurationField( this, SfxResId( SFX_FLD_DURATION) ),
1811     m_aEditButton(    this, SfxResId( SFX_PB_EDIT )),
1812     m_aYesNoButton  ( this, SfxResId( SFX_WIN_PROPERTY_YESNO ) ),
1813     m_aRemoveButton ( this, SfxResId( SFX_PB_PROPERTY_REMOVE ) ),
1814     m_nScrollPos (0),
1815     m_aNumberFormatter( ::comphelper::getProcessServiceFactory(),
1816                         Application::GetSettings().GetLanguage() )
1817 
1818 {
1819     m_aEditLoseFocusTimer.SetTimeout( 300 );
1820     m_aEditLoseFocusTimer.SetTimeoutHdl( LINK( this, CustomPropertiesWindow, EditTimeoutHdl ) );
1821     m_aBoxLoseFocusTimer.SetTimeout( 300 );
1822     m_aBoxLoseFocusTimer.SetTimeoutHdl( LINK( this, CustomPropertiesWindow, BoxTimeoutHdl ) );
1823 
1824     ResMgr* pResMgr = rResId.GetResMgr();
1825     m_aNameBox.SetAccessibleName( String( ResId( STR_HEADER_NAME, *pResMgr ) ) );
1826     m_aTypeBox.SetAccessibleName( String( ResId( STR_HEADER_TYPE, *pResMgr ) ) );
1827     m_aValueEdit.SetAccessibleName( String( ResId( STR_HEADER_VALUE, *pResMgr ) ) );
1828 }
1829 
1830 CustomPropertiesWindow::~CustomPropertiesWindow()
1831 {
1832     m_aEditLoseFocusTimer.Stop();
1833     m_aBoxLoseFocusTimer.Stop();
1834     ClearAllLines();
1835 }
1836 
1837 IMPL_LINK( CustomPropertiesWindow, TypeHdl, CustomPropertiesTypeBox*, pBox )
1838 {
1839     sal_Int64 nType = sal_Int64( (long)pBox->GetEntryData( pBox->GetSelectEntryPos() ) );
1840     CustomPropertyLine* pLine = pBox->GetLine();
1841     pLine->m_aValueEdit.Show( (CUSTOM_TYPE_TEXT == nType) || (CUSTOM_TYPE_NUMBER  == nType) );
1842     pLine->m_aDateField.Show( (CUSTOM_TYPE_DATE == nType) || (CUSTOM_TYPE_DATETIME  == nType) );
1843     pLine->m_aTimeField.Show( CUSTOM_TYPE_DATETIME  == nType );
1844     pLine->m_aDurationField.Show( CUSTOM_TYPE_DURATION == nType );
1845     pLine->m_aEditButton.Show( CUSTOM_TYPE_DURATION == nType );
1846     pLine->m_aYesNoButton.Show( CUSTOM_TYPE_BOOLEAN == nType );
1847     //adjust positions of date and time controls
1848     if( nType == CUSTOM_TYPE_DATE )
1849     {
1850         pLine->m_aDateField.SetPosSizePixel(pLine->m_aValueEdit.GetPosPixel(), pLine->m_aValueEdit.GetSizePixel());
1851     }
1852     else if( nType == CUSTOM_TYPE_DATETIME)
1853     {
1854         pLine->m_aDateField.SetPosSizePixel( pLine->m_aDatePos, pLine->m_aDateTimeSize );
1855         pLine->m_aTimeField.SetPosSizePixel(pLine->m_aTimePos, pLine->m_aDateTimeSize );
1856     }
1857 
1858     return 0;
1859 }
1860 
1861 IMPL_LINK( CustomPropertiesWindow, RemoveHdl, CustomPropertiesRemoveButton*, pButton )
1862 {
1863     CustomPropertyLine* pLine = pButton->GetLine();
1864     std::vector< CustomPropertyLine* >::iterator pFound =
1865         std::find( m_aCustomPropertiesLines.begin(), m_aCustomPropertiesLines.end(), pLine );
1866     if ( pFound != m_aCustomPropertiesLines.end() )
1867     {
1868         pLine = *pFound;
1869         pLine->SetRemoved();
1870         std::vector< CustomPropertyLine* >::iterator pIter = pFound + 1;
1871         const long nDelta = GetLineHeight();
1872         for ( ; pIter != m_aCustomPropertiesLines.end(); ++pIter )
1873         {
1874             pLine = *pIter;
1875             if ( pLine->m_bIsRemoved )
1876                 continue;
1877 
1878             Window* pWindows[] = {  &pLine->m_aNameBox, &pLine->m_aTypeBox, &pLine->m_aValueEdit,
1879                                     &pLine->m_aDateField, &pLine->m_aTimeField,
1880                                     &pLine->m_aDurationField, &pLine->m_aEditButton,
1881                                     &pLine->m_aYesNoButton, &pLine->m_aRemoveButton, NULL };
1882             Window** pCurrent = pWindows;
1883             while ( *pCurrent )
1884             {
1885                 Point aPos = (*pCurrent)->GetPosPixel();
1886                 aPos.Y() -= nDelta;
1887                 (*pCurrent)->SetPosPixel( aPos );
1888                 pCurrent++;
1889             }
1890         }
1891     }
1892 
1893     m_aRemovedHdl.Call(0);
1894     return 0;
1895 }
1896 
1897 IMPL_LINK( CustomPropertiesWindow, EditLoseFocusHdl, CustomPropertiesEdit*, pEdit )
1898 {
1899     if ( pEdit )
1900     {
1901         CustomPropertyLine* pLine = pEdit->GetLine();
1902         if ( !pLine->m_bTypeLostFocus )
1903         {
1904             m_pCurrentLine = pLine;
1905             m_aEditLoseFocusTimer.Start();
1906         }
1907         else
1908             pLine->m_bTypeLostFocus = false;
1909     }
1910     return 0;
1911 }
1912 
1913 IMPL_LINK( CustomPropertiesWindow, BoxLoseFocusHdl, CustomPropertiesTypeBox*, pBox )
1914 {
1915     if ( pBox )
1916     {
1917         m_pCurrentLine = pBox->GetLine();
1918         m_aBoxLoseFocusTimer.Start();
1919     }
1920 
1921     return 0;
1922 }
1923 
1924 IMPL_LINK( CustomPropertiesWindow, EditTimeoutHdl, Timer*, EMPTYARG )
1925 {
1926     ValidateLine( m_pCurrentLine, false );
1927     return 0;
1928 }
1929 
1930 IMPL_LINK( CustomPropertiesWindow, BoxTimeoutHdl, Timer*, EMPTYARG )
1931 {
1932     ValidateLine( m_pCurrentLine, true );
1933     return 0;
1934 }
1935 
1936 bool CustomPropertiesWindow::IsLineValid( CustomPropertyLine* pLine ) const
1937 {
1938     bool bIsValid = true;
1939     pLine->m_bTypeLostFocus = false;
1940     sal_Int64 nType = sal_Int64(
1941         (long)pLine->m_aTypeBox.GetEntryData( pLine->m_aTypeBox.GetSelectEntryPos() ) );
1942     String sValue = pLine->m_aValueEdit.GetText();
1943     if ( sValue.Len() == 0 )
1944         return true;
1945 
1946     double fDummy = 0.0;
1947     sal_uInt32 nIndex = 0xFFFFFFFF;
1948     if ( CUSTOM_TYPE_NUMBER == nType )
1949         nIndex = const_cast< SvNumberFormatter& >(
1950             m_aNumberFormatter ).GetFormatIndex( NF_NUMBER_SYSTEM );
1951     else if ( CUSTOM_TYPE_DATE == nType )
1952         nIndex = const_cast< SvNumberFormatter& >(
1953             m_aNumberFormatter).GetFormatIndex( NF_DATE_SYS_DDMMYYYY );
1954 
1955     if ( nIndex != 0xFFFFFFFF )
1956     {
1957         sal_uInt32 nTemp = nIndex;
1958         bIsValid = const_cast< SvNumberFormatter& >(
1959             m_aNumberFormatter ).IsNumberFormat( sValue, nIndex, fDummy ) != sal_False;
1960         if ( bIsValid && nTemp != nIndex )
1961             // sValue is a number but the format doesn't match the index
1962             bIsValid = false;
1963     }
1964 
1965     return bIsValid;
1966 }
1967 
1968 void CustomPropertiesWindow::ValidateLine( CustomPropertyLine* pLine, bool bIsFromTypeBox )
1969 {
1970     if ( !IsLineValid( pLine ) )
1971     {
1972         if ( bIsFromTypeBox ) // LoseFocus of TypeBox
1973             pLine->m_bTypeLostFocus = true;
1974         Window* pParent = GetParent()->GetParent();
1975         if ( QueryBox( pParent, SfxResId( SFX_QB_WRONG_TYPE ) ).Execute() == RET_OK )
1976             pLine->m_aTypeBox.SelectEntryPos( m_aTypeBox.GetEntryPos( (void*)CUSTOM_TYPE_TEXT ) );
1977         else
1978             pLine->m_aValueEdit.GrabFocus();
1979     }
1980 }
1981 
1982 void CustomPropertiesWindow::InitControls( HeaderBar* pHeaderBar, const ScrollBar* pScrollBar )
1983 {
1984     DBG_ASSERT( pHeaderBar, "CustomPropertiesWindow::InitControls(): invalid headerbar" );
1985     DBG_ASSERT( pScrollBar, "CustomPropertiesWindow::InitControls(): invalid scrollbar" );
1986 
1987     m_aNameBox.Hide();
1988     m_aTypeBox.Hide();
1989     m_aValueEdit.Hide();
1990     m_aDateField.Hide();
1991     m_aTimeField.Hide();
1992     m_aDurationField.Hide();
1993     m_aEditButton.Hide();
1994     m_aYesNoButton.Hide();
1995     m_aRemoveButton.Hide();
1996 
1997     const long nOffset = 4;
1998     const long nScrollBarWidth = pScrollBar->GetSizePixel().Width();
1999     const long nButtonWidth = m_aRemoveButton.GetSizePixel().Width() + nScrollBarWidth + nOffset;
2000     long nTypeWidth = m_aTypeBox.CalcMinimumSize().Width() + ( 2 * nOffset );
2001     long nFullWidth = pHeaderBar->GetSizePixel().Width();
2002     long nItemWidth = ( nFullWidth - nTypeWidth - nButtonWidth ) / 2;
2003     pHeaderBar->SetItemSize( HI_NAME, nItemWidth );
2004     pHeaderBar->SetItemSize( HI_TYPE, nTypeWidth );
2005     pHeaderBar->SetItemSize( HI_VALUE, nItemWidth );
2006     pHeaderBar->SetItemSize( HI_ACTION, nButtonWidth );
2007 
2008     Window* pWindows[] = { &m_aNameBox, &m_aTypeBox, &m_aValueEdit, &m_aRemoveButton, NULL };
2009     Window** pCurrent = pWindows;
2010     sal_uInt16 nPos = 0;
2011     while ( *pCurrent )
2012     {
2013         Rectangle aRect = pHeaderBar->GetItemRect( pHeaderBar->GetItemId( nPos++ ) );
2014         Size aSize = (*pCurrent)->GetSizePixel();
2015         Point aPos = (*pCurrent)->GetPosPixel();
2016         long nWidth = aRect.getWidth() - nOffset;
2017         if ( *pCurrent == &m_aRemoveButton )
2018             nWidth -= pScrollBar->GetSizePixel().Width();
2019         aSize.Width() = nWidth;
2020         aPos.X() = aRect.getX() + ( nOffset / 2 );
2021         (*pCurrent)->SetPosSizePixel( aPos, aSize );
2022 
2023         if ( *pCurrent == &m_aValueEdit )
2024         {
2025             Point aDurationPos( aPos );
2026             m_aDurationField.SetPosPixel( aDurationPos );
2027             Size aDurationSize(aSize);
2028             aDurationSize.Width() -= (m_aEditButton.GetSizePixel().Width() + 3 );
2029             m_aDurationField.SetSizePixel(aDurationSize);
2030             aDurationPos.X() = aPos.X() - m_aEditButton.GetSizePixel().Width() + aSize.Width();
2031             m_aEditButton.SetPosPixel(aDurationPos);
2032             aSize = m_aYesNoButton.GetSizePixel();
2033             aPos = m_aYesNoButton.GetPosPixel();
2034             aSize.Width() = nWidth;
2035             aPos.X() = aRect.getX() + ( nOffset / 2 );
2036             m_aYesNoButton.SetPosSizePixel( aPos, aSize );
2037             aSize.Width() /= 2;
2038             aSize.Width() -= 2;
2039             m_aDateField.SetPosSizePixel( aPos, aSize );
2040             aPos.X() += aSize.Width() + 4;
2041             m_aTimeField.SetPosSizePixel( aPos, aSize );
2042         }
2043 
2044         pCurrent++;
2045     }
2046 
2047     m_nLineHeight =
2048         ( m_aRemoveButton.GetPosPixel().Y() * 2 ) + m_aRemoveButton.GetSizePixel().Height();
2049 }
2050 
2051 sal_uInt16 CustomPropertiesWindow::GetVisibleLineCount() const
2052 {
2053     sal_uInt16 nCount = 0;
2054     std::vector< CustomPropertyLine* >::const_iterator pIter;
2055     for ( pIter = m_aCustomPropertiesLines.begin();
2056             pIter != m_aCustomPropertiesLines.end(); ++pIter )
2057     {
2058         CustomPropertyLine* pLine = *pIter;
2059         if ( !pLine->m_bIsRemoved )
2060             nCount++;
2061     }
2062     return nCount;
2063 }
2064 
2065 void CustomPropertiesWindow::AddLine( const ::rtl::OUString& sName, Any& rAny )
2066 {
2067     CustomPropertyLine* pNewLine = new CustomPropertyLine( this );
2068     pNewLine->m_aTypeBox.SetSelectHdl( LINK( this, CustomPropertiesWindow, TypeHdl ) );
2069     pNewLine->m_aRemoveButton.SetClickHdl( LINK( this, CustomPropertiesWindow, RemoveHdl ) );
2070     pNewLine->m_aValueEdit.SetLoseFocusHdl( LINK( this, CustomPropertiesWindow, EditLoseFocusHdl ) );
2071     //add lose focus handlers of date/time fields
2072 
2073     pNewLine->m_aTypeBox.SetLoseFocusHdl( LINK( this, CustomPropertiesWindow, BoxLoseFocusHdl ) );
2074 
2075     pNewLine->m_aNameBox.SetAccessibleName(m_aNameBox.GetAccessibleName());
2076     pNewLine->m_aTypeBox.SetAccessibleName(m_aTypeBox.GetAccessibleName());
2077     pNewLine->m_aValueEdit.SetAccessibleName(m_aValueEdit.GetAccessibleName());
2078 
2079     long nPos = GetVisibleLineCount() * GetLineHeight();
2080     m_aCustomPropertiesLines.push_back( pNewLine );
2081     Window* pWindows[] = {  &m_aNameBox, &m_aTypeBox, &m_aValueEdit,
2082                             &m_aDateField, &m_aTimeField,
2083                             &m_aDurationField, &m_aEditButton,
2084                             &m_aYesNoButton, &m_aRemoveButton, NULL };
2085     Window* pNewWindows[] =
2086         {   &pNewLine->m_aNameBox, &pNewLine->m_aTypeBox, &pNewLine->m_aValueEdit,
2087             &pNewLine->m_aDateField, &pNewLine->m_aTimeField,
2088             &pNewLine->m_aDurationField, &pNewLine->m_aEditButton,
2089             &pNewLine->m_aYesNoButton, &pNewLine->m_aRemoveButton, NULL };
2090     Window** pCurrent = pWindows;
2091     Window** pNewCurrent = pNewWindows;
2092     while ( *pCurrent )
2093     {
2094         Size aSize = (*pCurrent)->GetSizePixel();
2095         Point aPos = (*pCurrent)->GetPosPixel();
2096         aPos.Y() += nPos;
2097         aPos.Y() += m_nScrollPos;
2098         (*pNewCurrent)->SetPosSizePixel( aPos, aSize );
2099         (*pNewCurrent)->Show();
2100         pCurrent++;
2101         pNewCurrent++;
2102     }
2103     //
2104     pNewLine->m_aDatePos = pNewLine->m_aDateField.GetPosPixel();
2105     pNewLine->m_aTimePos = pNewLine->m_aTimeField.GetPosPixel();
2106     pNewLine->m_aDateTimeSize = pNewLine->m_aDateField.GetSizePixel();
2107 
2108     double nTmpValue = 0;
2109     bool bTmpValue = false;
2110     ::rtl::OUString sTmpValue;
2111     util::DateTime aTmpDateTime;
2112     util::Date aTmpDate;
2113     util::Duration aTmpDuration;
2114     SvtSysLocale aSysLocale;
2115     const LocaleDataWrapper& rLocaleWrapper = aSysLocale.GetLocaleData();
2116     pNewLine->m_aNameBox.SetText( sName );
2117     sal_Int32 nType = CUSTOM_TYPE_UNKNOWN;
2118     String sValue;
2119 
2120     if ( rAny >>= nTmpValue )
2121     {
2122         sal_uInt32 nIndex = m_aNumberFormatter.GetFormatIndex( NF_NUMBER_SYSTEM );
2123         m_aNumberFormatter.GetInputLineString( nTmpValue, nIndex, sValue );
2124         pNewLine->m_aValueEdit.SetText( sValue );
2125         nType = CUSTOM_TYPE_NUMBER;
2126     }
2127     else if ( rAny >>= bTmpValue )
2128     {
2129         sValue = ( bTmpValue ? rLocaleWrapper.getTrueWord() : rLocaleWrapper.getFalseWord() );
2130         nType = CUSTOM_TYPE_BOOLEAN;
2131     }
2132     else if ( rAny >>= sTmpValue )
2133     {
2134         pNewLine->m_aValueEdit.SetText( sTmpValue );
2135         nType = CUSTOM_TYPE_TEXT;
2136     }
2137     else if ( rAny >>= aTmpDate )
2138     {
2139         nType = CUSTOM_TYPE_DATE;
2140         pNewLine->m_aDateField.SetDate( Date( aTmpDate.Day, aTmpDate.Month, aTmpDate.Year ) );
2141 
2142     }
2143     else if ( rAny >>= aTmpDuration )
2144     {
2145         nType = CUSTOM_TYPE_DURATION;
2146         pNewLine->m_aDurationField.SetDuration( aTmpDuration );
2147     }
2148     else if ( rAny >>= aTmpDateTime )
2149     {
2150         pNewLine->m_aDateField.SetDate( Date( aTmpDateTime.Day, aTmpDateTime.Month, aTmpDateTime.Year ) );
2151         pNewLine->m_aTimeField.SetTime( Time( aTmpDateTime.Hours, aTmpDateTime.Minutes, aTmpDateTime.Seconds, aTmpDateTime.HundredthSeconds ) );
2152 
2153         nType = CUSTOM_TYPE_DATETIME;
2154     }
2155 
2156     if ( nType != CUSTOM_TYPE_UNKNOWN )
2157     {
2158         if ( CUSTOM_TYPE_BOOLEAN == nType )
2159         {
2160             if ( bTmpValue )
2161                 pNewLine->m_aYesNoButton.CheckYes();
2162             else
2163                 pNewLine->m_aYesNoButton.CheckNo();
2164         }
2165         pNewLine->m_aTypeBox.SelectEntryPos( m_aTypeBox.GetEntryPos( (void*)nType ) );
2166     }
2167 
2168     TypeHdl( &pNewLine->m_aTypeBox );
2169     pNewLine->m_aNameBox.GrabFocus();
2170 }
2171 
2172 bool CustomPropertiesWindow::AreAllLinesValid() const
2173 {
2174     bool bRet = true;
2175     std::vector< CustomPropertyLine* >::const_iterator pIter;
2176     for ( pIter = m_aCustomPropertiesLines.begin();
2177             pIter != m_aCustomPropertiesLines.end(); ++pIter )
2178     {
2179         CustomPropertyLine* pLine = *pIter;
2180         if ( !IsLineValid( pLine ) )
2181         {
2182             bRet = false;
2183             break;
2184         }
2185     }
2186 
2187     return bRet;
2188 }
2189 
2190 void CustomPropertiesWindow::ClearAllLines()
2191 {
2192     std::vector< CustomPropertyLine* >::iterator pIter;
2193     for ( pIter = m_aCustomPropertiesLines.begin();
2194           pIter != m_aCustomPropertiesLines.end(); ++pIter )
2195     {
2196         CustomPropertyLine* pLine = *pIter;
2197         pLine->SetRemoved();
2198         delete pLine;
2199     }
2200     m_aCustomPropertiesLines.clear();
2201     m_nScrollPos = 0;
2202 }
2203 
2204 void CustomPropertiesWindow::DoScroll( sal_Int32 nNewPos )
2205 {
2206     m_nScrollPos += nNewPos;
2207     std::vector< CustomPropertyLine* >::iterator pIter;
2208     for ( pIter = m_aCustomPropertiesLines.begin();
2209             pIter != m_aCustomPropertiesLines.end(); ++pIter )
2210     {
2211         CustomPropertyLine* pLine = *pIter;
2212         if ( pLine->m_bIsRemoved )
2213             continue;
2214 
2215         Window* pWindows[] = {  &pLine->m_aNameBox, &pLine->m_aTypeBox, &pLine->m_aValueEdit, &pLine->m_aDurationField,
2216                                 &pLine->m_aYesNoButton, &pLine->m_aRemoveButton, NULL };
2217         Window** pCurrent = pWindows;
2218         while ( *pCurrent )
2219         {
2220             Point aPos = (*pCurrent)->GetPosPixel();
2221             aPos.Y() += nNewPos;
2222             (*pCurrent)->SetPosPixel( aPos );
2223             pCurrent++;
2224         }
2225     }
2226 }
2227 
2228 bool CustomPropertiesWindow::DoesCustomPropertyExist( const String& rName ) const
2229 {
2230     bool bRet = false;
2231     std::vector< CustomPropertyLine* >::const_iterator pIter;
2232     for ( pIter = m_aCustomPropertiesLines.begin();
2233             pIter != m_aCustomPropertiesLines.end(); ++pIter )
2234     {
2235         CustomPropertyLine* pLine = *pIter;
2236         if ( !pLine->m_bIsRemoved && pLine->m_aNameBox.GetText() == rName )
2237         {
2238             bRet = true;
2239             break;
2240         }
2241     }
2242 
2243     return bRet;
2244 }
2245 
2246 Sequence< beans::PropertyValue > CustomPropertiesWindow::GetCustomProperties() const
2247 {
2248     Sequence< beans::PropertyValue > aPropertiesSeq( m_aCustomPropertiesLines.size() );
2249     sal_Int32 i = 0;
2250     std::vector< CustomPropertyLine* >::const_iterator pIter;
2251     for ( pIter = m_aCustomPropertiesLines.begin();
2252             pIter != m_aCustomPropertiesLines.end(); ++pIter, ++i )
2253     {
2254         CustomPropertyLine* pLine = *pIter;
2255         if ( pLine->m_bIsRemoved )
2256             continue;
2257 
2258         String sPropertyName = pLine->m_aNameBox.GetText();
2259         if ( sPropertyName.Len() > 0 )
2260         {
2261             aPropertiesSeq[i].Name = sPropertyName;
2262             sal_Int64 nType = sal_Int64(
2263                 (long)pLine->m_aTypeBox.GetEntryData( pLine->m_aTypeBox.GetSelectEntryPos() ) );
2264             if ( CUSTOM_TYPE_NUMBER == nType )
2265             {
2266                 double nValue = 0;
2267                 sal_uInt32 nIndex = const_cast< SvNumberFormatter& >(
2268                     m_aNumberFormatter ).GetFormatIndex( NF_NUMBER_SYSTEM );
2269                 sal_Bool bIsNum = const_cast< SvNumberFormatter& >( m_aNumberFormatter ).
2270                     IsNumberFormat( pLine->m_aValueEdit.GetText(), nIndex, nValue );
2271                 if ( bIsNum )
2272                     aPropertiesSeq[i].Value <<= makeAny( nValue );
2273             }
2274             else if ( CUSTOM_TYPE_BOOLEAN == nType )
2275             {
2276                 bool bValue = pLine->m_aYesNoButton.IsYesChecked();
2277                 aPropertiesSeq[i].Value <<= makeAny( bValue );
2278             }
2279             else if ( CUSTOM_TYPE_DATETIME == nType )
2280             {
2281                 Date aTmpDate = pLine->m_aDateField.GetDate();
2282                 Time aTmpTime = pLine->m_aTimeField.GetTime();
2283                 util::DateTime aDateTime(aTmpTime.Get100Sec(), aTmpTime.GetSec(), aTmpTime.GetMin(), aTmpTime.GetHour(),
2284                         aTmpDate.GetDay(), aTmpDate.GetMonth(), aTmpDate.GetYear() );
2285                 aPropertiesSeq[i].Value <<= aDateTime;
2286             }
2287             else if ( CUSTOM_TYPE_DURATION == nType )
2288             {
2289                 aPropertiesSeq[i].Value <<= pLine->m_aDurationField.GetDuration();
2290             }
2291             else if ( CUSTOM_TYPE_DATE == nType )
2292             {
2293                 Date aTmpDate = pLine->m_aDateField.GetDate();
2294                 util::Date aDate(aTmpDate.GetDay(), aTmpDate.GetMonth(), aTmpDate.GetYear());
2295                 aPropertiesSeq[i].Value <<= aDate;
2296 
2297             }
2298             else
2299             {
2300                 ::rtl::OUString sValue( pLine->m_aValueEdit.GetText() );
2301                 aPropertiesSeq[i].Value <<= makeAny( sValue );
2302             }
2303         }
2304     }
2305 
2306     return aPropertiesSeq;
2307 }
2308 
2309 // class CustomPropertiesControl -----------------------------------------
2310 
2311 CustomPropertiesControl::CustomPropertiesControl( Window* pParent, const ResId& rResId ) :
2312 
2313     Control( pParent, rResId ),
2314 
2315     m_aHeaderBar    ( this, WB_BUTTONSTYLE | WB_BOTTOMBORDER ),
2316     m_aPropertiesWin( this, ResId( WIN_PROPERTIES, *rResId.GetResMgr() ) ),
2317     m_aVertScroll   ( this, ResId( SB_VERTICAL, *rResId.GetResMgr() ) ),
2318 
2319     m_bIsInitialized( false ),
2320     m_nThumbPos     ( 0 )
2321 
2322 {
2323     m_aPropertiesWin.SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) );
2324     m_aVertScroll.EnableDrag();
2325     m_aVertScroll.Show();
2326     long nWidth = GetOutputSizePixel().Width();
2327     m_aHeaderBar.SetPosSizePixel( Point(), Size( nWidth, m_aVertScroll.GetPosPixel().Y() ) );
2328     const HeaderBarItemBits nHeadBits = HIB_VCENTER | HIB_FIXED | HIB_FIXEDPOS | HIB_LEFT;
2329     nWidth = nWidth / 4;
2330     ResMgr* pResMgr = rResId.GetResMgr();
2331     m_aHeaderBar.InsertItem( HI_NAME, String( ResId( STR_HEADER_NAME, *pResMgr ) ), nWidth, nHeadBits );
2332     m_aHeaderBar.InsertItem( HI_TYPE, String( ResId( STR_HEADER_TYPE, *pResMgr ) ), nWidth, nHeadBits );
2333     m_aHeaderBar.InsertItem( HI_VALUE, String( ResId( STR_HEADER_VALUE, *pResMgr ) ), nWidth, nHeadBits );
2334     m_aHeaderBar.InsertItem( HI_ACTION, String( ResId( STR_HEADER_ACTION, *pResMgr ) ), nWidth, nHeadBits );
2335     m_aHeaderBar.Show();
2336 
2337     FreeResource();
2338 
2339     XubString sTEST = m_aHeaderBar.GetItemText( HI_NAME );
2340 
2341     m_aPropertiesWin.InitControls( &m_aHeaderBar, &m_aVertScroll );
2342     m_aPropertiesWin.SetRemovedHdl( LINK( this, CustomPropertiesControl, RemovedHdl ) );
2343 
2344     m_aVertScroll.SetRangeMin( 0 );
2345     sal_Int32 nScrollOffset = m_aPropertiesWin.GetLineHeight();
2346     sal_Int32 nVisibleEntries = m_aPropertiesWin.GetSizePixel().Height() / nScrollOffset;
2347     m_aVertScroll.SetRangeMax( nVisibleEntries );
2348     m_aVertScroll.SetPageSize( nVisibleEntries - 1 );
2349     m_aVertScroll.SetVisibleSize( nVisibleEntries );
2350 
2351     Point aPos = m_aHeaderBar.GetPosPixel();
2352     Size aSize = m_aHeaderBar.GetSizePixel();
2353     aPos = m_aVertScroll.GetPosPixel();
2354     aSize = m_aVertScroll.GetSizePixel();
2355 
2356     Link aScrollLink = LINK( this, CustomPropertiesControl, ScrollHdl );
2357     m_aVertScroll.SetScrollHdl( aScrollLink );
2358 //    m_aVertScroll.SetEndScrollHdl( aScrollLink );
2359 }
2360 
2361 CustomPropertiesControl::~CustomPropertiesControl()
2362 {
2363 }
2364 
2365 void CustomPropertiesControl::Initialize()
2366 {
2367 }
2368 
2369 IMPL_LINK( CustomPropertiesControl, ScrollHdl, ScrollBar*, pScrollBar )
2370 {
2371     sal_Int32 nOffset = m_aPropertiesWin.GetLineHeight();
2372     nOffset *= ( m_nThumbPos - pScrollBar->GetThumbPos() );
2373     m_nThumbPos = pScrollBar->GetThumbPos();
2374     m_aPropertiesWin.DoScroll( nOffset );
2375     return 0;
2376 }
2377 
2378 IMPL_LINK( CustomPropertiesControl, RemovedHdl, void*, EMPTYARG )
2379 {
2380     m_aVertScroll.SetRangeMax( m_aPropertiesWin.GetVisibleLineCount() + 1 );
2381     if ( m_aPropertiesWin.GetOutputSizePixel().Height() < m_aPropertiesWin.GetVisibleLineCount() * m_aPropertiesWin.GetLineHeight() )
2382         m_aVertScroll.DoScrollAction ( SCROLL_LINEUP );
2383     return 0;
2384 }
2385 
2386 void CustomPropertiesControl::AddLine( const ::rtl::OUString& sName, Any& rAny, bool bInteractive )
2387 {
2388     m_aPropertiesWin.AddLine( sName, rAny );
2389     m_aVertScroll.SetRangeMax( m_aPropertiesWin.GetVisibleLineCount() + 1 );
2390     if ( bInteractive && m_aPropertiesWin.GetOutputSizePixel().Height() < m_aPropertiesWin.GetVisibleLineCount() * m_aPropertiesWin.GetLineHeight() )
2391         m_aVertScroll.DoScroll( m_aPropertiesWin.GetVisibleLineCount() + 1 );
2392 }
2393 
2394 // class SfxCustomPropertiesPage -----------------------------------------
2395 
2396 SfxCustomPropertiesPage::SfxCustomPropertiesPage( Window* pParent, const SfxItemSet& rItemSet ) :
2397 
2398     SfxTabPage( pParent, SfxResId( TP_CUSTOMPROPERTIES ), rItemSet ),
2399     m_aPropertiesCtrl   ( this, SfxResId( CTRL_PROPERTIES ) ),
2400     m_aAddBtn           ( this, SfxResId( BTN_ADD ) ),
2401     m_aPropertiesFT     ( this, SfxResId( FT_PROPERTIES ) )
2402 
2403 {
2404     FreeResource();
2405 
2406     m_aAddBtn.SetClickHdl( LINK( this, SfxCustomPropertiesPage, AddHdl ) );
2407 }
2408 
2409 IMPL_LINK( SfxCustomPropertiesPage, AddHdl, PushButton*, EMPTYARG )
2410 {
2411     Any aAny;
2412     m_aPropertiesCtrl.AddLine( ::rtl::OUString(), aAny, true );
2413     return 0;
2414 }
2415 
2416 sal_Bool SfxCustomPropertiesPage::FillItemSet( SfxItemSet& rSet )
2417 {
2418     sal_Bool bModified = sal_False;
2419     const SfxPoolItem*      pItem = NULL;
2420     SfxDocumentInfoItem*    pInfo = NULL;
2421     bool                    bMustDelete = false;
2422 
2423     if ( GetTabDialog() && GetTabDialog()->GetExampleSet() )
2424     {
2425         if( SFX_ITEM_SET !=
2426                 GetTabDialog()->GetExampleSet()->GetItemState( SID_DOCINFO, sal_True, &pItem ) )
2427             pInfo = &( SfxDocumentInfoItem& )rSet.Get( SID_DOCINFO );
2428         else
2429         {
2430             bMustDelete = true;
2431             pInfo = new SfxDocumentInfoItem( *( const SfxDocumentInfoItem* ) pItem );
2432         }
2433     }
2434 
2435     if ( pInfo )
2436     {
2437         pInfo->ClearCustomProperties();
2438         Sequence< beans::PropertyValue > aPropertySeq = m_aPropertiesCtrl.GetCustomProperties();
2439         sal_Int32 i = 0, nCount = aPropertySeq.getLength();
2440         for ( ; i < nCount; ++i )
2441         {
2442             if ( aPropertySeq[i].Name.getLength() > 0 )
2443                 pInfo->AddCustomProperty( aPropertySeq[i].Name, aPropertySeq[i].Value );
2444         }
2445     }
2446 
2447     bModified = sal_True; //!!!
2448     if ( bModified )
2449         rSet.Put( *pInfo );
2450     if ( bMustDelete )
2451         delete pInfo;
2452     return bModified;
2453 }
2454 
2455 void SfxCustomPropertiesPage::Reset( const SfxItemSet& rItemSet )
2456 {
2457     m_aPropertiesCtrl.ClearAllLines();
2458     const SfxDocumentInfoItem* pInfoItem = &(const SfxDocumentInfoItem &)rItemSet.Get(SID_DOCINFO);
2459     std::vector< CustomProperty* > aCustomProps = pInfoItem->GetCustomProperties();
2460     for ( sal_uInt32 i = 0; i < aCustomProps.size(); i++ )
2461     {
2462         m_aPropertiesCtrl.AddLine( aCustomProps[i]->m_sName, aCustomProps[i]->m_aValue, false );
2463     }
2464 }
2465 
2466 int SfxCustomPropertiesPage::DeactivatePage( SfxItemSet* /*pSet*/ )
2467 {
2468     int nRet = LEAVE_PAGE;
2469     if ( !m_aPropertiesCtrl.AreAllLinesValid() )
2470         nRet = KEEP_PAGE;
2471     return nRet;
2472 }
2473 
2474 SfxTabPage* SfxCustomPropertiesPage::Create( Window* pParent, const SfxItemSet& rItemSet )
2475 {
2476     return new SfxCustomPropertiesPage( pParent, rItemSet );
2477 }
2478 
2479