1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <svl/eitem.hxx> 21 #include <svl/urihelper.hxx> 22 #include <tools/datetime.hxx> 23 #include <tools/urlobj.hxx> 24 #include <vcl/mnemonic.hxx> 25 #include <vcl/svapp.hxx> 26 #include <vcl/weld.hxx> 27 #include <unotools/datetime.hxx> 28 #include <unotools/localedatawrapper.hxx> 29 #include <unotools/cmdoptions.hxx> 30 #include <comphelper/processfactory.hxx> 31 #include <comphelper/xmlsechelper.hxx> 32 #include <unotools/useroptions.hxx> 33 #include <svtools/controldims.hxx> 34 #include <svtools/imagemgr.hxx> 35 #include <toolkit/helper/vclunohelper.hxx> 36 #include <sal/log.hxx> 37 #include <osl/diagnose.h> 38 39 #include <memory> 40 41 #include <comphelper/sequence.hxx> 42 #include <comphelper/string.hxx> 43 #include <com/sun/star/security/DocumentSignatureInformation.hpp> 44 #include <com/sun/star/security/DocumentDigitalSignatures.hpp> 45 #include <unotools/syslocale.hxx> 46 #include <rtl/math.hxx> 47 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp> 48 #include <com/sun/star/beans/PropertyAttribute.hpp> 49 #include <com/sun/star/beans/XPropertyContainer.hpp> 50 #include <com/sun/star/beans/XPropertySet.hpp> 51 #include <com/sun/star/util/DateTime.hpp> 52 #include <com/sun/star/util/Date.hpp> 53 #include <com/sun/star/util/DateTimeWithTimezone.hpp> 54 #include <com/sun/star/util/DateWithTimezone.hpp> 55 #include <com/sun/star/util/Duration.hpp> 56 #include <com/sun/star/document/XDocumentProperties.hpp> 57 #include <com/sun/star/document/CmisProperty.hpp> 58 59 #include <vcl/timer.hxx> 60 #include <vcl/settings.hxx> 61 #include <sfx2/securitypage.hxx> 62 #include <sfx2/sfxresid.hxx> 63 #include <sfx2/frame.hxx> 64 #include <sfx2/viewfrm.hxx> 65 #include <sfx2/request.hxx> 66 #include <sfx2/passwd.hxx> 67 #include <sfx2/filedlghelper.hxx> 68 #include <sfx2/dinfdlg.hxx> 69 #include <sfx2/sfxsids.hrc> 70 #include <helper.hxx> 71 #include <sfx2/objsh.hxx> 72 #include <sfx2/docfile.hxx> 73 74 #include <documentfontsdialog.hxx> 75 #include <dinfdlg.hrc> 76 #include <sfx2/strings.hrc> 77 #include <strings.hxx> 78 #include <bitmaps.hlst> 79 #include <vcl/help.hxx> 80 #include <vcl/builderfactory.hxx> 81 #include <tools/diagnose_ex.h> 82 83 #include <algorithm> 84 85 using namespace ::com::sun::star; 86 using namespace ::com::sun::star::lang; 87 using namespace ::com::sun::star::ui::dialogs; 88 using namespace ::com::sun::star::uno; 89 90 const sal_uInt16 FONT_PAGE_ID = 99; 91 92 struct CustomProperty 93 { 94 OUString m_sName; 95 css::uno::Any m_aValue; 96 97 CustomProperty( const OUString& sName, const css::uno::Any& rValue ) : 98 m_sName( sName ), m_aValue( rValue ) {} 99 }; 100 101 SfxPoolItem* SfxDocumentInfoItem::CreateDefault() { return new SfxDocumentInfoItem; } 102 103 const sal_uInt16 HI_NAME = 1; 104 const sal_uInt16 HI_TYPE = 2; 105 const sal_uInt16 HI_VALUE = 3; 106 const sal_uInt16 HI_ACTION = 4; 107 108 namespace { 109 110 OUString CreateSizeText( sal_Int64 nSize ) 111 { 112 OUString aUnitStr(" "); 113 aUnitStr += SfxResId(STR_BYTES); 114 sal_Int64 nSize1 = nSize; 115 sal_Int64 nSize2 = nSize1; 116 sal_Int64 nMega = 1024 * 1024; 117 sal_Int64 nGiga = nMega * 1024; 118 double fSize = nSize; 119 int nDec = 0; 120 121 if ( nSize1 >= 10000 && nSize1 < nMega ) 122 { 123 nSize1 /= 1024; 124 aUnitStr = " "; 125 aUnitStr += SfxResId(STR_KB); 126 fSize /= 1024; 127 nDec = 0; 128 } 129 else if ( nSize1 >= nMega && nSize1 < nGiga ) 130 { 131 nSize1 /= nMega; 132 aUnitStr = " "; 133 aUnitStr += SfxResId(STR_MB); 134 fSize /= nMega; 135 nDec = 2; 136 } 137 else if ( nSize1 >= nGiga ) 138 { 139 nSize1 /= nGiga; 140 aUnitStr = " "; 141 aUnitStr += SfxResId(STR_GB); 142 fSize /= nGiga; 143 nDec = 3; 144 } 145 const SvtSysLocale aSysLocale; 146 const LocaleDataWrapper& rLocaleWrapper = aSysLocale.GetLocaleData(); 147 OUString aSizeStr( rLocaleWrapper.getNum( nSize1, 0 ) ); 148 aSizeStr += aUnitStr; 149 if ( nSize1 < nSize2 ) 150 { 151 aSizeStr = ::rtl::math::doubleToUString( fSize, 152 rtl_math_StringFormat_F, nDec, 153 rLocaleWrapper.getNumDecimalSep()[0] ) 154 + aUnitStr 155 + " (" 156 + rLocaleWrapper.getNum( nSize2, 0 ) 157 + " " 158 + SfxResId(STR_BYTES) 159 + ")"; 160 } 161 return aSizeStr; 162 } 163 164 OUString ConvertDateTime_Impl( const OUString& rName, 165 const util::DateTime& uDT, const LocaleDataWrapper& rWrapper ) 166 { 167 Date aD(uDT); 168 tools::Time aT(uDT); 169 const OUString aDelim( ", " ); 170 OUString aStr = rWrapper.getDate( aD ) 171 + aDelim 172 + rWrapper.getTime( aT ); 173 OUString aAuthor = comphelper::string::stripStart(rName, ' '); 174 if (!aAuthor.isEmpty()) 175 { 176 aStr += aDelim; 177 aStr += aAuthor; 178 } 179 return aStr; 180 } 181 182 } 183 184 185 SfxDocumentInfoItem::SfxDocumentInfoItem() 186 : SfxStringItem() 187 , m_AutoloadDelay(0) 188 , m_AutoloadURL() 189 , m_isAutoloadEnabled(false) 190 , m_DefaultTarget() 191 , m_TemplateName() 192 , m_Author() 193 , m_CreationDate() 194 , m_ModifiedBy() 195 , m_ModificationDate() 196 , m_PrintedBy() 197 , m_PrintDate() 198 , m_EditingCycles(0) 199 , m_EditingDuration(0) 200 , m_Description() 201 , m_Keywords() 202 , m_Subject() 203 , m_Title() 204 , m_bHasTemplate( true ) 205 , m_bDeleteUserData( false ) 206 , m_bUseUserData( true ) 207 , m_bUseThumbnailSave( true ) 208 { 209 } 210 211 SfxDocumentInfoItem::SfxDocumentInfoItem( const OUString& rFile, 212 const uno::Reference<document::XDocumentProperties>& i_xDocProps, 213 const uno::Sequence<document::CmisProperty>& i_cmisProps, 214 bool bIs, bool _bIs ) 215 : SfxStringItem( SID_DOCINFO, rFile ) 216 , m_AutoloadDelay( i_xDocProps->getAutoloadSecs() ) 217 , m_AutoloadURL( i_xDocProps->getAutoloadURL() ) 218 , m_isAutoloadEnabled( (m_AutoloadDelay > 0) || !m_AutoloadURL.isEmpty() ) 219 , m_DefaultTarget( i_xDocProps->getDefaultTarget() ) 220 , m_TemplateName( i_xDocProps->getTemplateName() ) 221 , m_Author( i_xDocProps->getAuthor() ) 222 , m_CreationDate( i_xDocProps->getCreationDate() ) 223 , m_ModifiedBy( i_xDocProps->getModifiedBy() ) 224 , m_ModificationDate( i_xDocProps->getModificationDate() ) 225 , m_PrintedBy( i_xDocProps->getPrintedBy() ) 226 , m_PrintDate( i_xDocProps->getPrintDate() ) 227 , m_EditingCycles( i_xDocProps->getEditingCycles() ) 228 , m_EditingDuration( i_xDocProps->getEditingDuration() ) 229 , m_Description( i_xDocProps->getDescription() ) 230 , m_Keywords( ::comphelper::string::convertCommaSeparated( 231 i_xDocProps->getKeywords()) ) 232 , m_Subject( i_xDocProps->getSubject() ) 233 , m_Title( i_xDocProps->getTitle() ) 234 , m_bHasTemplate( true ) 235 , m_bDeleteUserData( false ) 236 , m_bUseUserData( bIs ) 237 , m_bUseThumbnailSave( _bIs ) 238 { 239 try 240 { 241 Reference< beans::XPropertyContainer > xContainer = i_xDocProps->getUserDefinedProperties(); 242 if ( xContainer.is() ) 243 { 244 Reference < beans::XPropertySet > xSet( xContainer, UNO_QUERY ); 245 const Sequence< beans::Property > lProps = xSet->getPropertySetInfo()->getProperties(); 246 const beans::Property* pProps = lProps.getConstArray(); 247 sal_Int32 nCount = lProps.getLength(); 248 for ( sal_Int32 i = 0; i < nCount; ++i ) 249 { 250 // "fix" property? => not a custom property => ignore it! 251 if (!(pProps[i].Attributes & css::beans::PropertyAttribute::REMOVABLE)) 252 { 253 SAL_WARN( "sfx.dialog", "non-removable user-defined property?"); 254 continue; 255 } 256 257 uno::Any aValue = xSet->getPropertyValue(pProps[i].Name); 258 std::unique_ptr<CustomProperty> pProp(new CustomProperty( pProps[i].Name, aValue )); 259 m_aCustomProperties.push_back( std::move(pProp) ); 260 } 261 } 262 263 // get CMIS properties 264 m_aCmisProperties = i_cmisProps; 265 } 266 catch ( Exception& ) {} 267 } 268 269 270 SfxDocumentInfoItem::SfxDocumentInfoItem( const SfxDocumentInfoItem& rItem ) 271 : SfxStringItem( rItem ) 272 , m_AutoloadDelay( rItem.getAutoloadDelay() ) 273 , m_AutoloadURL( rItem.getAutoloadURL() ) 274 , m_isAutoloadEnabled( rItem.isAutoloadEnabled() ) 275 , m_DefaultTarget( rItem.getDefaultTarget() ) 276 , m_TemplateName( rItem.getTemplateName() ) 277 , m_Author( rItem.getAuthor() ) 278 , m_CreationDate( rItem.getCreationDate() ) 279 , m_ModifiedBy( rItem.getModifiedBy() ) 280 , m_ModificationDate( rItem.getModificationDate() ) 281 , m_PrintedBy( rItem.getPrintedBy() ) 282 , m_PrintDate( rItem.getPrintDate() ) 283 , m_EditingCycles( rItem.getEditingCycles() ) 284 , m_EditingDuration( rItem.getEditingDuration() ) 285 , m_Description( rItem.getDescription() ) 286 , m_Keywords( rItem.getKeywords() ) 287 , m_Subject( rItem.getSubject() ) 288 , m_Title( rItem.getTitle() ) 289 , m_bHasTemplate( rItem.m_bHasTemplate ) 290 , m_bDeleteUserData( rItem.m_bDeleteUserData ) 291 , m_bUseUserData( rItem.m_bUseUserData ) 292 , m_bUseThumbnailSave( rItem.m_bUseThumbnailSave ) 293 { 294 for (auto const & pOtherProp : rItem.m_aCustomProperties) 295 { 296 std::unique_ptr<CustomProperty> pProp(new CustomProperty( pOtherProp->m_sName, 297 pOtherProp->m_aValue )); 298 m_aCustomProperties.push_back( std::move(pProp) ); 299 } 300 301 m_aCmisProperties = rItem.m_aCmisProperties; 302 } 303 304 305 SfxDocumentInfoItem::~SfxDocumentInfoItem() 306 { 307 ClearCustomProperties(); 308 } 309 310 311 SfxPoolItem* SfxDocumentInfoItem::Clone( SfxItemPool * ) const 312 { 313 return new SfxDocumentInfoItem( *this ); 314 } 315 316 317 bool SfxDocumentInfoItem::operator==( const SfxPoolItem& rItem) const 318 { 319 if (!(typeid(rItem) == typeid(*this) && SfxStringItem::operator==(rItem))) 320 return false; 321 const SfxDocumentInfoItem& rInfoItem(static_cast<const SfxDocumentInfoItem&>(rItem)); 322 323 return 324 m_AutoloadDelay == rInfoItem.m_AutoloadDelay && 325 m_AutoloadURL == rInfoItem.m_AutoloadURL && 326 m_isAutoloadEnabled == rInfoItem.m_isAutoloadEnabled && 327 m_DefaultTarget == rInfoItem.m_DefaultTarget && 328 m_Author == rInfoItem.m_Author && 329 m_CreationDate == rInfoItem.m_CreationDate && 330 m_ModifiedBy == rInfoItem.m_ModifiedBy && 331 m_ModificationDate == rInfoItem.m_ModificationDate && 332 m_PrintedBy == rInfoItem.m_PrintedBy && 333 m_PrintDate == rInfoItem.m_PrintDate && 334 m_EditingCycles == rInfoItem.m_EditingCycles && 335 m_EditingDuration == rInfoItem.m_EditingDuration && 336 m_Description == rInfoItem.m_Description && 337 m_Keywords == rInfoItem.m_Keywords && 338 m_Subject == rInfoItem.m_Subject && 339 m_Title == rInfoItem.m_Title && 340 m_aCustomProperties.size() == rInfoItem.m_aCustomProperties.size() && 341 std::equal(m_aCustomProperties.begin(), m_aCustomProperties.end(), 342 rInfoItem.m_aCustomProperties.begin()) && 343 m_aCmisProperties.getLength() == rInfoItem.m_aCmisProperties.getLength(); 344 } 345 346 347 void SfxDocumentInfoItem::resetUserData(const OUString & i_rAuthor) 348 { 349 setAuthor(i_rAuthor); 350 DateTime now( DateTime::SYSTEM ); 351 m_CreationDate = now.GetUNODateTime(); 352 setModifiedBy(OUString()); 353 setPrintedBy(OUString()); 354 m_ModificationDate = util::DateTime(); 355 m_PrintDate = util::DateTime(); 356 setEditingDuration(0); 357 setEditingCycles(1); 358 } 359 360 361 void SfxDocumentInfoItem::UpdateDocumentInfo( 362 const uno::Reference<document::XDocumentProperties>& i_xDocProps, 363 bool i_bDoNotUpdateUserDefined) const 364 { 365 if (isAutoloadEnabled()) { 366 i_xDocProps->setAutoloadSecs(getAutoloadDelay()); 367 i_xDocProps->setAutoloadURL(getAutoloadURL()); 368 } else { 369 i_xDocProps->setAutoloadSecs(0); 370 i_xDocProps->setAutoloadURL(OUString()); 371 } 372 i_xDocProps->setDefaultTarget(getDefaultTarget()); 373 i_xDocProps->setAuthor(getAuthor()); 374 i_xDocProps->setCreationDate(getCreationDate()); 375 i_xDocProps->setModifiedBy(getModifiedBy()); 376 i_xDocProps->setModificationDate(getModificationDate()); 377 i_xDocProps->setPrintedBy(getPrintedBy()); 378 i_xDocProps->setPrintDate(getPrintDate()); 379 i_xDocProps->setEditingCycles(getEditingCycles()); 380 i_xDocProps->setEditingDuration(getEditingDuration()); 381 i_xDocProps->setDescription(getDescription()); 382 i_xDocProps->setKeywords( 383 ::comphelper::string::convertCommaSeparated(getKeywords())); 384 i_xDocProps->setSubject(getSubject()); 385 i_xDocProps->setTitle(getTitle()); 386 387 // this is necessary in case of replaying a recorded macro: 388 // in this case, the macro may contain the 4 old user-defined DocumentInfo 389 // fields, but not any of the DocumentInfo properties; 390 // as a consequence, most of the UserDefined properties of the 391 // DocumentProperties would be summarily deleted here, which does not 392 // seem like a good idea. 393 if (i_bDoNotUpdateUserDefined) 394 return; 395 396 try 397 { 398 Reference< beans::XPropertyContainer > xContainer = i_xDocProps->getUserDefinedProperties(); 399 Reference < beans::XPropertySet > xSet( xContainer, UNO_QUERY ); 400 Reference< beans::XPropertySetInfo > xSetInfo = xSet->getPropertySetInfo(); 401 const Sequence< beans::Property > lProps = xSetInfo->getProperties(); 402 const beans::Property* pProps = lProps.getConstArray(); 403 sal_Int32 nCount = lProps.getLength(); 404 for ( sal_Int32 j = 0; j < nCount; ++j ) 405 { 406 if (pProps[j].Attributes & css::beans::PropertyAttribute::REMOVABLE) 407 { 408 xContainer->removeProperty( pProps[j].Name ); 409 } 410 } 411 412 for (auto const & pProp : m_aCustomProperties) 413 { 414 try 415 { 416 xContainer->addProperty( pProp->m_sName, 417 beans::PropertyAttribute::REMOVABLE, pProp->m_aValue ); 418 } 419 catch ( Exception const & ) 420 { 421 css::uno::Any ex( cppu::getCaughtException() ); 422 SAL_WARN( "sfx.dialog", "SfxDocumentInfoItem::updateDocumentInfo(): exception while adding custom properties " << exceptionToString(ex) ); 423 } 424 } 425 } 426 catch ( Exception const & ) 427 { 428 css::uno::Any ex( cppu::getCaughtException() ); 429 SAL_WARN( "sfx.dialog", "SfxDocumentInfoItem::updateDocumentInfo(): exception while removing custom properties " << exceptionToString(ex) ); 430 } 431 } 432 433 434 void SfxDocumentInfoItem::SetDeleteUserData( bool bSet ) 435 { 436 m_bDeleteUserData = bSet; 437 } 438 439 440 void SfxDocumentInfoItem::SetUseUserData( bool bSet ) 441 { 442 m_bUseUserData = bSet; 443 } 444 445 void SfxDocumentInfoItem::SetUseThumbnailSave( bool bSet ) 446 { 447 m_bUseThumbnailSave = bSet; 448 } 449 450 std::vector< std::unique_ptr<CustomProperty> > SfxDocumentInfoItem::GetCustomProperties() const 451 { 452 std::vector< std::unique_ptr<CustomProperty> > aRet; 453 for (auto const & pOtherProp : m_aCustomProperties) 454 { 455 std::unique_ptr<CustomProperty> pProp(new CustomProperty( pOtherProp->m_sName, 456 pOtherProp->m_aValue )); 457 aRet.push_back( std::move(pProp) ); 458 } 459 460 return aRet; 461 } 462 463 void SfxDocumentInfoItem::ClearCustomProperties() 464 { 465 m_aCustomProperties.clear(); 466 } 467 468 void SfxDocumentInfoItem::AddCustomProperty( const OUString& sName, const Any& rValue ) 469 { 470 std::unique_ptr<CustomProperty> pProp(new CustomProperty( sName, rValue )); 471 m_aCustomProperties.push_back( std::move(pProp) ); 472 } 473 474 475 void SfxDocumentInfoItem::SetCmisProperties( const Sequence< document::CmisProperty >& cmisProps) 476 { 477 m_aCmisProperties = cmisProps; 478 } 479 480 bool SfxDocumentInfoItem::QueryValue( Any& rVal, sal_uInt8 nMemberId ) const 481 { 482 OUString aValue; 483 sal_Int32 nValue = 0; 484 bool bValue = false; 485 bool bIsInt = false; 486 bool bIsString = false; 487 nMemberId &= ~CONVERT_TWIPS; 488 switch ( nMemberId ) 489 { 490 case MID_DOCINFO_USEUSERDATA: 491 bValue = IsUseUserData(); 492 break; 493 case MID_DOCINFO_USETHUMBNAILSAVE: 494 bValue = IsUseThumbnailSave(); 495 break; 496 case MID_DOCINFO_DELETEUSERDATA: 497 bValue = IsDeleteUserData(); 498 break; 499 case MID_DOCINFO_AUTOLOADENABLED: 500 bValue = isAutoloadEnabled(); 501 break; 502 case MID_DOCINFO_AUTOLOADSECS: 503 bIsInt = true; 504 nValue = getAutoloadDelay(); 505 break; 506 case MID_DOCINFO_AUTOLOADURL: 507 bIsString = true; 508 aValue = getAutoloadURL(); 509 break; 510 case MID_DOCINFO_DEFAULTTARGET: 511 bIsString = true; 512 aValue = getDefaultTarget(); 513 break; 514 case MID_DOCINFO_DESCRIPTION: 515 bIsString = true; 516 aValue = getDescription(); 517 break; 518 case MID_DOCINFO_KEYWORDS: 519 bIsString = true; 520 aValue = getKeywords(); 521 break; 522 case MID_DOCINFO_SUBJECT: 523 bIsString = true; 524 aValue = getSubject(); 525 break; 526 case MID_DOCINFO_TITLE: 527 bIsString = true; 528 aValue = getTitle(); 529 break; 530 default: 531 OSL_FAIL("Wrong MemberId!"); 532 return false; 533 } 534 535 if ( bIsString ) 536 rVal <<= aValue; 537 else if ( bIsInt ) 538 rVal <<= nValue; 539 else 540 rVal <<= bValue; 541 return true; 542 } 543 544 bool SfxDocumentInfoItem::PutValue( const Any& rVal, sal_uInt8 nMemberId ) 545 { 546 OUString aValue; 547 sal_Int32 nValue=0; 548 bool bValue = false; 549 bool bRet = false; 550 nMemberId &= ~CONVERT_TWIPS; 551 switch ( nMemberId ) 552 { 553 case MID_DOCINFO_USEUSERDATA: 554 bRet = (rVal >>= bValue); 555 if ( bRet ) 556 SetUseUserData( bValue ); 557 break; 558 case MID_DOCINFO_USETHUMBNAILSAVE: 559 bRet = (rVal >>=bValue); 560 if ( bRet ) 561 SetUseThumbnailSave( bValue ); 562 break; 563 case MID_DOCINFO_DELETEUSERDATA: 564 // QUESTION: deleting user data was done here; seems to be superfluous! 565 bRet = (rVal >>= bValue); 566 if ( bRet ) 567 SetDeleteUserData( bValue ); 568 break; 569 case MID_DOCINFO_AUTOLOADENABLED: 570 bRet = (rVal >>= bValue); 571 if ( bRet ) 572 setAutoloadEnabled(bValue); 573 break; 574 case MID_DOCINFO_AUTOLOADSECS: 575 bRet = (rVal >>= nValue); 576 if ( bRet ) 577 setAutoloadDelay(nValue); 578 break; 579 case MID_DOCINFO_AUTOLOADURL: 580 bRet = (rVal >>= aValue); 581 if ( bRet ) 582 setAutoloadURL(aValue); 583 break; 584 case MID_DOCINFO_DEFAULTTARGET: 585 bRet = (rVal >>= aValue); 586 if ( bRet ) 587 setDefaultTarget(aValue); 588 break; 589 case MID_DOCINFO_DESCRIPTION: 590 bRet = (rVal >>= aValue); 591 if ( bRet ) 592 setDescription(aValue); 593 break; 594 case MID_DOCINFO_KEYWORDS: 595 bRet = (rVal >>= aValue); 596 if ( bRet ) 597 setKeywords(aValue); 598 break; 599 case MID_DOCINFO_SUBJECT: 600 bRet = (rVal >>= aValue); 601 if ( bRet ) 602 setSubject(aValue); 603 break; 604 case MID_DOCINFO_TITLE: 605 bRet = (rVal >>= aValue); 606 if ( bRet ) 607 setTitle(aValue); 608 break; 609 default: 610 OSL_FAIL("Wrong MemberId!"); 611 return false; 612 } 613 614 return bRet; 615 } 616 617 SfxDocumentDescPage::SfxDocumentDescPage(TabPageParent pParent, const SfxItemSet& rItemSet) 618 : SfxTabPage(pParent, "sfx/ui/descriptioninfopage.ui", "DescriptionInfoPage", &rItemSet) 619 , m_pInfoItem( nullptr) 620 , m_xTitleEd(m_xBuilder->weld_entry("title")) 621 , m_xThemaEd(m_xBuilder->weld_entry("subject")) 622 , m_xKeywordsEd(m_xBuilder->weld_entry("keywords")) 623 , m_xCommentEd(m_xBuilder->weld_text_view("comments")) 624 { 625 m_xCommentEd->set_size_request(m_xKeywordsEd->get_preferred_size().Width(), 626 m_xCommentEd->get_height_rows(16)); 627 } 628 629 SfxDocumentDescPage::~SfxDocumentDescPage() 630 { 631 } 632 633 VclPtr<SfxTabPage> SfxDocumentDescPage::Create(TabPageParent pParent, const SfxItemSet *rItemSet) 634 { 635 return VclPtr<SfxDocumentDescPage>::Create(pParent, *rItemSet); 636 } 637 638 bool SfxDocumentDescPage::FillItemSet(SfxItemSet *rSet) 639 { 640 // Test whether a change is present 641 const bool bTitleMod = m_xTitleEd->get_value_changed_from_saved(); 642 const bool bThemeMod = m_xThemaEd->get_value_changed_from_saved(); 643 const bool bKeywordsMod = m_xKeywordsEd->get_value_changed_from_saved(); 644 const bool bCommentMod = m_xCommentEd->get_value_changed_from_saved(); 645 if ( !( bTitleMod || bThemeMod || bKeywordsMod || bCommentMod ) ) 646 { 647 return false; 648 } 649 650 // Generating the output data 651 const SfxPoolItem* pItem = nullptr; 652 SfxDocumentInfoItem* pInfo = nullptr; 653 const SfxItemSet* pExSet = GetDialogExampleSet(); 654 655 if ( pExSet && SfxItemState::SET != pExSet->GetItemState( SID_DOCINFO, true, &pItem ) ) 656 pInfo = m_pInfoItem; 657 else if ( pItem ) 658 pInfo = new SfxDocumentInfoItem( *static_cast<const SfxDocumentInfoItem *>(pItem) ); 659 660 if ( !pInfo ) 661 { 662 SAL_WARN( "sfx.dialog", "SfxDocumentDescPage::FillItemSet(): no item found" ); 663 return false; 664 } 665 666 if ( bTitleMod ) 667 { 668 pInfo->setTitle( m_xTitleEd->get_text() ); 669 } 670 if ( bThemeMod ) 671 { 672 pInfo->setSubject( m_xThemaEd->get_text() ); 673 } 674 if ( bKeywordsMod ) 675 { 676 pInfo->setKeywords( m_xKeywordsEd->get_text() ); 677 } 678 if ( bCommentMod ) 679 { 680 pInfo->setDescription( m_xCommentEd->get_text() ); 681 } 682 rSet->Put( *pInfo ); 683 if ( pInfo != m_pInfoItem ) 684 { 685 delete pInfo; 686 } 687 688 return true; 689 } 690 691 void SfxDocumentDescPage::Reset(const SfxItemSet *rSet) 692 { 693 m_pInfoItem = const_cast<SfxDocumentInfoItem*>(&rSet->Get(SID_DOCINFO)); 694 695 m_xTitleEd->set_text(m_pInfoItem->getTitle()); 696 m_xThemaEd->set_text(m_pInfoItem->getSubject()); 697 m_xKeywordsEd->set_text(m_pInfoItem->getKeywords()); 698 m_xCommentEd->set_text(m_pInfoItem->getDescription()); 699 700 m_xTitleEd->save_value(); 701 m_xThemaEd->save_value(); 702 m_xKeywordsEd->save_value(); 703 m_xCommentEd->save_value(); 704 705 const SfxBoolItem* pROItem = SfxItemSet::GetItem<SfxBoolItem>(rSet, SID_DOC_READONLY, false); 706 if (pROItem && pROItem->GetValue()) 707 { 708 m_xTitleEd->set_editable(false); 709 m_xThemaEd->set_editable(false); 710 m_xKeywordsEd->set_editable(false); 711 m_xCommentEd->set_editable(false); 712 } 713 } 714 715 SfxDocumentPage::SfxDocumentPage(TabPageParent pParent, const SfxItemSet& rItemSet) 716 : SfxTabPage(pParent, "sfx/ui/documentinfopage.ui", "DocumentInfoPage", &rItemSet) 717 , bEnableUseUserData( false ) 718 , bHandleDelete( false ) 719 , m_xBmp(m_xBuilder->weld_image("icon")) 720 , m_xNameED(m_xBuilder->weld_label("nameed")) 721 , m_xChangePassBtn(m_xBuilder->weld_button("changepass")) 722 , m_xShowTypeFT(m_xBuilder->weld_label("showtype")) 723 , m_xFileValEd(m_xBuilder->weld_label("showlocation")) 724 , m_xShowSizeFT(m_xBuilder->weld_label("showsize")) 725 , m_xCreateValFt(m_xBuilder->weld_label("showcreate")) 726 , m_xChangeValFt(m_xBuilder->weld_label("showmodify")) 727 , m_xSignedValFt(m_xBuilder->weld_label("showsigned")) 728 , m_xSignatureBtn(m_xBuilder->weld_button("signature")) 729 , m_xPrintValFt(m_xBuilder->weld_label("showprint")) 730 , m_xTimeLogValFt(m_xBuilder->weld_label("showedittime")) 731 , m_xDocNoValFt(m_xBuilder->weld_label("showrevision")) 732 , m_xUseUserDataCB(m_xBuilder->weld_check_button("userdatacb")) 733 , m_xDeleteBtn(m_xBuilder->weld_button("reset")) 734 , m_xUseThumbnailSaveCB(m_xBuilder->weld_check_button("thumbnailsavecb")) 735 , m_xTemplFt(m_xBuilder->weld_label("templateft")) 736 , m_xTemplValFt(m_xBuilder->weld_label("showtemplate")) 737 { 738 m_aUnknownSize = m_xShowSizeFT->get_label(); 739 m_xShowSizeFT->set_label(OUString()); 740 741 m_aMultiSignedStr = m_xSignedValFt->get_label(); 742 m_xSignedValFt->set_label(OUString()); 743 744 ImplUpdateSignatures(); 745 ImplCheckPasswordState(); 746 m_xChangePassBtn->connect_clicked( LINK( this, SfxDocumentPage, ChangePassHdl ) ); 747 m_xSignatureBtn->connect_clicked( LINK( this, SfxDocumentPage, SignatureHdl ) ); 748 m_xDeleteBtn->connect_clicked( LINK( this, SfxDocumentPage, DeleteHdl ) ); 749 750 // [i96288] Check if the document signature command is enabled 751 // on the main list enable/disable the pushbutton accordingly 752 SvtCommandOptions aCmdOptions; 753 if ( aCmdOptions.Lookup( SvtCommandOptions::CMDOPTION_DISABLED, "Signature" ) ) 754 m_xSignatureBtn->set_sensitive(false); 755 } 756 757 SfxDocumentPage::~SfxDocumentPage() 758 { 759 disposeOnce(); 760 } 761 762 IMPL_LINK_NOARG(SfxDocumentPage, DeleteHdl, weld::Button&, void) 763 { 764 OUString aName; 765 if (bEnableUseUserData && m_xUseUserDataCB->get_active()) 766 aName = SvtUserOptions().GetFullName(); 767 const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() ); 768 DateTime now( DateTime::SYSTEM ); 769 util::DateTime uDT( now.GetUNODateTime() ); 770 m_xCreateValFt->set_label( ConvertDateTime_Impl( aName, uDT, rLocaleWrapper ) ); 771 m_xChangeValFt->set_label( "" ); 772 m_xPrintValFt->set_label( "" ); 773 const tools::Time aTime( 0 ); 774 m_xTimeLogValFt->set_label( rLocaleWrapper.getDuration( aTime ) ); 775 m_xDocNoValFt->set_label(OUString('1')); 776 bHandleDelete = true; 777 } 778 779 IMPL_LINK_NOARG(SfxDocumentPage, SignatureHdl, weld::Button&, void) 780 { 781 SfxObjectShell* pDoc = SfxObjectShell::Current(); 782 if( pDoc ) 783 { 784 pDoc->SignDocumentContent(GetFrameWeld()); 785 786 ImplUpdateSignatures(); 787 } 788 } 789 790 IMPL_LINK_NOARG(SfxDocumentPage, ChangePassHdl, weld::Button&, void) 791 { 792 SfxObjectShell* pShell = SfxObjectShell::Current(); 793 do 794 { 795 if (!pShell) 796 break; 797 SfxItemSet* pMedSet = pShell->GetMedium()->GetItemSet(); 798 if (!pMedSet) 799 break; 800 std::shared_ptr<const SfxFilter> pFilter = pShell->GetMedium()->GetFilter(); 801 if (!pFilter) 802 break; 803 804 sfx2::RequestPassword(pFilter, OUString(), pMedSet, VCLUnoHelper::GetInterface(GetParentDialog())); 805 pShell->SetModified(); 806 } 807 while (false); 808 } 809 810 void SfxDocumentPage::ImplUpdateSignatures() 811 { 812 SfxObjectShell* pDoc = SfxObjectShell::Current(); 813 if ( !pDoc ) 814 return; 815 816 SfxMedium* pMedium = pDoc->GetMedium(); 817 if ( !pMedium || pMedium->GetName().isEmpty() || !pMedium->GetStorage().is() ) 818 return; 819 820 Reference< security::XDocumentDigitalSignatures > xD; 821 try 822 { 823 xD = security::DocumentDigitalSignatures::createDefault(comphelper::getProcessComponentContext()); 824 xD->setParentWindow(VCLUnoHelper::GetInterface(GetTabDialog())); 825 } 826 catch ( const css::uno::DeploymentException& ) 827 { 828 } 829 OUString s; 830 Sequence< security::DocumentSignatureInformation > aInfos; 831 832 if ( xD.is() ) 833 aInfos = xD->verifyDocumentContentSignatures( pMedium->GetZipStorageToSign_Impl(), 834 uno::Reference< io::XInputStream >() ); 835 if ( aInfos.getLength() > 1 ) 836 s = m_aMultiSignedStr; 837 else if ( aInfos.getLength() == 1 ) 838 { 839 const security::DocumentSignatureInformation& rInfo = aInfos[ 0 ]; 840 s = utl::GetDateTimeString( rInfo.SignatureDate, rInfo.SignatureTime ); 841 s += ", "; 842 s += comphelper::xmlsec::GetContentPart(rInfo.Signer->getSubjectName()); 843 } 844 m_xSignedValFt->set_label(s); 845 } 846 847 void SfxDocumentPage::ImplCheckPasswordState() 848 { 849 SfxObjectShell* pShell = SfxObjectShell::Current(); 850 do 851 { 852 if (!pShell) 853 break; 854 SfxItemSet* pMedSet = pShell->GetMedium()->GetItemSet(); 855 if (!pMedSet) 856 break; 857 const SfxUnoAnyItem* pEncryptionDataItem = SfxItemSet::GetItem<SfxUnoAnyItem>(pMedSet, SID_ENCRYPTIONDATA, false); 858 uno::Sequence< beans::NamedValue > aEncryptionData; 859 if (pEncryptionDataItem) 860 pEncryptionDataItem->GetValue() >>= aEncryptionData; 861 else 862 break; 863 864 if (!aEncryptionData.getLength()) 865 break; 866 m_xChangePassBtn->set_sensitive(true); 867 return; 868 } 869 while (false); 870 m_xChangePassBtn->set_sensitive(false); 871 } 872 873 VclPtr<SfxTabPage> SfxDocumentPage::Create( TabPageParent pParent, const SfxItemSet* rItemSet ) 874 { 875 return VclPtr<SfxDocumentPage>::Create( pParent, *rItemSet ); 876 } 877 878 void SfxDocumentPage::EnableUseUserData() 879 { 880 bEnableUseUserData = true; 881 m_xUseUserDataCB->show(); 882 m_xDeleteBtn->show(); 883 } 884 885 bool SfxDocumentPage::FillItemSet( SfxItemSet* rSet ) 886 { 887 bool bRet = false; 888 889 if ( !bHandleDelete && bEnableUseUserData && 890 m_xUseUserDataCB->get_state_changed_from_saved() ) 891 { 892 const SfxItemSet* pExpSet = GetDialogExampleSet(); 893 const SfxPoolItem* pItem; 894 895 if ( pExpSet && SfxItemState::SET == pExpSet->GetItemState( SID_DOCINFO, true, &pItem ) ) 896 { 897 const SfxDocumentInfoItem* pInfoItem = static_cast<const SfxDocumentInfoItem*>(pItem); 898 bool bUseData = ( TRISTATE_TRUE == m_xUseUserDataCB->get_state() ); 899 const_cast<SfxDocumentInfoItem*>(pInfoItem)->SetUseUserData( bUseData ); 900 rSet->Put( *pInfoItem ); 901 bRet = true; 902 } 903 } 904 905 if ( bHandleDelete ) 906 { 907 const SfxItemSet* pExpSet = GetDialogExampleSet(); 908 const SfxPoolItem* pItem; 909 if ( pExpSet && SfxItemState::SET == pExpSet->GetItemState( SID_DOCINFO, true, &pItem ) ) 910 { 911 const SfxDocumentInfoItem* pInfoItem = static_cast<const SfxDocumentInfoItem*>(pItem); 912 bool bUseAuthor = bEnableUseUserData && m_xUseUserDataCB->get_active(); 913 SfxDocumentInfoItem newItem( *pInfoItem ); 914 newItem.resetUserData( bUseAuthor 915 ? SvtUserOptions().GetFullName() 916 : OUString() ); 917 const_cast<SfxDocumentInfoItem*>(pInfoItem)->SetUseUserData( TRISTATE_TRUE == m_xUseUserDataCB->get_state() ); 918 newItem.SetUseUserData( TRISTATE_TRUE == m_xUseUserDataCB->get_state() ); 919 920 newItem.SetDeleteUserData( true ); 921 rSet->Put( newItem ); 922 bRet = true; 923 } 924 } 925 926 if ( m_xUseThumbnailSaveCB->get_state_changed_from_saved() ) 927 { 928 const SfxItemSet* pExpSet = GetDialogExampleSet(); 929 const SfxPoolItem* pItem; 930 931 if ( pExpSet && SfxItemState::SET == pExpSet->GetItemState( SID_DOCINFO, true, &pItem ) ) 932 { 933 const SfxDocumentInfoItem* pInfoItem = static_cast<const SfxDocumentInfoItem*>(pItem); 934 bool bUseThumbnail = ( TRISTATE_TRUE == m_xUseThumbnailSaveCB->get_state() ); 935 const_cast<SfxDocumentInfoItem*>(pInfoItem)->SetUseThumbnailSave( bUseThumbnail ); 936 rSet->Put( *pInfoItem ); 937 bRet = true; 938 } 939 } 940 941 return bRet; 942 } 943 944 void SfxDocumentPage::Reset( const SfxItemSet* rSet ) 945 { 946 // Determine the document information 947 const SfxDocumentInfoItem& rInfoItem = rSet->Get(SID_DOCINFO); 948 949 // template data 950 if (rInfoItem.HasTemplate()) 951 { 952 const OUString& rName = rInfoItem.getTemplateName(); 953 if (rName.getLength() > SAL_MAX_INT16) // tdf#122780 pick some ~arbitrary max size 954 m_xTemplValFt->set_label(rName.copy(0, SAL_MAX_INT16)); 955 else 956 m_xTemplValFt->set_label(rName); 957 } 958 else 959 { 960 m_xTemplFt->hide(); 961 m_xTemplValFt->hide(); 962 } 963 964 // determine file name 965 OUString aFile( rInfoItem.GetValue() ); 966 OUString aFactory( aFile ); 967 if ( aFile.getLength() > 2 && aFile[0] == '[' ) 968 { 969 sal_Int32 nPos = aFile.indexOf( ']' ); 970 aFactory = aFile.copy( 1, nPos-1 ); 971 aFile = aFile.copy( nPos+1 ); 972 } 973 974 // determine name 975 INetURLObject aURL(aFile); 976 OUString aName = aURL.GetName( INetURLObject::DecodeMechanism::WithCharset ); 977 if ( aName.isEmpty() || aURL.GetProtocol() == INetProtocol::PrivSoffice ) 978 aName = SfxResId( STR_NONAME ); 979 m_xNameED->set_label( aName ); 980 981 // determine context symbol 982 aURL.SetSmartProtocol( INetProtocol::File ); 983 aURL.SetSmartURL( aFactory); 984 const OUString& rMainURL = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ); 985 OUString aImage = SvFileInformationManager::GetImageId( aURL, true ); 986 m_xBmp->set_from_icon_name(aImage); 987 988 // determine size and type 989 OUString aSizeText( m_aUnknownSize ); 990 if ( aURL.GetProtocol() == INetProtocol::File || 991 aURL.isAnyKnownWebDAVScheme() ) 992 aSizeText = CreateSizeText( SfxContentHelper::GetSize( aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ); 993 m_xShowSizeFT->set_label( aSizeText ); 994 995 OUString aDescription = SvFileInformationManager::GetDescription( INetURLObject(rMainURL) ); 996 if ( aDescription.isEmpty() ) 997 aDescription = SfxResId( STR_SFX_NEWOFFICEDOC ); 998 m_xShowTypeFT->set_label( aDescription ); 999 1000 // determine location 1001 aURL.SetSmartURL( aFile); 1002 if ( aURL.GetProtocol() == INetProtocol::File ) 1003 { 1004 INetURLObject aPath( aURL ); 1005 aPath.setFinalSlash(); 1006 aPath.removeSegment(); 1007 // we know it's a folder -> don't need the final slash, but it's better for WB_PATHELLIPSIS 1008 aPath.removeFinalSlash(); 1009 OUString aText( aPath.PathToFileName() ); //! (pb) MaxLen? 1010 m_xFileValEd->set_label( aText ); 1011 } 1012 else if ( aURL.GetProtocol() != INetProtocol::PrivSoffice ) 1013 m_xFileValEd->set_label( aURL.GetPartBeforeLastName() ); 1014 1015 // handle access data 1016 bool bUseUserData = rInfoItem.IsUseUserData(); 1017 const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetLocaleDataWrapper() ); 1018 m_xCreateValFt->set_label( ConvertDateTime_Impl( rInfoItem.getAuthor(), 1019 rInfoItem.getCreationDate(), rLocaleWrapper ) ); 1020 util::DateTime aTime( rInfoItem.getModificationDate() ); 1021 if ( aTime.Month > 0 ) 1022 m_xChangeValFt->set_label( ConvertDateTime_Impl( 1023 rInfoItem.getModifiedBy(), aTime, rLocaleWrapper ) ); 1024 aTime = rInfoItem.getPrintDate(); 1025 if ( aTime.Month > 0 ) 1026 m_xPrintValFt->set_label( ConvertDateTime_Impl( rInfoItem.getPrintedBy(), 1027 aTime, rLocaleWrapper ) ); 1028 const long nTime = rInfoItem.getEditingDuration(); 1029 if ( bUseUserData ) 1030 { 1031 const tools::Time aT( nTime/3600, (nTime%3600)/60, nTime%60 ); 1032 m_xTimeLogValFt->set_label( rLocaleWrapper.getDuration( aT ) ); 1033 m_xDocNoValFt->set_label( OUString::number( 1034 rInfoItem.getEditingCycles() ) ); 1035 } 1036 1037 bool bUseThumbnailSave = rInfoItem.IsUseThumbnailSave(); 1038 1039 // Check for cmis properties where otherwise unavailable 1040 if ( rInfoItem.isCmisDocument( ) ) 1041 { 1042 uno::Sequence< document::CmisProperty > aCmisProps = rInfoItem.GetCmisProperties(); 1043 for ( sal_Int32 i = 0; i < aCmisProps.getLength(); i++ ) 1044 { 1045 if ( aCmisProps[i].Id == "cmis:contentStreamLength" && 1046 aSizeText == m_aUnknownSize ) 1047 { 1048 Sequence< sal_Int64 > seqValue; 1049 aCmisProps[i].Value >>= seqValue; 1050 SvNumberFormatter aNumberFormatter( ::comphelper::getProcessComponentContext(), 1051 Application::GetSettings().GetLanguageTag().getLanguageType() ); 1052 sal_uInt32 nIndex = aNumberFormatter.GetFormatIndex( NF_NUMBER_SYSTEM ); 1053 if ( seqValue.getLength( ) > 0 ) 1054 { 1055 OUString sValue; 1056 aNumberFormatter.GetInputLineString( seqValue[0], nIndex, sValue ); 1057 m_xShowSizeFT->set_label( CreateSizeText( sValue.toInt64( ) ) ); 1058 } 1059 } 1060 1061 util::DateTime uDT; 1062 OUString emptyDate = ConvertDateTime_Impl( "", uDT, rLocaleWrapper ); 1063 if ( aCmisProps[i].Id == "cmis:creationDate" && 1064 (m_xCreateValFt->get_label() == emptyDate || 1065 m_xCreateValFt->get_label().isEmpty())) 1066 { 1067 Sequence< util::DateTime > seqValue; 1068 aCmisProps[i].Value >>= seqValue; 1069 if ( seqValue.getLength( ) > 0 ) 1070 { 1071 m_xCreateValFt->set_label( ConvertDateTime_Impl( "", seqValue[0], rLocaleWrapper ) ); 1072 } 1073 } 1074 if ( aCmisProps[i].Id == "cmis:lastModificationDate" && 1075 (m_xChangeValFt->get_label() == emptyDate || 1076 m_xChangeValFt->get_label().isEmpty())) 1077 { 1078 Sequence< util::DateTime > seqValue; 1079 aCmisProps[i].Value >>= seqValue; 1080 if ( seqValue.getLength( ) > 0 ) 1081 { 1082 m_xChangeValFt->set_label( ConvertDateTime_Impl( "", seqValue[0], rLocaleWrapper ) ); 1083 } 1084 } 1085 } 1086 } 1087 1088 m_xUseUserDataCB->set_active(bUseUserData); 1089 m_xUseUserDataCB->save_state(); 1090 m_xUseUserDataCB->set_sensitive( bEnableUseUserData ); 1091 bHandleDelete = false; 1092 m_xDeleteBtn->set_sensitive( bEnableUseUserData ); 1093 m_xUseThumbnailSaveCB->set_active(bUseThumbnailSave); 1094 m_xUseThumbnailSaveCB->save_state(); 1095 } 1096 1097 SfxDocumentInfoDialog::SfxDocumentInfoDialog( vcl::Window* pParent, 1098 const SfxItemSet& rItemSet ) 1099 : SfxTabDialog(pParent, "DocumentPropertiesDialog", 1100 "sfx/ui/documentpropertiesdialog.ui", &rItemSet) 1101 , m_nDocInfoId(0) 1102 { 1103 const SfxDocumentInfoItem& rInfoItem = rItemSet.Get( SID_DOCINFO ); 1104 1105 #ifdef DBG_UTIL 1106 const SfxStringItem* pURLItem = rItemSet.GetItem<SfxStringItem>(SID_BASEURL, false); 1107 DBG_ASSERT( pURLItem, "No BaseURL provided for InternetTabPage!" ); 1108 #endif 1109 1110 // Determine the Titles 1111 const SfxPoolItem* pItem = nullptr; 1112 OUString aTitle( GetText() ); 1113 if ( SfxItemState::SET != 1114 rItemSet.GetItemState( SID_EXPLORER_PROPS_START, false, &pItem ) ) 1115 { 1116 // File name 1117 const OUString& aFile( rInfoItem.GetValue() ); 1118 1119 INetURLObject aURL; 1120 aURL.SetSmartProtocol( INetProtocol::File ); 1121 aURL.SetSmartURL( aFile); 1122 if ( INetProtocol::PrivSoffice != aURL.GetProtocol() ) 1123 { 1124 OUString aLastName( aURL.GetLastName() ); 1125 if ( !aLastName.isEmpty() ) 1126 aTitle = aTitle.replaceFirst("%1", aLastName); 1127 else 1128 aTitle = aTitle.replaceFirst("%1", aFile); 1129 } 1130 else 1131 aTitle = aTitle.replaceFirst("%1", SfxResId( STR_NONAME )); 1132 } 1133 else 1134 { 1135 DBG_ASSERT( dynamic_cast<const SfxStringItem *>(pItem) != nullptr, 1136 "SfxDocumentInfoDialog:<SfxStringItem> expected" ); 1137 aTitle = aTitle.replaceFirst("%1", static_cast<const SfxStringItem*>(pItem)->GetValue()); 1138 } 1139 SetText( aTitle ); 1140 1141 // Property Pages 1142 m_nDocInfoId = AddTabPage("general", SfxDocumentPage::Create); 1143 AddTabPage("description", SfxDocumentDescPage::Create); 1144 AddTabPage("customprops", SfxCustomPropertiesPage::Create); 1145 AddTabPage("cmisprops", SfxCmisPropertiesPage::Create); 1146 AddTabPage("security", SfxSecurityPage::Create); 1147 } 1148 1149 1150 void SfxDocumentInfoDialog::PageCreated( sal_uInt16 nId, SfxTabPage &rPage ) 1151 { 1152 if ( m_nDocInfoId == nId ) 1153 static_cast<SfxDocumentPage&>(rPage).EnableUseUserData(); 1154 } 1155 1156 void SfxDocumentInfoDialog::AddFontTabPage() 1157 { 1158 AddTabPage(FONT_PAGE_ID, SfxResId(STR_FONT_TABPAGE), SfxDocumentFontsPage::Create); 1159 SetPageName(FONT_PAGE_ID , "font"); 1160 } 1161 1162 // class CustomPropertiesYesNoButton ------------------------------------- 1163 1164 CustomPropertiesYesNoButton::CustomPropertiesYesNoButton(vcl::Window* pParent) 1165 : Control(pParent, WB_DIALOGCONTROL | WB_BORDER) 1166 , m_aYesButton(VclPtr<RadioButton>::Create(this, WB_TABSTOP)) 1167 , m_aNoButton(VclPtr<RadioButton>::Create(this, WB_TABSTOP)) 1168 { 1169 m_aYesButton->SetText(MnemonicGenerator::EraseAllMnemonicChars(Button::GetStandardText(StandardButtonType::Yes))); 1170 m_aYesButton->Show(); 1171 m_aNoButton->SetText(MnemonicGenerator::EraseAllMnemonicChars(Button::GetStandardText(StandardButtonType::No))); 1172 m_aNoButton->Show(); 1173 SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) ); 1174 SetBorderStyle( WindowBorderStyle::MONO ); 1175 CheckNo(); 1176 Wallpaper aWall( COL_TRANSPARENT ); 1177 m_aYesButton->SetBackground( aWall ); 1178 m_aNoButton->SetBackground( aWall ); 1179 } 1180 1181 CustomPropertiesYesNoButton::~CustomPropertiesYesNoButton() 1182 { 1183 disposeOnce(); 1184 } 1185 1186 void CustomPropertiesYesNoButton::dispose() 1187 { 1188 m_aYesButton.disposeAndClear(); 1189 m_aNoButton.disposeAndClear(); 1190 Control::dispose(); 1191 } 1192 1193 class DurationDialog_Impl : public weld::GenericDialogController 1194 { 1195 std::unique_ptr<weld::CheckButton> m_xNegativeCB; 1196 std::unique_ptr<weld::SpinButton> m_xYearNF; 1197 std::unique_ptr<weld::SpinButton> m_xMonthNF; 1198 std::unique_ptr<weld::SpinButton> m_xDayNF; 1199 std::unique_ptr<weld::SpinButton> m_xHourNF; 1200 std::unique_ptr<weld::SpinButton> m_xMinuteNF; 1201 std::unique_ptr<weld::SpinButton> m_xSecondNF; 1202 std::unique_ptr<weld::SpinButton> m_xMSecondNF; 1203 1204 public: 1205 DurationDialog_Impl(weld::Window* pParent, const util::Duration& rDuration); 1206 util::Duration GetDuration() const; 1207 }; 1208 1209 DurationDialog_Impl::DurationDialog_Impl(weld::Window* pParent, const util::Duration& rDuration) 1210 : GenericDialogController(pParent, "sfx/ui/editdurationdialog.ui", "EditDurationDialog") 1211 , m_xNegativeCB(m_xBuilder->weld_check_button("negative")) 1212 , m_xYearNF(m_xBuilder->weld_spin_button("years")) 1213 , m_xMonthNF(m_xBuilder->weld_spin_button("months")) 1214 , m_xDayNF(m_xBuilder->weld_spin_button("days")) 1215 , m_xHourNF(m_xBuilder->weld_spin_button("hours")) 1216 , m_xMinuteNF(m_xBuilder->weld_spin_button("minutes")) 1217 , m_xSecondNF(m_xBuilder->weld_spin_button("seconds")) 1218 , m_xMSecondNF(m_xBuilder->weld_spin_button("milliseconds")) 1219 { 1220 m_xNegativeCB->set_active(rDuration.Negative); 1221 m_xYearNF->set_value(rDuration.Years); 1222 m_xMonthNF->set_value(rDuration.Months); 1223 m_xDayNF->set_value(rDuration.Days); 1224 m_xHourNF->set_value(rDuration.Hours); 1225 m_xMinuteNF->set_value(rDuration.Minutes); 1226 m_xSecondNF->set_value(rDuration.Seconds); 1227 m_xMSecondNF->set_value(rDuration.NanoSeconds); 1228 } 1229 1230 util::Duration DurationDialog_Impl::GetDuration() const 1231 { 1232 util::Duration aRet; 1233 aRet.Negative = m_xNegativeCB->get_active(); 1234 aRet.Years = m_xYearNF->get_value(); 1235 aRet.Months = m_xMonthNF->get_value(); 1236 aRet.Days = m_xDayNF->get_value(); 1237 aRet.Hours = m_xHourNF->get_value(); 1238 aRet.Minutes = m_xMinuteNF->get_value(); 1239 aRet.Seconds = m_xSecondNF->get_value(); 1240 aRet.NanoSeconds = m_xMSecondNF->get_value(); 1241 return aRet; 1242 } 1243 1244 CustomPropertiesDurationField::CustomPropertiesDurationField(vcl::Window* pParent, WinBits nStyle, 1245 CustomPropertyLine* pLine) 1246 : Edit(pParent, nStyle) 1247 , m_pLine(pLine) 1248 1249 { 1250 SetDuration( util::Duration(false, 0, 0, 0, 0, 0, 0, 0) ); 1251 } 1252 1253 void CustomPropertiesDurationField::RequestHelp( const HelpEvent& rHEvt ) 1254 { 1255 if ( rHEvt.GetMode() & HelpEventMode::QUICK ) 1256 { 1257 Size aSize( GetSizePixel() ); 1258 tools::Rectangle aItemRect( rHEvt.GetMousePosPixel(), aSize ); 1259 if (Help::IsBalloonHelpEnabled()) 1260 Help::ShowBalloon( this, rHEvt.GetMousePosPixel(), aItemRect, GetText() ); 1261 else 1262 Help::ShowQuickHelp( this, aItemRect, GetText(), 1263 QuickHelpFlags::Left|QuickHelpFlags::VCenter ); 1264 } 1265 } 1266 1267 void CustomPropertiesDurationField::SetDuration( const util::Duration& rDuration ) 1268 { 1269 m_aDuration = rDuration; 1270 OUString sText(rDuration.Negative ? OUString('-') : OUString('+')); 1271 sText += m_pLine->m_sDurationFormat; 1272 sText = sText.replaceFirst( "%1", OUString::number( rDuration.Years ) ); 1273 sText = sText.replaceFirst( "%2", OUString::number( rDuration.Months ) ); 1274 sText = sText.replaceFirst( "%3", OUString::number( rDuration.Days ) ); 1275 sText = sText.replaceFirst( "%4", OUString::number( rDuration.Hours ) ); 1276 sText = sText.replaceFirst( "%5", OUString::number( rDuration.Minutes) ); 1277 sText = sText.replaceFirst( "%6", OUString::number( rDuration.Seconds) ); 1278 SetText( sText ); 1279 } 1280 1281 CustomPropertiesEditButton::CustomPropertiesEditButton(vcl::Window* pParent, WinBits nStyle, 1282 CustomPropertyLine* pLine) 1283 : PushButton(pParent, nStyle) 1284 , m_pLine(pLine) 1285 { 1286 SetClickHdl( LINK( this, CustomPropertiesEditButton, ClickHdl )); 1287 } 1288 1289 IMPL_LINK_NOARG(CustomPropertiesEditButton, ClickHdl, Button*, void) 1290 { 1291 DurationDialog_Impl aDurationDlg(GetFrameWeld(), m_pLine->m_aDurationField->GetDuration()); 1292 if (aDurationDlg.run() == RET_OK) 1293 m_pLine->m_aDurationField->SetDuration(aDurationDlg.GetDuration()); 1294 } 1295 1296 void CustomPropertiesYesNoButton::Resize() 1297 { 1298 Size aParentSize(GetSizePixel()); 1299 const long nWidth = aParentSize.Width(); 1300 const long n1Width = LogicToPixel(Size(1, 1), MapMode(MapUnit::MapAppFont)).Width(); 1301 const long n3Width = LogicToPixel(Size(3, 3), MapMode(MapUnit::MapAppFont)).Width(); 1302 const long nNewWidth = (nWidth / 2) - n3Width - 2; 1303 Size aSize(nNewWidth, m_aYesButton->get_preferred_size().Height()); 1304 Point aPos(n1Width, (aParentSize.Height() - aSize.Height()) / 2); 1305 m_aYesButton->SetPosSizePixel(aPos, aSize); 1306 aPos.AdjustX(aSize.Width() + n3Width ); 1307 m_aNoButton->SetPosSizePixel(aPos, aSize); 1308 } 1309 1310 namespace 1311 { 1312 VclPtr<ComboBox> makeComboBox(vcl::Window *pParent) 1313 { 1314 VclPtr<ComboBox> aNameBox(VclPtr<ComboBox>::Create(pParent, WB_TABSTOP|WB_DROPDOWN|WB_AUTOHSCROLL)); 1315 for (size_t i = 0; i < SAL_N_ELEMENTS(SFX_CB_PROPERTY_STRINGARRAY); ++i) 1316 aNameBox->InsertEntry(SfxResId(SFX_CB_PROPERTY_STRINGARRAY[i])); 1317 aNameBox->EnableAutoSize(true); 1318 return aNameBox; 1319 } 1320 } 1321 1322 CustomPropertiesTypeBox::CustomPropertiesTypeBox(vcl::Window* pParent, CustomPropertyLine* pLine) 1323 : ListBox(pParent, WB_BORDER|WB_DROPDOWN) 1324 , m_pLine(pLine) 1325 { 1326 for (size_t i = 0; i < SAL_N_ELEMENTS(SFX_LB_PROPERTY_STRINGARRAY); ++i) 1327 { 1328 InsertEntry(SfxResId(SFX_LB_PROPERTY_STRINGARRAY[i].first)); 1329 SetEntryData(i, reinterpret_cast<void*>(SFX_LB_PROPERTY_STRINGARRAY[i].second)); 1330 } 1331 SelectEntryPos(0); 1332 EnableAutoSize(true); 1333 } 1334 1335 // struct CustomPropertyLine --------------------------------------------- 1336 CustomPropertyLine::CustomPropertyLine( vcl::Window* pParent ) : 1337 m_aLine ( VclPtr<VclGrid>::Create(pParent) ), 1338 m_aNameBox ( makeComboBox(m_aLine) ), 1339 m_aTypeBox ( VclPtr<CustomPropertiesTypeBox>::Create(m_aLine, this) ), 1340 m_aValueEdit ( VclPtr<CustomPropertiesEdit>::Create(m_aLine, WB_BORDER|WB_TABSTOP|WB_LEFT, this ) ), 1341 m_aDateField ( VclPtr<CustomPropertiesDateField>::Create(m_aLine, WB_BORDER|WB_TABSTOP|WB_SPIN|WB_LEFT ) ), 1342 m_aTimeField ( VclPtr<CustomPropertiesTimeField>::Create(m_aLine, WB_BORDER|WB_TABSTOP|WB_SPIN|WB_LEFT ) ), 1343 m_sDurationFormat( SfxResId( SFX_ST_DURATION_FORMAT ) ), 1344 m_aDurationField( VclPtr<CustomPropertiesDurationField>::Create(m_aLine, WB_BORDER|WB_TABSTOP|WB_READONLY, this ) ), 1345 m_aEditButton ( VclPtr<CustomPropertiesEditButton>::Create(m_aLine, WB_TABSTOP, this) ), 1346 m_aYesNoButton ( VclPtr<CustomPropertiesYesNoButton>::Create(m_aLine) ), 1347 m_aRemoveButton ( VclPtr<CustomPropertiesRemoveButton>::Create(m_aLine, 0, this) ), 1348 m_bTypeLostFocus( false ) 1349 { 1350 m_aLine->set_column_spacing(4); 1351 1352 m_aNameBox->set_grid_left_attach(0); 1353 m_aNameBox->set_grid_top_attach(0); 1354 m_aNameBox->set_margin_left(4); 1355 m_aNameBox->Show(); 1356 1357 m_aTypeBox->set_grid_left_attach(1); 1358 m_aTypeBox->set_grid_top_attach(0); 1359 m_aTypeBox->Show(); 1360 1361 m_aValueEdit->set_grid_left_attach(2); 1362 m_aValueEdit->set_grid_top_attach(0); 1363 m_aValueEdit->set_hexpand(true); 1364 m_aValueEdit->Show(); 1365 1366 m_aDateField->set_grid_left_attach(3); 1367 m_aDateField->set_grid_top_attach(0); 1368 m_aDateField->set_hexpand(true); 1369 m_aDateField->Show(); 1370 1371 m_aTimeField->set_grid_left_attach(4); 1372 m_aTimeField->set_grid_top_attach(0); 1373 m_aTimeField->set_hexpand(true); 1374 m_aTimeField->Show(); 1375 1376 m_aDurationField->set_grid_left_attach(5); 1377 m_aDurationField->set_grid_top_attach(0); 1378 m_aDurationField->set_hexpand(true); 1379 m_aDurationField->Show(); 1380 1381 m_aEditButton->set_grid_left_attach(6); 1382 m_aEditButton->set_grid_top_attach(0); 1383 m_aEditButton->Show(); 1384 1385 m_aYesNoButton->set_grid_left_attach(7); 1386 m_aYesNoButton->set_grid_top_attach(0); 1387 m_aYesNoButton->set_hexpand(true); 1388 m_aYesNoButton->Show(); 1389 1390 m_aRemoveButton->set_grid_left_attach(8); 1391 m_aRemoveButton->set_grid_top_attach(0); 1392 m_aRemoveButton->set_margin_right(4); 1393 m_aRemoveButton->Show(); 1394 1395 m_aTimeField->SetExtFormat( ExtTimeFieldFormat::Long24H ); 1396 m_aDateField->SetExtDateFormat( ExtDateFieldFormat::SystemShortYYYY ); 1397 1398 m_aRemoveButton->SetModeImage(Image(StockImage::Yes, SFX_BMP_PROPERTY_REMOVE)); 1399 m_aRemoveButton->SetQuickHelpText(SfxResId(STR_SFX_REMOVE_PROPERTY)); 1400 1401 m_aEditButton->SetText(SFX_ST_EDIT); 1402 } 1403 1404 void CustomPropertyLine::Clear() 1405 { 1406 m_aNameBox->SetNoSelection(); 1407 m_aValueEdit->SetText(OUString()); 1408 1409 } 1410 1411 void CustomPropertyLine::Hide() 1412 { 1413 m_aLine->Hide(); 1414 } 1415 1416 CustomPropertiesWindow::CustomPropertiesWindow(vcl::Window* pParent, 1417 FixedText *pHeaderAccName, 1418 FixedText *pHeaderAccType, 1419 FixedText *pHeaderAccValue) : 1420 Window(pParent, WB_HIDE | WB_TABSTOP | WB_DIALOGCONTROL), 1421 m_pHeaderAccName(pHeaderAccName), 1422 m_pHeaderAccType(pHeaderAccType), 1423 m_pHeaderAccValue(pHeaderAccValue), 1424 m_nScrollPos (0), 1425 m_pCurrentLine (nullptr), 1426 m_aNumberFormatter( ::comphelper::getProcessComponentContext(), 1427 Application::GetSettings().GetLanguageTag().getLanguageType() ) 1428 { 1429 m_nRemoveButtonWidth = ScopedVclPtrInstance<CustomPropertiesRemoveButton>(pParent, 0, nullptr)->get_preferred_size().Width(); 1430 Size aSize = ScopedVclPtrInstance<CustomPropertiesTypeBox>(pParent, nullptr)->CalcMinimumSize(); 1431 m_nTypeBoxWidth = aSize.Width(); 1432 m_nWidgetHeight = aSize.Height(); 1433 1434 Point aPos(LogicToPixel(Point(0, 2), MapMode(MapUnit::MapAppFont))); 1435 1436 m_aEditLoseFocusIdle.SetPriority( TaskPriority::LOWEST ); 1437 m_aEditLoseFocusIdle.SetInvokeHandler( LINK( this, CustomPropertiesWindow, EditTimeoutHdl ) ); 1438 m_aBoxLoseFocusIdle.SetPriority( TaskPriority::LOWEST ); 1439 m_aBoxLoseFocusIdle.SetInvokeHandler( LINK( this, CustomPropertiesWindow, BoxTimeoutHdl ) ); 1440 1441 m_nLineHeight = (aPos.Y() * 2) + m_nWidgetHeight; 1442 } 1443 1444 void CustomPropertiesWindow::Init(HeaderBar* pHeaderBar, ScrollBar* pScrollBar) 1445 { 1446 m_pHeaderBar = pHeaderBar; 1447 m_pScrollBar = pScrollBar; 1448 } 1449 1450 CustomPropertiesWindow::~CustomPropertiesWindow() 1451 { 1452 disposeOnce(); 1453 } 1454 1455 void CustomPropertiesWindow::dispose() 1456 { 1457 m_aEditLoseFocusIdle.Stop(); 1458 m_aBoxLoseFocusIdle.Stop(); 1459 1460 m_aCustomPropertiesLines.clear(); 1461 m_pCurrentLine = nullptr; 1462 1463 m_pHeaderBar.clear(); 1464 m_pScrollBar.clear(); 1465 m_pHeaderAccName.clear(); 1466 m_pHeaderAccType.clear(); 1467 m_pHeaderAccValue.clear(); 1468 vcl::Window::dispose(); 1469 } 1470 1471 IMPL_LINK(CustomPropertiesWindow, TypeHdl, ListBox&, rListBox, void) 1472 { 1473 CustomPropertiesTypeBox* pBox = static_cast<CustomPropertiesTypeBox*>(&rListBox); 1474 long nType = reinterpret_cast<long>( pBox->GetSelectedEntryData() ); 1475 CustomPropertyLine* pLine = pBox->GetLine(); 1476 pLine->m_aValueEdit->Show( (CUSTOM_TYPE_TEXT == nType) || (CUSTOM_TYPE_NUMBER == nType) ); 1477 pLine->m_aDateField->Show( (CUSTOM_TYPE_DATE == nType) || (CUSTOM_TYPE_DATETIME == nType) ); 1478 pLine->m_aTimeField->Show( CUSTOM_TYPE_DATETIME == nType ); 1479 pLine->m_aDurationField->Show( CUSTOM_TYPE_DURATION == nType ); 1480 pLine->m_aEditButton->Show( CUSTOM_TYPE_DURATION == nType ); 1481 pLine->m_aYesNoButton->Show( CUSTOM_TYPE_BOOLEAN == nType ); 1482 1483 pLine->m_aLine->SetSizePixel(Size(GetSizePixel().Width(), m_nWidgetHeight)); 1484 } 1485 1486 IMPL_LINK( CustomPropertiesWindow, RemoveHdl, Button*, pBtn, void ) 1487 { 1488 StoreCustomProperties(); 1489 1490 CustomPropertiesRemoveButton* pButton = static_cast<CustomPropertiesRemoveButton*>(pBtn); 1491 CustomPropertyLine* pLine = pButton->GetLine(); 1492 auto pFound = std::find_if( m_aCustomPropertiesLines.begin(), m_aCustomPropertiesLines.end(), 1493 [&] (const std::unique_ptr<CustomPropertyLine>& p) { return p.get() == pLine; }); 1494 if ( pFound != m_aCustomPropertiesLines.end() ) 1495 { 1496 sal_uInt32 nLineNumber = pFound - m_aCustomPropertiesLines.begin(); 1497 sal_uInt32 nDataModelIndex = GetCurrentDataModelPosition() + nLineNumber; 1498 m_aCustomProperties.erase(m_aCustomProperties.begin() + nDataModelIndex); 1499 1500 ReloadLinesContent(); 1501 } 1502 1503 m_aRemovedHdl.Call(nullptr); 1504 } 1505 1506 IMPL_LINK( CustomPropertiesWindow, EditLoseFocusHdl, Control&, rControl, void ) 1507 { 1508 CustomPropertiesEdit* pEdit = static_cast<CustomPropertiesEdit*>(&rControl); 1509 CustomPropertyLine* pLine = pEdit->GetLine(); 1510 if ( !pLine->m_bTypeLostFocus ) 1511 { 1512 m_pCurrentLine = pLine; 1513 m_aEditLoseFocusIdle.Start(); 1514 } 1515 else 1516 pLine->m_bTypeLostFocus = false; 1517 } 1518 1519 IMPL_LINK( CustomPropertiesWindow, BoxLoseFocusHdl, Control&, rControl, void ) 1520 { 1521 m_pCurrentLine = static_cast<CustomPropertiesTypeBox*>(&rControl)->GetLine(); 1522 m_aBoxLoseFocusIdle.Start(); 1523 } 1524 1525 IMPL_LINK_NOARG(CustomPropertiesWindow, EditTimeoutHdl, Timer *, void) 1526 { 1527 ValidateLine( m_pCurrentLine, false ); 1528 } 1529 1530 IMPL_LINK_NOARG(CustomPropertiesWindow, BoxTimeoutHdl, Timer *, void) 1531 { 1532 ValidateLine( m_pCurrentLine, true ); 1533 } 1534 1535 bool CustomPropertiesWindow::IsLineValid( CustomPropertyLine* pLine ) const 1536 { 1537 bool bIsValid = true; 1538 pLine->m_bTypeLostFocus = false; 1539 long nType = reinterpret_cast<long>( 1540 pLine->m_aTypeBox->GetSelectedEntryData() ); 1541 OUString sValue = pLine->m_aValueEdit->GetText(); 1542 if ( sValue.isEmpty() ) 1543 return true; 1544 1545 sal_uInt32 nIndex = 0xFFFFFFFF; 1546 if ( CUSTOM_TYPE_NUMBER == nType ) 1547 nIndex = const_cast< SvNumberFormatter& >( 1548 m_aNumberFormatter ).GetFormatIndex( NF_NUMBER_SYSTEM ); 1549 else if ( CUSTOM_TYPE_DATE == nType ) 1550 nIndex = const_cast< SvNumberFormatter& >( 1551 m_aNumberFormatter).GetFormatIndex( NF_DATE_SYS_DDMMYYYY ); 1552 1553 if ( nIndex != 0xFFFFFFFF ) 1554 { 1555 sal_uInt32 nTemp = nIndex; 1556 double fDummy = 0.0; 1557 bIsValid = const_cast< SvNumberFormatter& >( 1558 m_aNumberFormatter ).IsNumberFormat( sValue, nIndex, fDummy ); 1559 if ( bIsValid && nTemp != nIndex ) 1560 // sValue is a number but the format doesn't match the index 1561 bIsValid = false; 1562 } 1563 1564 return bIsValid; 1565 } 1566 1567 void CustomPropertiesWindow::ValidateLine( CustomPropertyLine* pLine, bool bIsFromTypeBox ) 1568 { 1569 if (pLine && !IsLineValid(pLine)) 1570 { 1571 if ( bIsFromTypeBox ) // LoseFocus of TypeBox 1572 pLine->m_bTypeLostFocus = true; 1573 vcl::Window* pParent = GetParent()->GetParent(); 1574 std::unique_ptr<weld::MessageDialog> xMessageBox(Application::CreateMessageDialog(pParent ? pParent->GetFrameWeld() : nullptr, 1575 VclMessageType::Question, VclButtonsType::OkCancel, SfxResId(STR_SFX_QUERY_WRONG_TYPE))); 1576 if (xMessageBox->run() == RET_OK) 1577 pLine->m_aTypeBox->SelectEntryPos(pLine->m_aTypeBox->GetEntryPos(reinterpret_cast<void*>(CUSTOM_TYPE_TEXT))); 1578 else 1579 pLine->m_aValueEdit->GrabFocus(); 1580 } 1581 } 1582 1583 void CustomPropertiesWindow::SetWidgetWidths(const CustomPropertyLine* pLine) const 1584 { 1585 const long nOffset = 4; 1586 long nItemWidth = m_pHeaderBar->GetItemSize(HI_NAME); 1587 nItemWidth -= nOffset; 1588 1589 pLine->m_aNameBox->set_width_request(nItemWidth); 1590 pLine->m_aTypeBox->set_width_request(m_nTypeBoxWidth); 1591 pLine->m_aValueEdit->set_width_request(nItemWidth); 1592 1593 long nTimeWidth = nItemWidth; 1594 nTimeWidth /= 2; 1595 nTimeWidth -= 2; 1596 1597 pLine->m_aDateField->set_width_request(nTimeWidth); 1598 pLine->m_aTimeField->set_width_request(nTimeWidth); 1599 1600 pLine->m_aDurationField->set_width_request(nItemWidth - (pLine->m_aEditButton->get_preferred_size().Width() + nOffset)); 1601 pLine->m_aYesNoButton->set_width_request(nItemWidth); 1602 pLine->m_aRemoveButton->set_width_request(m_nRemoveButtonWidth); 1603 1604 pLine->m_aLine->SetSizePixel(Size(GetSizePixel().Width(), m_nWidgetHeight)); 1605 } 1606 1607 void CustomPropertiesWindow::Resize() 1608 { 1609 const long nOffset = 4; 1610 const long nScrollBarWidth = m_pScrollBar->GetSizePixel().Width(); 1611 long nButtonWidth = m_nRemoveButtonWidth + nScrollBarWidth + nOffset; 1612 long nTypeWidth = m_nTypeBoxWidth + (2 * nOffset); 1613 long nFullWidth = m_pHeaderBar->GetSizePixel().Width(); 1614 long nItemWidth = ( nFullWidth - nTypeWidth - nButtonWidth ) / 2; 1615 m_pHeaderBar->SetItemSize( HI_NAME, nItemWidth ); 1616 m_pHeaderBar->SetItemSize( HI_TYPE, nTypeWidth ); 1617 m_pHeaderBar->SetItemSize( HI_VALUE, nItemWidth ); 1618 m_pHeaderBar->SetItemSize( HI_ACTION, nButtonWidth ); 1619 1620 for (std::unique_ptr<CustomPropertyLine>& pLine : m_aCustomPropertiesLines) 1621 SetWidgetWidths(pLine.get()); 1622 1623 SetVisibleLineCount(GetVisibleLineCount()); 1624 ReloadLinesContent(); 1625 } 1626 1627 sal_uInt16 CustomPropertiesWindow::GetVisibleLineCount() const 1628 { 1629 sal_Int32 nScrollOffset = GetLineHeight(); 1630 sal_uInt16 nCount = ceil(static_cast<double>(GetSizePixel().Height()) / nScrollOffset); 1631 return nCount; 1632 } 1633 1634 void CustomPropertiesWindow::SetVisibleLineCount(sal_uInt32 nCount) 1635 { 1636 while (GetExistingLineCount() < nCount) 1637 { 1638 CreateNewLine(); 1639 } 1640 } 1641 1642 void CustomPropertiesWindow::AddLine(const OUString& sName, Any const & rAny) 1643 { 1644 m_aCustomProperties.push_back(std::unique_ptr<CustomProperty>(new CustomProperty(sName, rAny))); 1645 ReloadLinesContent(); 1646 } 1647 1648 void CustomPropertiesWindow::CreateNewLine() 1649 { 1650 CustomPropertyLine* pNewLine = new CustomPropertyLine( this ); 1651 pNewLine->m_aTypeBox->SetSelectHdl( LINK( this, CustomPropertiesWindow, TypeHdl ) ); 1652 pNewLine->m_aRemoveButton->SetClickHdl( LINK( this, CustomPropertiesWindow, RemoveHdl ) ); 1653 pNewLine->m_aValueEdit->SetLoseFocusHdl( LINK( this, CustomPropertiesWindow, EditLoseFocusHdl ) ); 1654 //add lose focus handlers of date/time fields 1655 1656 pNewLine->m_aTypeBox->SetLoseFocusHdl( LINK( this, CustomPropertiesWindow, BoxLoseFocusHdl ) ); 1657 1658 pNewLine->m_aNameBox->add_mnemonic_label(m_pHeaderAccName); 1659 pNewLine->m_aNameBox->SetAccessibleName(m_pHeaderAccName->GetText()); 1660 pNewLine->m_aTypeBox->add_mnemonic_label(m_pHeaderAccType); 1661 pNewLine->m_aTypeBox->SetAccessibleName(m_pHeaderAccType->GetText()); 1662 pNewLine->m_aValueEdit->add_mnemonic_label(m_pHeaderAccValue); 1663 pNewLine->m_aValueEdit->SetAccessibleName(m_pHeaderAccValue->GetText()); 1664 1665 sal_Int32 nPos = GetExistingLineCount() * GetLineHeight(); 1666 nPos += LogicToPixel(Size(0, 2), MapMode(MapUnit::MapAppFont)).Height(); 1667 m_aCustomPropertiesLines.emplace_back( pNewLine ); 1668 1669 SetWidgetWidths(pNewLine); 1670 pNewLine->m_aLine->SetPosSizePixel(Point(0, nPos + m_nScrollPos), Size(GetSizePixel().Width(), m_nWidgetHeight)); 1671 pNewLine->m_aLine->Show(); 1672 1673 TypeHdl(*pNewLine->m_aTypeBox.get()); 1674 pNewLine->m_aNameBox->GrabFocus(); 1675 } 1676 1677 bool CustomPropertiesWindow::AreAllLinesValid() const 1678 { 1679 bool bRet = true; 1680 for ( std::unique_ptr<CustomPropertyLine> const & pLine : m_aCustomPropertiesLines ) 1681 { 1682 if ( !IsLineValid( pLine.get() ) ) 1683 { 1684 bRet = false; 1685 break; 1686 } 1687 } 1688 1689 return bRet; 1690 } 1691 1692 void CustomPropertiesWindow::ClearAllLines() 1693 { 1694 for (auto& pLine : m_aCustomPropertiesLines) 1695 { 1696 pLine->Clear(); 1697 } 1698 m_pCurrentLine = nullptr; 1699 m_aCustomProperties.clear(); 1700 m_nScrollPos = 0; 1701 } 1702 1703 void CustomPropertiesWindow::DoScroll( sal_Int32 nNewPos ) 1704 { 1705 StoreCustomProperties(); 1706 1707 m_nScrollPos += nNewPos; 1708 ReloadLinesContent(); 1709 } 1710 1711 Sequence< beans::PropertyValue > CustomPropertiesWindow::GetCustomProperties() 1712 { 1713 StoreCustomProperties(); 1714 1715 Sequence< beans::PropertyValue > aPropertiesSeq(GetTotalLineCount()); 1716 1717 for (sal_uInt32 i = 0; i < GetTotalLineCount(); ++i) 1718 { 1719 aPropertiesSeq[i].Name = m_aCustomProperties[i]->m_sName; 1720 aPropertiesSeq[i].Value = m_aCustomProperties[i]->m_aValue; 1721 } 1722 1723 return aPropertiesSeq; 1724 } 1725 1726 void CustomPropertiesWindow::StoreCustomProperties() 1727 { 1728 sal_uInt32 nDataModelPos = GetCurrentDataModelPosition(); 1729 1730 for (sal_uInt32 i = 0; nDataModelPos + i < GetTotalLineCount() && i < GetExistingLineCount(); i++) 1731 { 1732 CustomPropertyLine* pLine = m_aCustomPropertiesLines[i].get(); 1733 1734 OUString sPropertyName = pLine->m_aNameBox->GetText(); 1735 if (!sPropertyName.isEmpty()) 1736 { 1737 m_aCustomProperties[nDataModelPos + i]->m_sName = sPropertyName; 1738 long nType = reinterpret_cast<long>( 1739 pLine->m_aTypeBox->GetSelectedEntryData()); 1740 if (CUSTOM_TYPE_NUMBER == nType) 1741 { 1742 double nValue = 0; 1743 sal_uInt32 nIndex = m_aNumberFormatter.GetFormatIndex(NF_NUMBER_SYSTEM); 1744 bool bIsNum = m_aNumberFormatter. 1745 IsNumberFormat(pLine->m_aValueEdit->GetText(), nIndex, nValue); 1746 if (bIsNum) 1747 m_aCustomProperties[nDataModelPos + i]->m_aValue <<= nValue; 1748 } 1749 else if (CUSTOM_TYPE_BOOLEAN == nType) 1750 { 1751 bool bValue = pLine->m_aYesNoButton->IsYesChecked(); 1752 m_aCustomProperties[nDataModelPos + i]->m_aValue <<= bValue; 1753 } 1754 else if (CUSTOM_TYPE_DATETIME == nType) 1755 { 1756 Date aTmpDate = pLine->m_aDateField->GetDate(); 1757 tools::Time aTmpTime = pLine->m_aTimeField->GetTime(); 1758 util::DateTime const aDateTime(aTmpTime.GetNanoSec(), 1759 aTmpTime.GetSec(), aTmpTime.GetMin(), aTmpTime.GetHour(), 1760 aTmpDate.GetDay(), aTmpDate.GetMonth(), aTmpDate.GetYear(), 1761 pLine->m_aTimeField->m_isUTC); 1762 if (pLine->m_aDateField->m_TZ.is_initialized()) 1763 { 1764 m_aCustomProperties[nDataModelPos + i]->m_aValue <<= util::DateTimeWithTimezone( 1765 aDateTime, pLine->m_aDateField->m_TZ.get()); 1766 } 1767 else 1768 { 1769 m_aCustomProperties[nDataModelPos + i]->m_aValue <<= aDateTime; 1770 } 1771 } 1772 else if (CUSTOM_TYPE_DATE == nType) 1773 { 1774 Date aTmpDate = pLine->m_aDateField->GetDate(); 1775 util::Date const aDate(aTmpDate.GetDay(), aTmpDate.GetMonth(), 1776 aTmpDate.GetYear()); 1777 if (pLine->m_aDateField->m_TZ.is_initialized()) 1778 { 1779 m_aCustomProperties[nDataModelPos + i]->m_aValue <<= util::DateWithTimezone( 1780 aDate, pLine->m_aDateField->m_TZ.get()); 1781 } 1782 else 1783 { 1784 m_aCustomProperties[nDataModelPos + i]->m_aValue <<= aDate; 1785 } 1786 } 1787 else if (CUSTOM_TYPE_DURATION == nType) 1788 { 1789 m_aCustomProperties[nDataModelPos + i]->m_aValue <<= pLine->m_aDurationField->GetDuration(); 1790 } 1791 else 1792 { 1793 OUString sValue(pLine->m_aValueEdit->GetText()); 1794 m_aCustomProperties[nDataModelPos + i]->m_aValue <<= sValue; 1795 } 1796 } 1797 } 1798 } 1799 1800 void CustomPropertiesWindow::SetCustomProperties(std::vector< std::unique_ptr<CustomProperty> >&& rProperties) 1801 { 1802 m_aCustomProperties = std::move(rProperties); 1803 ReloadLinesContent(); 1804 } 1805 1806 void CustomPropertiesWindow::ReloadLinesContent() 1807 { 1808 double nTmpValue = 0; 1809 bool bTmpValue = false; 1810 OUString sTmpValue; 1811 util::DateTime aTmpDateTime; 1812 util::Date aTmpDate; 1813 util::DateTimeWithTimezone aTmpDateTimeTZ; 1814 util::DateWithTimezone aTmpDateTZ; 1815 util::Duration aTmpDuration; 1816 SvtSysLocale aSysLocale; 1817 const LocaleDataWrapper& rLocaleWrapper = aSysLocale.GetLocaleData(); 1818 sal_IntPtr nType = CUSTOM_TYPE_UNKNOWN; 1819 OUString sValue; 1820 1821 sal_uInt32 nDataModelPos = GetCurrentDataModelPosition(); 1822 sal_uInt32 i = 0; 1823 1824 for (; nDataModelPos + i < GetTotalLineCount() && i < GetExistingLineCount(); i++) 1825 { 1826 const OUString& rName = m_aCustomProperties[nDataModelPos + i]->m_sName; 1827 const css::uno::Any& rAny = m_aCustomProperties[nDataModelPos + i]->m_aValue; 1828 1829 CustomPropertyLine* pLine = m_aCustomPropertiesLines[i].get(); 1830 pLine->Clear(); 1831 1832 pLine->m_aNameBox->SetText(rName); 1833 pLine->m_aLine->Show(); 1834 1835 if (!rAny.hasValue()) 1836 { 1837 pLine->m_aValueEdit->SetText(OUString()); 1838 } 1839 else if (rAny >>= nTmpValue) 1840 { 1841 sal_uInt32 nIndex = m_aNumberFormatter.GetFormatIndex(NF_NUMBER_SYSTEM); 1842 m_aNumberFormatter.GetInputLineString(nTmpValue, nIndex, sValue); 1843 pLine->m_aValueEdit->SetText(sValue); 1844 nType = CUSTOM_TYPE_NUMBER; 1845 } 1846 else if (rAny >>= bTmpValue) 1847 { 1848 sValue = (bTmpValue ? rLocaleWrapper.getTrueWord() : rLocaleWrapper.getFalseWord()); 1849 nType = CUSTOM_TYPE_BOOLEAN; 1850 } 1851 else if (rAny >>= sTmpValue) 1852 { 1853 pLine->m_aValueEdit->SetText(sTmpValue); 1854 nType = CUSTOM_TYPE_TEXT; 1855 } 1856 else if (rAny >>= aTmpDate) 1857 { 1858 pLine->m_aDateField->SetDate(Date(aTmpDate)); 1859 nType = CUSTOM_TYPE_DATE; 1860 } 1861 else if (rAny >>= aTmpDateTime) 1862 { 1863 pLine->m_aDateField->SetDate(Date(aTmpDateTime)); 1864 pLine->m_aTimeField->SetTime(tools::Time(aTmpDateTime)); 1865 pLine->m_aTimeField->m_isUTC = aTmpDateTime.IsUTC; 1866 nType = CUSTOM_TYPE_DATETIME; 1867 } 1868 else if (rAny >>= aTmpDateTZ) 1869 { 1870 pLine->m_aDateField->SetDate(Date(aTmpDateTZ.DateInTZ.Day, 1871 aTmpDateTZ.DateInTZ.Month, aTmpDateTZ.DateInTZ.Year)); 1872 pLine->m_aDateField->m_TZ = aTmpDateTZ.Timezone; 1873 nType = CUSTOM_TYPE_DATE; 1874 } 1875 else if (rAny >>= aTmpDateTimeTZ) 1876 { 1877 util::DateTime const& rDT(aTmpDateTimeTZ.DateTimeInTZ); 1878 pLine->m_aDateField->SetDate(Date(rDT)); 1879 pLine->m_aTimeField->SetTime(tools::Time(rDT)); 1880 pLine->m_aTimeField->m_isUTC = rDT.IsUTC; 1881 pLine->m_aDateField->m_TZ = aTmpDateTimeTZ.Timezone; 1882 nType = CUSTOM_TYPE_DATETIME; 1883 } 1884 else if (rAny >>= aTmpDuration) 1885 { 1886 nType = CUSTOM_TYPE_DURATION; 1887 pLine->m_aDurationField->SetDuration(aTmpDuration); 1888 } 1889 1890 if (nType != CUSTOM_TYPE_UNKNOWN) 1891 { 1892 if (CUSTOM_TYPE_BOOLEAN == nType) 1893 { 1894 if (bTmpValue) 1895 pLine->m_aYesNoButton->CheckYes(); 1896 else 1897 pLine->m_aYesNoButton->CheckNo(); 1898 } 1899 pLine->m_aTypeBox->SelectEntryPos(pLine->m_aTypeBox->GetEntryPos(reinterpret_cast<void*>(nType))); 1900 } 1901 1902 TypeHdl(*pLine->m_aTypeBox.get()); 1903 } 1904 while (nDataModelPos + i >= GetTotalLineCount() && i < GetExistingLineCount()) 1905 { 1906 CustomPropertyLine* pLine = m_aCustomPropertiesLines[i].get(); 1907 pLine->Hide(); 1908 i++; 1909 } 1910 } 1911 1912 CustomPropertiesControl::CustomPropertiesControl(vcl::Window* pParent) 1913 : Window(pParent, WB_HIDE | WB_CLIPCHILDREN | WB_TABSTOP | WB_DIALOGCONTROL | WB_BORDER) 1914 , m_pVBox(nullptr) 1915 , m_pHeaderBar(nullptr) 1916 , m_pBody(nullptr) 1917 , m_pPropertiesWin(nullptr) 1918 , m_pVertScroll(nullptr) 1919 , m_nThumbPos(0) 1920 { 1921 Size aRequest(LogicToPixel(Size(320, 141), MapMode(MapUnit::MapAppFont))); 1922 set_width_request(aRequest.Width()); 1923 } 1924 1925 void CustomPropertiesControl::Init(VclBuilderContainer& rBuilder) 1926 { 1927 m_pVBox = VclPtr<VclVBox>::Create(this); 1928 m_pHeaderBar = VclPtr<HeaderBar>::Create(m_pVBox, WB_BUTTONSTYLE | WB_BOTTOMBORDER); 1929 m_pBody = VclPtr<VclHBox>::Create(m_pVBox); 1930 FixedText* pName = rBuilder.get<FixedText>("name"); 1931 FixedText* pType = rBuilder.get<FixedText>("type"); 1932 FixedText* pValue = rBuilder.get<FixedText>("value"); 1933 OUString sName = pName->GetText(); 1934 OUString sType = pType->GetText(); 1935 OUString sValue = pValue->GetText(); 1936 m_pPropertiesWin = VclPtr<CustomPropertiesWindow>::Create(m_pBody, pName, pType, pValue); 1937 m_pVertScroll = VclPtr<ScrollBar>::Create(m_pBody, WB_VERT); 1938 m_pPropertiesWin->Init(m_pHeaderBar, m_pVertScroll); 1939 1940 set_hexpand(true); 1941 set_vexpand(true); 1942 set_expand(true); 1943 set_fill(true); 1944 1945 m_pVBox->set_hexpand(true); 1946 m_pVBox->set_vexpand(true); 1947 m_pVBox->set_expand(true); 1948 m_pVBox->set_fill(true); 1949 m_pVBox->Show(); 1950 1951 m_pBody->set_hexpand(true); 1952 m_pBody->set_vexpand(true); 1953 m_pBody->set_expand(true); 1954 m_pBody->set_fill(true); 1955 m_pBody->Show(); 1956 1957 m_pPropertiesWin->set_hexpand(true); 1958 m_pPropertiesWin->set_vexpand(true); 1959 m_pPropertiesWin->set_expand(true); 1960 m_pPropertiesWin->set_fill(true); 1961 m_pPropertiesWin->Show(); 1962 1963 m_pPropertiesWin->SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetFieldColor() ) ); 1964 m_pVertScroll->EnableDrag(); 1965 m_pVertScroll->Show(); 1966 1967 m_pHeaderBar->set_height_request(GetTextHeight() + 6); 1968 1969 const HeaderBarItemBits nHeadBits = HeaderBarItemBits::FIXED | HeaderBarItemBits::FIXEDPOS | HeaderBarItemBits::LEFT; 1970 1971 m_pHeaderBar->InsertItem( HI_NAME, sName, 0, nHeadBits ); 1972 m_pHeaderBar->InsertItem( HI_TYPE, sType, 0, nHeadBits ); 1973 m_pHeaderBar->InsertItem( HI_VALUE, sValue, 0, nHeadBits ); 1974 m_pHeaderBar->InsertItem( HI_ACTION, OUString(), 0, nHeadBits ); 1975 m_pHeaderBar->Show(); 1976 1977 m_pPropertiesWin->SetRemovedHdl( LINK( this, CustomPropertiesControl, RemovedHdl ) ); 1978 1979 m_pVertScroll->SetRangeMin( 0 ); 1980 m_pVertScroll->SetRangeMax( 0 ); 1981 m_pVertScroll->SetVisibleSize( 0xFFFF ); 1982 1983 Link<ScrollBar*,void> aScrollLink = LINK( this, CustomPropertiesControl, ScrollHdl ); 1984 m_pVertScroll->SetScrollHdl( aScrollLink ); 1985 } 1986 1987 void CustomPropertiesControl::Resize() 1988 { 1989 if (m_pVBox) 1990 { 1991 m_pVBox->SetSizePixel(GetSizePixel()); 1992 sal_Int32 nScrollOffset = m_pPropertiesWin->GetLineHeight(); 1993 sal_Int32 nVisibleEntries = m_pPropertiesWin->GetSizePixel().Height() / nScrollOffset; 1994 m_pPropertiesWin->SetVisibleLineCount( nVisibleEntries ); 1995 m_pVertScroll->SetPageSize( nVisibleEntries - 1 ); 1996 m_pVertScroll->SetVisibleSize( nVisibleEntries ); 1997 } 1998 Window::Resize(); 1999 } 2000 2001 VCL_BUILDER_FACTORY(CustomPropertiesControl) 2002 2003 CustomPropertiesControl::~CustomPropertiesControl() 2004 { 2005 disposeOnce(); 2006 } 2007 2008 void CustomPropertiesControl::dispose() 2009 { 2010 m_pVertScroll.disposeAndClear(); 2011 m_pPropertiesWin.disposeAndClear(); 2012 m_pBody.disposeAndClear(); 2013 m_pHeaderBar.disposeAndClear(); 2014 m_pVBox.disposeAndClear(); 2015 vcl::Window::dispose(); 2016 } 2017 2018 IMPL_LINK( CustomPropertiesControl, ScrollHdl, ScrollBar*, pScrollBar, void ) 2019 { 2020 sal_Int32 nOffset = m_pPropertiesWin->GetLineHeight(); 2021 nOffset *= ( m_nThumbPos - pScrollBar->GetThumbPos() ); 2022 m_nThumbPos = pScrollBar->GetThumbPos(); 2023 m_pPropertiesWin->DoScroll( nOffset ); 2024 } 2025 2026 IMPL_LINK_NOARG(CustomPropertiesControl, RemovedHdl, void*, void) 2027 { 2028 long nLineCount = m_pPropertiesWin->GetTotalLineCount(); 2029 m_pVertScroll->SetRangeMax(nLineCount + 1); 2030 if ( m_pPropertiesWin->GetTotalLineCount() > m_pPropertiesWin->GetExistingLineCount() ) 2031 m_pVertScroll->DoScrollAction ( ScrollType::LineUp ); 2032 } 2033 2034 void CustomPropertiesControl::AddLine( Any const & rAny ) 2035 { 2036 m_pPropertiesWin->AddLine( OUString(), rAny ); 2037 long nLineCount = m_pPropertiesWin->GetTotalLineCount(); 2038 m_pVertScroll->SetRangeMax(nLineCount + 1); 2039 if ( m_pPropertiesWin->GetOutputSizePixel().Height() < nLineCount * m_pPropertiesWin->GetLineHeight() ) 2040 m_pVertScroll->DoScroll(nLineCount + 1); 2041 } 2042 2043 void CustomPropertiesControl::SetCustomProperties(std::vector< std::unique_ptr<CustomProperty> >&& rProperties) 2044 { 2045 m_pPropertiesWin->SetCustomProperties(std::move(rProperties)); 2046 long nLineCount = m_pPropertiesWin->GetTotalLineCount(); 2047 m_pVertScroll->SetRangeMax(nLineCount + 1); 2048 } 2049 2050 // class SfxCustomPropertiesPage ----------------------------------------- 2051 SfxCustomPropertiesPage::SfxCustomPropertiesPage( vcl::Window* pParent, const SfxItemSet& rItemSet ) 2052 : SfxTabPage(pParent, "CustomInfoPage", "sfx/ui/custominfopage.ui", &rItemSet) 2053 { 2054 get(m_pPropertiesCtrl, "properties"); 2055 m_pPropertiesCtrl->Init(*this); 2056 get<PushButton>("add")->SetClickHdl(LINK(this, SfxCustomPropertiesPage, AddHdl)); 2057 } 2058 2059 SfxCustomPropertiesPage::~SfxCustomPropertiesPage() 2060 { 2061 disposeOnce(); 2062 } 2063 2064 void SfxCustomPropertiesPage::dispose() 2065 { 2066 m_pPropertiesCtrl.clear(); 2067 SfxTabPage::dispose(); 2068 } 2069 2070 IMPL_LINK_NOARG(SfxCustomPropertiesPage, AddHdl, Button*, void) 2071 { 2072 // tdf#115853: reload current lines before adding a brand new one 2073 // indeed the info are deleted by ClearCustomProperties 2074 // each time SfxDocumentInfoItem destructor is called 2075 SfxDocumentInfoItem pInfo; 2076 Sequence< beans::PropertyValue > aPropertySeq = m_pPropertiesCtrl->GetCustomProperties(); 2077 sal_Int32 i = 0, nCount = aPropertySeq.getLength(); 2078 for ( ; i < nCount; ++i ) 2079 { 2080 if ( !aPropertySeq[i].Name.isEmpty() ) 2081 { 2082 pInfo.AddCustomProperty( aPropertySeq[i].Name, aPropertySeq[i].Value ); 2083 } 2084 } 2085 2086 Any aAny; 2087 m_pPropertiesCtrl->AddLine(aAny); 2088 } 2089 2090 bool SfxCustomPropertiesPage::FillItemSet( SfxItemSet* rSet ) 2091 { 2092 const SfxPoolItem* pItem = nullptr; 2093 SfxDocumentInfoItem* pInfo = nullptr; 2094 bool bMustDelete = false; 2095 2096 if (const SfxItemSet* pItemSet = GetDialogExampleSet()) 2097 { 2098 if (SfxItemState::SET != pItemSet->GetItemState(SID_DOCINFO, true, &pItem)) 2099 pInfo = const_cast<SfxDocumentInfoItem*>(&rSet->Get( SID_DOCINFO )); 2100 else 2101 { 2102 bMustDelete = true; 2103 pInfo = new SfxDocumentInfoItem( *static_cast<const SfxDocumentInfoItem*>(pItem) ); 2104 } 2105 } 2106 2107 if ( pInfo ) 2108 { 2109 // If it's a CMIS document, we can't save custom properties 2110 if ( pInfo->isCmisDocument( ) ) 2111 { 2112 if ( bMustDelete ) 2113 delete pInfo; 2114 return false; 2115 } 2116 2117 pInfo->ClearCustomProperties(); 2118 Sequence< beans::PropertyValue > aPropertySeq = m_pPropertiesCtrl->GetCustomProperties(); 2119 sal_Int32 i = 0, nCount = aPropertySeq.getLength(); 2120 for ( ; i < nCount; ++i ) 2121 { 2122 if ( !aPropertySeq[i].Name.isEmpty() ) 2123 pInfo->AddCustomProperty( aPropertySeq[i].Name, aPropertySeq[i].Value ); 2124 } 2125 } 2126 2127 if (pInfo) 2128 { 2129 rSet->Put(*pInfo); 2130 if ( bMustDelete ) 2131 delete pInfo; 2132 } 2133 return true; 2134 } 2135 2136 void SfxCustomPropertiesPage::Reset( const SfxItemSet* rItemSet ) 2137 { 2138 m_pPropertiesCtrl->ClearAllLines(); 2139 const SfxDocumentInfoItem& rInfoItem = rItemSet->Get(SID_DOCINFO); 2140 std::vector< std::unique_ptr<CustomProperty> > aCustomProps = rInfoItem.GetCustomProperties(); 2141 m_pPropertiesCtrl->SetCustomProperties(std::move(aCustomProps)); 2142 } 2143 2144 DeactivateRC SfxCustomPropertiesPage::DeactivatePage( SfxItemSet* /*pSet*/ ) 2145 { 2146 DeactivateRC nRet = DeactivateRC::LeavePage; 2147 if ( !m_pPropertiesCtrl->AreAllLinesValid() ) 2148 nRet = DeactivateRC::KeepPage; 2149 return nRet; 2150 } 2151 2152 VclPtr<SfxTabPage> SfxCustomPropertiesPage::Create( TabPageParent pParent, const SfxItemSet* rItemSet ) 2153 { 2154 return VclPtr<SfxCustomPropertiesPage>::Create( pParent.pParent, *rItemSet ); 2155 } 2156 2157 CmisValue::CmisValue( vcl::Window* pParent, const OUString& aStr ) 2158 { 2159 m_pUIBuilder.reset(new VclBuilder( pParent, getUIRootDir(), "sfx/ui/cmisline.ui")); 2160 get( m_aValueEdit, "value"); 2161 m_aValueEdit->Show(); 2162 m_aValueEdit->SetText( aStr ); 2163 } 2164 2165 CmisDateTime::CmisDateTime( vcl::Window* pParent, const util::DateTime& aDateTime ) 2166 { 2167 m_pUIBuilder.reset(new VclBuilder( pParent, getUIRootDir(), "sfx/ui/cmisline.ui")); 2168 get( m_aDateField, "date"); 2169 get( m_aTimeField, "time"); 2170 m_aDateField->Show(); 2171 m_aTimeField->Show(); 2172 m_aDateField->SetDate( Date( aDateTime ) ); 2173 m_aTimeField->SetTime( tools::Time( aDateTime ) ); 2174 } 2175 2176 CmisYesNo::CmisYesNo( vcl::Window* pParent, bool bValue ) 2177 { 2178 m_pUIBuilder.reset(new VclBuilder( pParent, getUIRootDir(), "sfx/ui/cmisline.ui")); 2179 get( m_aYesButton, "yes"); 2180 get( m_aNoButton, "no"); 2181 m_aYesButton->Show(); 2182 m_aNoButton->Show(); 2183 if ( bValue ) 2184 m_aYesButton->Check( ); 2185 else 2186 m_aNoButton->Check( ); 2187 } 2188 2189 // struct CmisPropertyLine --------------------------------------------- 2190 CmisPropertyLine::CmisPropertyLine(vcl::Window* pParent) 2191 : m_sType(CMIS_TYPE_STRING) 2192 , m_bUpdatable(false) 2193 , m_bRequired(false) 2194 , m_bMultiValued(false) 2195 , m_bOpenChoice(false) 2196 { 2197 m_pUIBuilder.reset(new VclBuilder( pParent, getUIRootDir(), "sfx/ui/cmisline.ui")); 2198 get( m_pFrame, "CmisFrame" ); 2199 get( m_aName, "name" ); 2200 get( m_aType, "type" ); 2201 m_pFrame->Enable(); 2202 } 2203 2204 CmisPropertyLine::~CmisPropertyLine( ) 2205 { 2206 m_aValues.clear(); 2207 m_aYesNos.clear(); 2208 m_aDateTimes.clear(); 2209 } 2210 2211 long CmisPropertyLine::getItemHeight() const 2212 { 2213 return VclContainer::getLayoutRequisition(*m_pFrame).Height(); 2214 } 2215 2216 // class CmisPropertiesWindow ----------------------------------------- 2217 2218 CmisPropertiesWindow::CmisPropertiesWindow(SfxTabPage* pParent): 2219 m_aNumberFormatter( ::comphelper::getProcessComponentContext(), 2220 Application::GetSettings().GetLanguageTag().getLanguageType() ) 2221 { 2222 pParent->get(m_pBox, "CmisWindow"); 2223 CmisPropertyLine aTemp( m_pBox ); 2224 m_nItemHeight = aTemp.getItemHeight(); 2225 } 2226 2227 CmisPropertiesWindow::~CmisPropertiesWindow() 2228 { 2229 ClearAllLines(); 2230 } 2231 2232 void CmisPropertiesWindow::ClearAllLines() 2233 { 2234 m_aCmisPropertiesLines.clear(); 2235 } 2236 2237 void CmisPropertiesWindow::AddLine( const OUString& sId, const OUString& sName, 2238 const OUString& sType, const bool bUpdatable, 2239 const bool bRequired, const bool bMultiValued, 2240 const bool bOpenChoice, Any& /*aChoices*/, Any const & rAny ) 2241 { 2242 std::unique_ptr<CmisPropertyLine> pNewLine(new CmisPropertyLine( m_pBox )); 2243 2244 pNewLine->m_sId = sId; 2245 pNewLine->m_sType = sType; 2246 pNewLine->m_bUpdatable = bUpdatable; 2247 pNewLine->m_bRequired = bRequired; 2248 pNewLine->m_bMultiValued = bMultiValued; 2249 pNewLine->m_bOpenChoice = bOpenChoice; 2250 2251 if ( sType == CMIS_TYPE_INTEGER ) 2252 { 2253 Sequence< sal_Int64 > seqValue; 2254 rAny >>= seqValue; 2255 sal_uInt32 nIndex = m_aNumberFormatter.GetFormatIndex( NF_NUMBER_SYSTEM ); 2256 sal_Int32 nNumValue = seqValue.getLength( ); 2257 for ( sal_Int32 i = 0; i < nNumValue; ++i ) 2258 { 2259 OUString sValue; 2260 m_aNumberFormatter.GetInputLineString( seqValue[i], nIndex, sValue ); 2261 std::unique_ptr<CmisValue> pValue(new CmisValue( m_pBox, sValue )); 2262 pValue->m_aValueEdit->SetReadOnly( !bUpdatable ); 2263 pNewLine->m_aValues.push_back( std::move(pValue) ); 2264 } 2265 } 2266 else if ( sType == CMIS_TYPE_DECIMAL ) 2267 { 2268 Sequence< double > seqValue; 2269 rAny >>= seqValue; 2270 sal_uInt32 nIndex = m_aNumberFormatter.GetFormatIndex( NF_NUMBER_SYSTEM ); 2271 sal_Int32 nNumValue = seqValue.getLength( ); 2272 for ( sal_Int32 i = 0; i < nNumValue; ++i ) 2273 { 2274 OUString sValue; 2275 m_aNumberFormatter.GetInputLineString( seqValue[i], nIndex, sValue ); 2276 std::unique_ptr<CmisValue> pValue(new CmisValue( m_pBox, sValue )); 2277 pValue->m_aValueEdit->SetReadOnly( !bUpdatable ); 2278 pNewLine->m_aValues.push_back( std::move(pValue) ); 2279 } 2280 2281 } 2282 else if ( sType == CMIS_TYPE_BOOL ) 2283 { 2284 Sequence<sal_Bool> seqValue; 2285 rAny >>= seqValue; 2286 sal_Int32 nNumValue = seqValue.getLength( ); 2287 for ( sal_Int32 i = 0; i < nNumValue; ++i ) 2288 { 2289 std::unique_ptr<CmisYesNo> pYesNo(new CmisYesNo( m_pBox, seqValue[i] )); 2290 pYesNo->m_aYesButton->Enable( bUpdatable ); 2291 pYesNo->m_aNoButton->Enable( bUpdatable ); 2292 pNewLine->m_aYesNos.push_back( std::move(pYesNo) ); 2293 } 2294 } 2295 else if ( sType == CMIS_TYPE_STRING ) 2296 { 2297 Sequence< OUString > seqValue; 2298 rAny >>= seqValue; 2299 sal_Int32 nNumValue = seqValue.getLength( ); 2300 for ( sal_Int32 i = 0; i < nNumValue; ++i ) 2301 { 2302 std::unique_ptr<CmisValue> pValue(new CmisValue( m_pBox, seqValue[i] )); 2303 pValue->m_aValueEdit->SetReadOnly( !bUpdatable ); 2304 pNewLine->m_aValues.push_back( std::move(pValue) ); 2305 } 2306 } 2307 else if ( sType == CMIS_TYPE_DATETIME ) 2308 { 2309 Sequence< util::DateTime > seqValue; 2310 rAny >>= seqValue; 2311 sal_Int32 nNumValue = seqValue.getLength( ); 2312 for ( sal_Int32 i = 0; i < nNumValue; ++i ) 2313 { 2314 std::unique_ptr<CmisDateTime> pDateTime(new CmisDateTime( m_pBox, seqValue[i])); 2315 pDateTime->m_aDateField->SetReadOnly( !bUpdatable ); 2316 pDateTime->m_aTimeField->SetReadOnly( !bUpdatable ); 2317 pNewLine->m_aDateTimes.push_back( std::move(pDateTime) ); 2318 } 2319 } 2320 pNewLine->m_aName->SetText( sName ); 2321 pNewLine->m_aName->Show(); 2322 pNewLine->m_aType->SetText( sType ); 2323 pNewLine->m_aType->Show(); 2324 2325 m_aCmisPropertiesLines.push_back( std::move(pNewLine) ); 2326 } 2327 2328 void CmisPropertiesWindow::DoScroll( sal_Int32 nNewPos ) 2329 { 2330 m_pBox->SetPosPixel(Point(0, nNewPos)); 2331 } 2332 2333 Sequence< document::CmisProperty > CmisPropertiesWindow::GetCmisProperties() const 2334 { 2335 Sequence< document::CmisProperty > aPropertiesSeq( m_aCmisPropertiesLines.size() ); 2336 sal_Int32 i = 0; 2337 for ( auto& rxLine : m_aCmisPropertiesLines ) 2338 { 2339 CmisPropertyLine* pLine = rxLine.get(); 2340 2341 aPropertiesSeq[i].Id = pLine->m_sId; 2342 aPropertiesSeq[i].Type = pLine->m_sType; 2343 aPropertiesSeq[i].Updatable = pLine->m_bUpdatable; 2344 aPropertiesSeq[i].Required = pLine->m_bRequired; 2345 aPropertiesSeq[i].OpenChoice = pLine->m_bOpenChoice; 2346 aPropertiesSeq[i].MultiValued = pLine->m_bMultiValued; 2347 2348 OUString sPropertyName = pLine->m_aName->GetText(); 2349 if ( !sPropertyName.isEmpty() ) 2350 { 2351 aPropertiesSeq[i].Name = sPropertyName; 2352 OUString sType = pLine->m_aType->GetText( ); 2353 if ( CMIS_TYPE_DECIMAL == sType ) 2354 { 2355 sal_uInt32 nIndex = const_cast< SvNumberFormatter& >( 2356 m_aNumberFormatter ).GetFormatIndex( NF_NUMBER_SYSTEM ); 2357 Sequence< double > seqValue( pLine->m_aValues.size( ) ); 2358 sal_Int32 k = 0; 2359 for ( auto& rxValue : pLine->m_aValues ) 2360 { 2361 double dValue = 0.0; 2362 OUString sValue( rxValue->m_aValueEdit->GetText() ); 2363 bool bIsNum = const_cast< SvNumberFormatter& >( m_aNumberFormatter ). 2364 IsNumberFormat( sValue, nIndex, dValue ); 2365 if ( bIsNum ) 2366 seqValue[k] = dValue; 2367 ++k; 2368 } 2369 aPropertiesSeq[i].Value <<= seqValue; 2370 } 2371 else if ( CMIS_TYPE_INTEGER == sType ) 2372 { 2373 sal_uInt32 nIndex = const_cast< SvNumberFormatter& >( 2374 m_aNumberFormatter ).GetFormatIndex( NF_NUMBER_SYSTEM ); 2375 Sequence< sal_Int64 > seqValue( pLine->m_aValues.size( ) ); 2376 sal_Int32 k = 0; 2377 for ( auto& rxValue : pLine->m_aValues ) 2378 { 2379 double dValue = 0; 2380 OUString sValue( rxValue->m_aValueEdit->GetText() ); 2381 bool bIsNum = const_cast< SvNumberFormatter& >( m_aNumberFormatter ). 2382 IsNumberFormat( sValue, nIndex, dValue ); 2383 if ( bIsNum ) 2384 seqValue[k] = static_cast<sal_Int64>(dValue); 2385 ++k; 2386 } 2387 aPropertiesSeq[i].Value <<= seqValue; 2388 } 2389 else if ( CMIS_TYPE_BOOL == sType ) 2390 { 2391 Sequence<sal_Bool> seqValue( pLine->m_aYesNos.size( ) ); 2392 sal_Int32 k = 0; 2393 for ( auto& rxYesNo : pLine->m_aYesNos ) 2394 { 2395 bool bValue = rxYesNo->m_aYesButton->IsChecked(); 2396 seqValue[k] = bValue; 2397 ++k; 2398 } 2399 aPropertiesSeq[i].Value <<= seqValue; 2400 2401 } 2402 else if ( CMIS_TYPE_DATETIME == sType ) 2403 { 2404 Sequence< util::DateTime > seqValue( pLine->m_aDateTimes.size( ) ); 2405 sal_Int32 k = 0; 2406 for ( auto& rxDateTime : pLine->m_aDateTimes ) 2407 { 2408 Date aTmpDate = rxDateTime->m_aDateField->GetDate(); 2409 tools::Time aTmpTime = rxDateTime->m_aTimeField->GetTime(); 2410 util::DateTime aDateTime( aTmpTime.GetNanoSec(), aTmpTime.GetSec(), 2411 aTmpTime.GetMin(), aTmpTime.GetHour(), 2412 aTmpDate.GetDay(), aTmpDate.GetMonth(), 2413 aTmpDate.GetYear(), true ); 2414 seqValue[k] = aDateTime; 2415 ++k; 2416 } 2417 aPropertiesSeq[i].Value <<= seqValue; 2418 } 2419 else 2420 { 2421 Sequence< OUString > seqValue( pLine->m_aValues.size( ) ); 2422 sal_Int32 k = 0; 2423 for ( auto& rxValue : pLine->m_aValues ) 2424 { 2425 OUString sValue( rxValue->m_aValueEdit->GetText() ); 2426 seqValue[k] = sValue; 2427 ++k; 2428 } 2429 aPropertiesSeq[i].Value <<= seqValue; 2430 } 2431 } 2432 ++i; 2433 } 2434 2435 return aPropertiesSeq; 2436 } 2437 2438 CmisPropertiesControl::CmisPropertiesControl(SfxTabPage* pParent) 2439 : m_pPropertiesWin( pParent ) 2440 , m_rScrolledWindow( *pParent->get<VclScrolledWindow>("CmisScroll")) 2441 , m_rVertScroll( m_rScrolledWindow.getVertScrollBar()) 2442 { 2443 m_rScrolledWindow.setUserManagedScrolling(true); 2444 m_rVertScroll.EnableDrag(); 2445 m_rVertScroll.Show( m_rScrolledWindow.GetStyle() & WB_VSCROLL); 2446 m_rVertScroll.SetRangeMin(0); 2447 m_rVertScroll.SetVisibleSize( 0xFFFF ); 2448 2449 Link<ScrollBar*,void> aScrollLink = LINK( this, CmisPropertiesControl, ScrollHdl ); 2450 m_rVertScroll.SetScrollHdl( aScrollLink ); 2451 } 2452 2453 void CmisPropertiesControl::ClearAllLines() 2454 { 2455 m_pPropertiesWin.ClearAllLines(); 2456 } 2457 2458 IMPL_LINK( CmisPropertiesControl, ScrollHdl, ScrollBar*, pScrollBar, void ) 2459 { 2460 sal_Int32 nOffset = m_pPropertiesWin.GetItemHeight(); 2461 nOffset *= ( pScrollBar->GetThumbPos() ); 2462 m_pPropertiesWin.DoScroll( -nOffset ); 2463 } 2464 2465 void CmisPropertiesControl::checkAutoVScroll() 2466 { 2467 WinBits nBits = m_rScrolledWindow.GetStyle(); 2468 if (nBits & WB_VSCROLL) 2469 return; 2470 if (nBits & WB_AUTOVSCROLL) 2471 { 2472 bool bShow = m_rVertScroll.GetRangeMax() > m_rVertScroll.GetVisibleSize(); 2473 if (bShow != m_rVertScroll.IsVisible()) 2474 m_rVertScroll.Show(bShow); 2475 } 2476 } 2477 2478 void CmisPropertiesControl::setScrollRange() 2479 { 2480 sal_Int32 nScrollOffset = m_pPropertiesWin.GetItemHeight(); 2481 sal_Int32 nVisibleItems = m_rScrolledWindow.getVisibleChildSize().Height() / nScrollOffset; 2482 m_rVertScroll.SetPageSize( nVisibleItems - 1 ); 2483 m_rVertScroll.SetVisibleSize( nVisibleItems ); 2484 m_rVertScroll.Scroll(); 2485 checkAutoVScroll(); 2486 } 2487 2488 void CmisPropertiesControl::AddLine( const OUString& sId, const OUString& sName, 2489 const OUString& sType, const bool bUpdatable, 2490 const bool bRequired, const bool bMultiValued, 2491 const bool bOpenChoice, Any& aChoices, Any const & rAny 2492 ) 2493 { 2494 m_pPropertiesWin.AddLine( sId, sName, sType, bUpdatable, bRequired, bMultiValued, 2495 bOpenChoice, aChoices, rAny ); 2496 //compute logical elements 2497 sal_Int32 nLogicElements = ( m_pPropertiesWin.getBoxHeight() 2498 + m_pPropertiesWin.GetItemHeight() ) / m_pPropertiesWin.GetItemHeight(); 2499 m_rVertScroll.SetRangeMax( nLogicElements ); 2500 m_rVertScroll.DoScroll( nLogicElements ); 2501 checkAutoVScroll(); 2502 } 2503 2504 // class SfxCmisPropertiesPage ----------------------------------------- 2505 SfxCmisPropertiesPage::SfxCmisPropertiesPage( vcl::Window* pParent, const SfxItemSet& rItemSet ) 2506 : SfxTabPage(pParent, "CmisInfoPage", "sfx/ui/cmisinfopage.ui", &rItemSet) 2507 , m_pPropertiesCtrl( this ) 2508 { 2509 } 2510 2511 SfxCmisPropertiesPage::~SfxCmisPropertiesPage() 2512 { 2513 disposeOnce(); 2514 } 2515 2516 void SfxCmisPropertiesPage::dispose() 2517 { 2518 m_pPropertiesCtrl.ClearAllLines(); 2519 SfxTabPage::dispose(); 2520 } 2521 2522 bool SfxCmisPropertiesPage::FillItemSet( SfxItemSet* rSet ) 2523 { 2524 const SfxPoolItem* pItem = nullptr; 2525 SfxDocumentInfoItem* pInfo = nullptr; 2526 bool bMustDelete = false; 2527 2528 if (const SfxItemSet* pItemSet = GetDialogExampleSet()) 2529 { 2530 if (SfxItemState::SET != pItemSet->GetItemState(SID_DOCINFO, true, &pItem)) 2531 pInfo = const_cast<SfxDocumentInfoItem*>(&rSet->Get( SID_DOCINFO )); 2532 else 2533 { 2534 bMustDelete = true; 2535 pInfo = new SfxDocumentInfoItem( *static_cast<const SfxDocumentInfoItem*>(pItem) ); 2536 } 2537 } 2538 2539 sal_Int32 modifiedNum = 0; 2540 if ( pInfo ) 2541 { 2542 Sequence< document::CmisProperty > aOldProps = pInfo->GetCmisProperties( ); 2543 Sequence< document::CmisProperty > aNewProps = m_pPropertiesCtrl.GetCmisProperties(); 2544 2545 std::vector< document::CmisProperty > changedProps; 2546 for ( sal_Int32 i = 0; i< aNewProps.getLength( ); ++i ) 2547 { 2548 if ( aOldProps[i].Updatable && !aNewProps[i].Id.isEmpty( ) ) 2549 { 2550 if ( aOldProps[i].Type == CMIS_TYPE_DATETIME ) 2551 { 2552 Sequence< util::DateTime > oldValue; 2553 aOldProps[i].Value >>= oldValue; 2554 // We only edit hours and minutes 2555 // don't compare NanoSeconds and Seconds 2556 for ( sal_Int32 ii = 0; ii < oldValue.getLength( ); ++ii ) 2557 { 2558 oldValue[ii].NanoSeconds = 0; 2559 oldValue[ii].Seconds = 0; 2560 } 2561 Sequence< util::DateTime > newValue; 2562 aNewProps[i].Value >>= newValue; 2563 if ( oldValue != newValue ) 2564 { 2565 modifiedNum++; 2566 changedProps.push_back( aNewProps[i] ); 2567 } 2568 } 2569 else if ( aOldProps[i].Value != aNewProps[i].Value ) 2570 { 2571 modifiedNum++; 2572 changedProps.push_back( aNewProps[i] ); 2573 } 2574 } 2575 } 2576 Sequence< document::CmisProperty> aModifiedProps( comphelper::containerToSequence(changedProps) ); 2577 pInfo->SetCmisProperties( aModifiedProps ); 2578 rSet->Put( *pInfo ); 2579 if ( bMustDelete ) 2580 delete pInfo; 2581 } 2582 2583 return modifiedNum; 2584 } 2585 2586 void SfxCmisPropertiesPage::Reset( const SfxItemSet* rItemSet ) 2587 { 2588 m_pPropertiesCtrl.ClearAllLines(); 2589 const SfxDocumentInfoItem& rInfoItem = rItemSet->Get(SID_DOCINFO); 2590 uno::Sequence< document::CmisProperty > aCmisProps = rInfoItem.GetCmisProperties(); 2591 for ( sal_Int32 i = 0; i < aCmisProps.getLength(); i++ ) 2592 { 2593 m_pPropertiesCtrl.AddLine( aCmisProps[i].Id, 2594 aCmisProps[i].Name, 2595 aCmisProps[i].Type, 2596 aCmisProps[i].Updatable, 2597 aCmisProps[i].Required, 2598 aCmisProps[i].MultiValued, 2599 aCmisProps[i].OpenChoice, 2600 aCmisProps[i].Choices, 2601 aCmisProps[i].Value ); 2602 } 2603 m_pPropertiesCtrl.setScrollRange(); 2604 } 2605 2606 DeactivateRC SfxCmisPropertiesPage::DeactivatePage( SfxItemSet* /*pSet*/ ) 2607 { 2608 return DeactivateRC::LeavePage; 2609 } 2610 2611 VclPtr<SfxTabPage> SfxCmisPropertiesPage::Create( TabPageParent pParent, const SfxItemSet* rItemSet ) 2612 { 2613 return VclPtr<SfxCmisPropertiesPage>::Create( pParent.pParent, *rItemSet ); 2614 } 2615 2616 void SfxCmisPropertiesPage::SetPosSizePixel(const Point& rAllocPos, const Size& rAllocation) 2617 { 2618 SfxTabPage::SetPosSizePixel(rAllocPos, rAllocation); 2619 m_pPropertiesCtrl.setScrollRange(); 2620 } 2621 2622 void SfxCmisPropertiesPage::SetSizePixel(const Size& rAllocation) 2623 { 2624 SfxTabPage::SetSizePixel(rAllocation); 2625 m_pPropertiesCtrl.setScrollRange(); 2626 } 2627 2628 void SfxCmisPropertiesPage::SetPosPixel(const Point& rAllocPos) 2629 { 2630 SfxTabPage::SetPosPixel(rAllocPos); 2631 m_pPropertiesCtrl.setScrollRange(); 2632 } 2633 2634 2635 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 2636
