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_unotools.hxx" 30 #ifndef GCC 31 #endif 32 33 //_________________________________________________________________________________________________________________ 34 // includes 35 //_________________________________________________________________________________________________________________ 36 37 #include <unotools/dynamicmenuoptions.hxx> 38 #include <unotools/moduleoptions.hxx> 39 #include <unotools/configmgr.hxx> 40 #include <unotools/configitem.hxx> 41 #include <tools/debug.hxx> 42 #include <com/sun/star/uno/Any.hxx> 43 #include <com/sun/star/uno/Sequence.hxx> 44 45 #ifndef __SGI_STL_VECTOR 46 #include <vector> 47 #endif 48 49 #include <itemholder1.hxx> 50 51 #include <algorithm> 52 53 //_________________________________________________________________________________________________________________ 54 // namespaces 55 //_________________________________________________________________________________________________________________ 56 57 using namespace ::std ; 58 using namespace ::utl ; 59 using namespace ::rtl ; 60 using namespace ::osl ; 61 using namespace ::com::sun::star::uno ; 62 using namespace ::com::sun::star::beans ; 63 64 //_________________________________________________________________________________________________________________ 65 // const 66 //_________________________________________________________________________________________________________________ 67 68 #define ROOTNODE_MENUS OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Common/Menus/" )) 69 #define PATHDELIMITER OUString(RTL_CONSTASCII_USTRINGPARAM("/" )) 70 71 #define SETNODE_NEWMENU OUString(RTL_CONSTASCII_USTRINGPARAM("New" )) 72 #define SETNODE_WIZARDMENU OUString(RTL_CONSTASCII_USTRINGPARAM("Wizard" )) 73 #define SETNODE_HELPBOOKMARKS OUString(RTL_CONSTASCII_USTRINGPARAM("HelpBookmarks" )) 74 75 #define PROPERTYNAME_URL DYNAMICMENU_PROPERTYNAME_URL 76 #define PROPERTYNAME_TITLE DYNAMICMENU_PROPERTYNAME_TITLE 77 #define PROPERTYNAME_IMAGEIDENTIFIER DYNAMICMENU_PROPERTYNAME_IMAGEIDENTIFIER 78 #define PROPERTYNAME_TARGETNAME DYNAMICMENU_PROPERTYNAME_TARGETNAME 79 80 #define PROPERTYCOUNT 4 81 82 #define OFFSET_URL 0 83 #define OFFSET_TITLE 1 84 #define OFFSET_IMAGEIDENTIFIER 2 85 #define OFFSET_TARGETNAME 3 86 87 #define PATHPREFIX_SETUP OUString(RTL_CONSTASCII_USTRINGPARAM("m" )) 88 #define PATHPREFIX_USER OUString(RTL_CONSTASCII_USTRINGPARAM("u" )) 89 90 //_________________________________________________________________________________________________________________ 91 // private declarations! 92 //_________________________________________________________________________________________________________________ 93 94 /*-**************************************************************************************************************** 95 @descr struct to hold information about one menu entry. 96 ****************************************************************************************************************-*/ 97 struct SvtDynMenuEntry 98 { 99 public: 100 SvtDynMenuEntry() {}; 101 102 SvtDynMenuEntry( const OUString& sNewURL , 103 const OUString& sNewTitle , 104 const OUString& sNewImageIdentifier , 105 const OUString& sNewTargetName ) 106 { 107 sURL = sNewURL ; 108 sTitle = sNewTitle ; 109 sImageIdentifier = sNewImageIdentifier ; 110 sTargetName = sNewTargetName ; 111 } 112 113 public: 114 OUString sName ; 115 OUString sURL ; 116 OUString sTitle ; 117 OUString sImageIdentifier ; 118 OUString sTargetName ; 119 }; 120 121 /*-**************************************************************************************************************** 122 @descr support simple menu structures and operations on it 123 ****************************************************************************************************************-*/ 124 class SvtDynMenu 125 { 126 public: 127 //--------------------------------------------------------------------------------------------------------- 128 // append setup written menu entry 129 // Don't touch name of entry. It was defined by setup and must be the same everytime! 130 // Look for double menu entries here too ... may be some seperator items are supeflous ... 131 void AppendSetupEntry( const SvtDynMenuEntry& rEntry ) 132 { 133 if( 134 ( lSetupEntries.size() < 1 ) || 135 ( lSetupEntries.rbegin()->sURL != rEntry.sURL ) 136 ) 137 { 138 lSetupEntries.push_back( rEntry ); 139 } 140 } 141 142 //--------------------------------------------------------------------------------------------------------- 143 // append user specific menu entry 144 // We must find unique name for it by using special prefix 145 // and next count of user setted entries! 146 // Look for double menu entries here too ... may be some seperator items are supeflous ... 147 void AppendUserEntry( SvtDynMenuEntry& rEntry ) 148 { 149 if( 150 ( lUserEntries.size() < 1 ) || 151 ( lUserEntries.rbegin()->sURL != rEntry.sURL ) 152 ) 153 { 154 rEntry.sName = PATHPREFIX_USER; 155 rEntry.sName += OUString::valueOf( (sal_Int32)impl_getNextUserEntryNr() ); 156 lUserEntries.push_back( rEntry ); 157 } 158 } 159 160 //--------------------------------------------------------------------------------------------------------- 161 // the only way to free memory! 162 void Clear() 163 { 164 lSetupEntries.clear(); 165 lUserEntries.clear(); 166 } 167 168 //--------------------------------------------------------------------------------------------------------- 169 // convert internal list to external format 170 // for using it on right menus realy 171 // Notice: We build a property list with 4 entries and set it on result list then. 172 // The while-loop starts with pointer on internal member list lSetupEntries, change to 173 // lUserEntries then and stop after that with NULL! 174 // Separator entries will be packed in another way then normal entries! We define 175 // special strings "sEmpty" and "sSeperator" to perform too ... 176 Sequence< Sequence< PropertyValue > > GetList() const 177 { 178 sal_Int32 nSetupCount = (sal_Int32)lSetupEntries.size(); 179 sal_Int32 nUserCount = (sal_Int32)lUserEntries.size(); 180 sal_Int32 nStep = 0; 181 Sequence< PropertyValue > lProperties ( PROPERTYCOUNT ); 182 Sequence< Sequence< PropertyValue > > lResult ( nSetupCount+nUserCount ); 183 OUString sSeperator ( RTL_CONSTASCII_USTRINGPARAM("private:separator") ); 184 OUString sEmpty ; 185 const vector< SvtDynMenuEntry >* pList = &lSetupEntries; 186 187 lProperties[OFFSET_URL ].Name = PROPERTYNAME_URL ; 188 lProperties[OFFSET_TITLE ].Name = PROPERTYNAME_TITLE ; 189 lProperties[OFFSET_IMAGEIDENTIFIER].Name = PROPERTYNAME_IMAGEIDENTIFIER ; 190 lProperties[OFFSET_TARGETNAME ].Name = PROPERTYNAME_TARGETNAME ; 191 192 while( pList != NULL ) 193 { 194 for( vector< SvtDynMenuEntry >::const_iterator pItem =pList->begin(); 195 pItem!=pList->end() ; 196 ++pItem ) 197 { 198 if( pItem->sURL == sSeperator ) 199 { 200 lProperties[OFFSET_URL ].Value <<= sSeperator ; 201 lProperties[OFFSET_TITLE ].Value <<= sEmpty ; 202 lProperties[OFFSET_IMAGEIDENTIFIER ].Value <<= sEmpty ; 203 lProperties[OFFSET_TARGETNAME ].Value <<= sEmpty ; 204 } 205 else 206 { 207 lProperties[OFFSET_URL ].Value <<= pItem->sURL ; 208 lProperties[OFFSET_TITLE ].Value <<= pItem->sTitle ; 209 lProperties[OFFSET_IMAGEIDENTIFIER ].Value <<= pItem->sImageIdentifier; 210 lProperties[OFFSET_TARGETNAME ].Value <<= pItem->sTargetName ; 211 } 212 lResult[nStep] = lProperties; 213 ++nStep; 214 } 215 if( pList == &lSetupEntries ) 216 pList = &lUserEntries; 217 else 218 pList = NULL; 219 } 220 return lResult; 221 } 222 223 private: 224 //--------------------------------------------------------------------------------------------------------- 225 // search for an entry named "ux" with x=[0..i] inside our menu 226 // which has set highest number x. So we can add another user entry. 227 sal_Int32 impl_getNextUserEntryNr() const 228 { 229 sal_Int32 nNr = 0; 230 for( vector< SvtDynMenuEntry >::const_iterator pItem =lUserEntries.begin(); 231 pItem!=lUserEntries.end() ; 232 ++pItem ) 233 { 234 if( pItem->sName.compareTo( PATHPREFIX_USER, 1 ) == 0 ) 235 { 236 OUString sNr = pItem->sName.copy( 1, pItem->sName.getLength()-1 ); 237 sal_Int32 nCheckNr = sNr.toInt32(); 238 if( nCheckNr > nNr ) 239 nNr = nCheckNr; 240 } 241 } 242 // Attention: Code isn't prepared for recyling of unused fragmented numbers! 243 // If we reach end of sal_Int32 range ... we must stop further working ... 244 // But I think nobody expand a menu to more then 1000 ... 100000 ... entries ... or? 245 DBG_ASSERT( !(nNr>0x7fffffff), "Menu::impl_getNextUserEntryNr()\nUser count can be out of range next time ...\n" ); 246 return nNr; 247 } 248 249 private: 250 vector< SvtDynMenuEntry > lSetupEntries; 251 vector< SvtDynMenuEntry > lUserEntries ; 252 }; 253 254 class SvtDynamicMenuOptions_Impl : public ConfigItem 255 { 256 //------------------------------------------------------------------------------------------------------------- 257 // public methods 258 //------------------------------------------------------------------------------------------------------------- 259 260 public: 261 262 //--------------------------------------------------------------------------------------------------------- 263 // constructor / destructor 264 //--------------------------------------------------------------------------------------------------------- 265 266 SvtDynamicMenuOptions_Impl(); 267 ~SvtDynamicMenuOptions_Impl(); 268 269 //--------------------------------------------------------------------------------------------------------- 270 // overloaded methods of baseclass 271 //--------------------------------------------------------------------------------------------------------- 272 273 /*-****************************************************************************************************//** 274 @short called for notify of configmanager 275 @descr These method is called from the ConfigManager before application ends or from the 276 PropertyChangeListener if the sub tree broadcasts changes. You must update your 277 internal values. 278 279 @seealso baseclass ConfigItem 280 281 @param "lPropertyNames" is the list of properties which should be updated. 282 @return - 283 284 @onerror - 285 *//*-*****************************************************************************************************/ 286 287 virtual void Notify( const Sequence< OUString >& lPropertyNames ); 288 289 /*-****************************************************************************************************//** 290 @short write changes to configuration 291 @descr These method writes the changed values into the sub tree 292 and should always called in our destructor to guarantee consistency of config data. 293 294 @seealso baseclass ConfigItem 295 296 @param - 297 @return - 298 299 @onerror - 300 *//*-*****************************************************************************************************/ 301 302 virtual void Commit(); 303 304 //--------------------------------------------------------------------------------------------------------- 305 // public interface 306 //--------------------------------------------------------------------------------------------------------- 307 308 /*-****************************************************************************************************//** 309 @short base implementation of public interface for "SvtDynamicMenuOptions"! 310 @descr These class is used as static member of "SvtDynamicMenuOptions" ... 311 => The code exist only for one time and isn't duplicated for every instance! 312 313 @seealso - 314 315 @param - 316 @return - 317 318 @onerror - 319 *//*-*****************************************************************************************************/ 320 321 void Clear ( EDynamicMenuType eMenu ); 322 Sequence< Sequence< PropertyValue > > GetMenu ( EDynamicMenuType eMenu ) const ; 323 void AppendItem ( EDynamicMenuType eMenu , 324 const OUString& sURL , 325 const OUString& sTitle , 326 const OUString& sImageIdentifier, 327 const OUString& sTargetName ); 328 329 //------------------------------------------------------------------------------------------------------------- 330 // private methods 331 //------------------------------------------------------------------------------------------------------------- 332 333 private: 334 335 /*-****************************************************************************************************//** 336 @short return list of key names of our configuration management which represent oue module tree 337 @descr These methods return the current list of key names! We need it to get needed values from our 338 configuration management and support dynamical menu item lists! 339 340 @seealso - 341 342 @param "nNewCount" , returns count of menu entries for "new" 343 @param "nWizardCount" , returns count of menu entries for "wizard" 344 @return A list of configuration key names is returned. 345 346 @onerror - 347 *//*-*****************************************************************************************************/ 348 349 Sequence< OUString > impl_GetPropertyNames( sal_uInt32& nNewCount, sal_uInt32& nWizardCount, sal_uInt32& nHelpBookmarksCount ); 350 351 /*-****************************************************************************************************//** 352 @short sort given source list and expand it for all well known properties to destination 353 @descr We must support sets of entries with count inside the name .. but some of them could be missing! 354 e.g. s1-s2-s3-s0-u1-s6-u5-u7 355 Then we must sort it by name and expand it to the follow one: 356 sSetNode/s0/URL 357 sSetNode/s0/Title 358 sSetNode/s0/... 359 sSetNode/s1/URL 360 sSetNode/s1/Title 361 sSetNode/s1/... 362 ... 363 sSetNode/s6/URL 364 sSetNode/s6/Title 365 sSetNode/s6/... 366 sSetNode/u1/URL 367 sSetNode/u1/Title 368 sSetNode/u1/... 369 ... 370 sSetNode/u7/URL 371 sSetNode/u7/Title 372 sSetNode/u7/... 373 Rules: We start with all setup written entries names "sx" and x=[0..n]. 374 Then we handle all "ux" items. Inside these blocks we sort it ascending by number. 375 376 @attention We add these expanded list to the end of given "lDestination" list! 377 So we must start on "lDestination.getLength()". 378 Reallocation of memory of destination list is done by us! 379 380 @seealso method impl_GetPropertyNames() 381 382 @param "lSource" , original list (e.g. [m1-m2-m3-m6-m0] ) 383 @param "lDestination" , destination of operation 384 @param "sSetNode" , name of configuration set to build complete path 385 @return A list of configuration key names is returned. 386 387 @onerror - 388 *//*-*****************************************************************************************************/ 389 390 void impl_SortAndExpandPropertyNames( const Sequence< OUString >& lSource , 391 Sequence< OUString >& lDestination , 392 const OUString& sSetNode ); 393 394 //------------------------------------------------------------------------------------------------------------- 395 // private member 396 //------------------------------------------------------------------------------------------------------------- 397 398 private: 399 400 SvtDynMenu m_aNewMenu ; 401 SvtDynMenu m_aWizardMenu ; 402 SvtDynMenu m_aHelpBookmarksMenu ; 403 }; 404 405 //_________________________________________________________________________________________________________________ 406 // definitions 407 //_________________________________________________________________________________________________________________ 408 409 //***************************************************************************************************************** 410 // constructor 411 //***************************************************************************************************************** 412 SvtDynamicMenuOptions_Impl::SvtDynamicMenuOptions_Impl() 413 // Init baseclasses first 414 : ConfigItem( ROOTNODE_MENUS ) 415 // Init member then... 416 { 417 // Get names and values of all accessable menu entries and fill internal structures. 418 // See impl_GetPropertyNames() for further informations. 419 sal_uInt32 nNewCount = 0; 420 sal_uInt32 nWizardCount = 0; 421 sal_uInt32 nHelpBookmarksCount = 0; 422 Sequence< OUString > lNames = impl_GetPropertyNames ( nNewCount , 423 nWizardCount , 424 nHelpBookmarksCount ); 425 Sequence< Any > lValues = GetProperties ( lNames ); 426 427 // Safe impossible cases. 428 // We need values from ALL configuration keys. 429 // Follow assignment use order of values in relation to our list of key names! 430 DBG_ASSERT( !(lNames.getLength()!=lValues.getLength()), "SvtDynamicMenuOptions_Impl::SvtDynamicMenuOptions_Impl()\nI miss some values of configuration keys!\n" ); 431 432 // Copy values from list in right order to ouer internal member. 433 // Attention: List for names and values have an internal construction pattern! 434 // 435 // first "New" menu ... 436 // Name Value 437 // /New/1/URL "private:factory/swriter" 438 // /New/1/Title "Neues Writer Dokument" 439 // /New/1/ImageIdentifier "icon_writer" 440 // /New/1/TargetName "_blank" 441 // 442 // /New/2/URL "private:factory/scalc" 443 // /New/2/Title "Neues Calc Dokument" 444 // /New/2/ImageIdentifier "icon_calc" 445 // /New/2/TargetName "_blank" 446 // 447 // second "Wizard" menu ... 448 // /Wizard/1/URL "file://b" 449 // /Wizard/1/Title "MalWas" 450 // /Wizard/1/ImageIdentifier "icon_?" 451 // /Wizard/1/TargetName "_self" 452 // 453 // ... and so on ... 454 455 sal_uInt32 nItem = 0 ; 456 sal_uInt32 nPosition = 0 ; 457 OUString sName ; 458 459 // We must use these one instance object(!) to get information about installed modules. 460 // These information are used to filter menu entries wich need not installed modules ... 461 // Such entries shouldnt be available then! 462 // see impl_IsEntrySupported() too 463 SvtModuleOptions aModuleOptions; 464 465 // Get names/values for new menu. 466 // 4 subkeys for every item! 467 for( nItem=0; nItem<nNewCount; ++nItem ) 468 { 469 SvtDynMenuEntry aItem ; 470 lValues[nPosition] >>= aItem.sURL ; 471 ++nPosition; 472 lValues[nPosition] >>= aItem.sTitle ; 473 ++nPosition; 474 lValues[nPosition] >>= aItem.sImageIdentifier ; 475 ++nPosition; 476 lValues[nPosition] >>= aItem.sTargetName ; 477 ++nPosition; 478 m_aNewMenu.AppendSetupEntry( aItem ); 479 } 480 481 // Attention: Don't reset nPosition here! 482 483 // Get names/values for wizard menu. 484 // 4 subkeys for every item! 485 for( nItem=0; nItem<nWizardCount; ++nItem ) 486 { 487 SvtDynMenuEntry aItem ; 488 lValues[nPosition] >>= aItem.sURL ; 489 ++nPosition; 490 lValues[nPosition] >>= aItem.sTitle ; 491 ++nPosition; 492 lValues[nPosition] >>= aItem.sImageIdentifier ; 493 ++nPosition; 494 lValues[nPosition] >>= aItem.sTargetName ; 495 ++nPosition; 496 m_aWizardMenu.AppendSetupEntry( aItem ); 497 } 498 499 // Attention: Don't reset nPosition here! 500 501 // Get names/values for wizard menu. 502 // 4 subkeys for every item! 503 for( nItem=0; nItem<nHelpBookmarksCount; ++nItem ) 504 { 505 SvtDynMenuEntry aItem ; 506 lValues[nPosition] >>= aItem.sURL ; 507 ++nPosition; 508 lValues[nPosition] >>= aItem.sTitle ; 509 ++nPosition; 510 lValues[nPosition] >>= aItem.sImageIdentifier ; 511 ++nPosition; 512 lValues[nPosition] >>= aItem.sTargetName ; 513 ++nPosition; 514 m_aHelpBookmarksMenu.AppendSetupEntry( aItem ); 515 } 516 517 /*TODO: Not used in the moment! see Notify() ... 518 // Enable notification mechanism of ouer baseclass. 519 // We need it to get information about changes outside these class on ouer used configuration keys! 520 EnableNotification( lNames ); 521 */ 522 } 523 524 //***************************************************************************************************************** 525 // destructor 526 //***************************************************************************************************************** 527 SvtDynamicMenuOptions_Impl::~SvtDynamicMenuOptions_Impl() 528 { 529 // We must save our current values .. if user forget it! 530 if( IsModified() == sal_True ) 531 { 532 Commit(); 533 } 534 } 535 536 //***************************************************************************************************************** 537 // public method 538 //***************************************************************************************************************** 539 void SvtDynamicMenuOptions_Impl::Notify( const Sequence< OUString >& ) 540 { 541 DBG_ASSERT( sal_False, "SvtDynamicMenuOptions_Impl::Notify()\nNot implemented yet! I don't know how I can handle a dynamical list of unknown properties ...\n" ); 542 } 543 544 //***************************************************************************************************************** 545 // public method 546 //***************************************************************************************************************** 547 void SvtDynamicMenuOptions_Impl::Commit() 548 { 549 DBG_ERROR( "SvtDynamicMenuOptions_Impl::Commit()\nNot implemented yet!\n" ); 550 /* 551 // Write all properties! 552 // Delete complete sets first. 553 ClearNodeSet( SETNODE_NEWMENU ); 554 ClearNodeSet( SETNODE_WIZARDMENU ); 555 ClearNodeSet( SETNODE_HELPBOOKMARKS ); 556 557 MenuEntry aItem ; 558 OUString sNode ; 559 Sequence< PropertyValue > lPropertyValues( PROPERTYCOUNT ); 560 sal_uInt32 nItem = 0 ; 561 562 // Copy "new" menu entries to save-list! 563 sal_uInt32 nNewCount = m_aNewMenu.size(); 564 for( nItem=0; nItem<nNewCount; ++nItem ) 565 { 566 aItem = m_aNewMenu[nItem]; 567 // Format: "New/1/URL" 568 // "New/1/Title" 569 // ... 570 sNode = SETNODE_NEWMENU + PATHDELIMITER + PATHPREFIX + OUString::valueOf( (sal_Int32)nItem ) + PATHDELIMITER; 571 572 lPropertyValues[OFFSET_URL ].Name = sNode + PROPERTYNAME_URL ; 573 lPropertyValues[OFFSET_TITLE ].Name = sNode + PROPERTYNAME_TITLE ; 574 lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Name = sNode + PROPERTYNAME_IMAGEIDENTIFIER ; 575 lPropertyValues[OFFSET_TARGETNAME ].Name = sNode + PROPERTYNAME_TARGETNAME ; 576 577 lPropertyValues[OFFSET_URL ].Value <<= aItem.sURL ; 578 lPropertyValues[OFFSET_TITLE ].Value <<= aItem.sTitle ; 579 lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Value <<= aItem.sImageIdentifier ; 580 lPropertyValues[OFFSET_TARGETNAME ].Value <<= aItem.sTargetName ; 581 582 SetSetProperties( SETNODE_NEWMENU, lPropertyValues ); 583 } 584 585 // Copy "wizard" menu entries to save-list! 586 sal_uInt32 nWizardCount = m_aWizardMenu.size(); 587 for( nItem=0; nItem<nWizardCount; ++nItem ) 588 { 589 aItem = m_aWizardMenu[nItem]; 590 // Format: "Wizard/1/URL" 591 // "Wizard/1/Title" 592 // ... 593 sNode = SETNODE_WIZARDMENU + PATHDELIMITER + PATHPREFIX + OUString::valueOf( (sal_Int32)nItem ) + PATHDELIMITER; 594 595 lPropertyValues[OFFSET_URL ].Name = sNode + PROPERTYNAME_URL ; 596 lPropertyValues[OFFSET_TITLE ].Name = sNode + PROPERTYNAME_TITLE ; 597 lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Name = sNode + PROPERTYNAME_IMAGEIDENTIFIER ; 598 lPropertyValues[OFFSET_TARGETNAME ].Name = sNode + PROPERTYNAME_TARGETNAME ; 599 600 lPropertyValues[OFFSET_URL ].Value <<= aItem.sURL ; 601 lPropertyValues[OFFSET_TITLE ].Value <<= aItem.sTitle ; 602 lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Value <<= aItem.sImageIdentifier ; 603 lPropertyValues[OFFSET_TARGETNAME ].Value <<= aItem.sTargetName ; 604 605 SetSetProperties( SETNODE_WIZARDMENU, lPropertyValues ); 606 } 607 608 // Copy help bookmarks entries to save-list! 609 sal_uInt32 nHelpBookmarksCount = m_aHelpBookmarksMenu.size(); 610 for( nItem=0; nItem<nHelpBookmarksCount; ++nItem ) 611 { 612 aItem = m_aHelpBookmarksMenu[nItem]; 613 // Format: "HelpBookmarks/1/URL" 614 // "HelpBookmarks/1/Title" 615 // ... 616 sNode = SETNODE_HELPBOOKMARKS + PATHDELIMITER + PATHPREFIX + OUString::valueOf( (sal_Int32)nItem ) + PATHDELIMITER; 617 618 lPropertyValues[OFFSET_URL ].Name = sNode + PROPERTYNAME_URL ; 619 lPropertyValues[OFFSET_TITLE ].Name = sNode + PROPERTYNAME_TITLE ; 620 lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Name = sNode + PROPERTYNAME_IMAGEIDENTIFIER ; 621 lPropertyValues[OFFSET_TARGETNAME ].Name = sNode + PROPERTYNAME_TARGETNAME ; 622 623 lPropertyValues[OFFSET_URL ].Value <<= aItem.sURL ; 624 lPropertyValues[OFFSET_TITLE ].Value <<= aItem.sTitle ; 625 lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Value <<= aItem.sImageIdentifier ; 626 lPropertyValues[OFFSET_TARGETNAME ].Value <<= aItem.sTargetName ; 627 628 SetSetProperties( SETNODE_HELPBOOKMARKS, lPropertyValues ); 629 } 630 */ 631 } 632 633 //***************************************************************************************************************** 634 // public method 635 //***************************************************************************************************************** 636 void SvtDynamicMenuOptions_Impl::Clear( EDynamicMenuType eMenu ) 637 { 638 switch( eMenu ) 639 { 640 case E_NEWMENU : { 641 m_aNewMenu.Clear(); 642 SetModified(); 643 } 644 break; 645 646 case E_WIZARDMENU : { 647 m_aWizardMenu.Clear(); 648 SetModified(); 649 } 650 break; 651 652 case E_HELPBOOKMARKS : { 653 m_aHelpBookmarksMenu.Clear(); 654 SetModified(); 655 } 656 break; 657 } 658 } 659 660 //***************************************************************************************************************** 661 // public method 662 //***************************************************************************************************************** 663 Sequence< Sequence< PropertyValue > > SvtDynamicMenuOptions_Impl::GetMenu( EDynamicMenuType eMenu ) const 664 { 665 Sequence< Sequence< PropertyValue > > lReturn; 666 switch( eMenu ) 667 { 668 case E_NEWMENU : { 669 lReturn = m_aNewMenu.GetList(); 670 } 671 break; 672 673 case E_WIZARDMENU : { 674 lReturn = m_aWizardMenu.GetList(); 675 } 676 break; 677 678 case E_HELPBOOKMARKS : { 679 lReturn = m_aHelpBookmarksMenu.GetList(); 680 } 681 break; 682 } 683 return lReturn; 684 } 685 686 //***************************************************************************************************************** 687 // public method 688 //***************************************************************************************************************** 689 void SvtDynamicMenuOptions_Impl::AppendItem( EDynamicMenuType eMenu , 690 const OUString& sURL , 691 const OUString& sTitle , 692 const OUString& sImageIdentifier, 693 const OUString& sTargetName ) 694 { 695 SvtDynMenuEntry aItem( sURL, sTitle, sImageIdentifier, sTargetName ); 696 697 switch( eMenu ) 698 { 699 case E_NEWMENU : { 700 m_aNewMenu.AppendUserEntry( aItem ); 701 SetModified(); 702 } 703 break; 704 705 case E_WIZARDMENU : { 706 m_aWizardMenu.AppendUserEntry( aItem ); 707 SetModified(); 708 } 709 break; 710 711 case E_HELPBOOKMARKS : { 712 m_aHelpBookmarksMenu.AppendUserEntry( aItem ); 713 SetModified(); 714 } 715 break; 716 } 717 } 718 719 //***************************************************************************************************************** 720 // private method 721 //***************************************************************************************************************** 722 Sequence< OUString > SvtDynamicMenuOptions_Impl::impl_GetPropertyNames( sal_uInt32& nNewCount, sal_uInt32& nWizardCount, sal_uInt32& nHelpBookmarksCount ) 723 { 724 // First get ALL names of current existing list items in configuration! 725 Sequence< OUString > lNewItems = GetNodeNames( SETNODE_NEWMENU ); 726 Sequence< OUString > lWizardItems = GetNodeNames( SETNODE_WIZARDMENU ); 727 Sequence< OUString > lHelpBookmarksItems = GetNodeNames( SETNODE_HELPBOOKMARKS ); 728 729 // Get information about list counts ... 730 nNewCount = lNewItems.getLength (); 731 nWizardCount = lWizardItems.getLength (); 732 nHelpBookmarksCount = lHelpBookmarksItems.getLength(); 733 734 // Sort and expand all three list to result list ... 735 Sequence< OUString > lProperties; 736 impl_SortAndExpandPropertyNames( lNewItems , lProperties, SETNODE_NEWMENU ); 737 impl_SortAndExpandPropertyNames( lWizardItems , lProperties, SETNODE_WIZARDMENU ); 738 impl_SortAndExpandPropertyNames( lHelpBookmarksItems, lProperties, SETNODE_HELPBOOKMARKS ); 739 740 // Return result. 741 return lProperties; 742 } 743 744 //***************************************************************************************************************** 745 // private helper 746 //***************************************************************************************************************** 747 class CountWithPrefixSort 748 { 749 public: 750 int operator() ( const OUString& s1 , 751 const OUString& s2 ) const 752 { 753 // Get order numbers from entry name without prefix. 754 // e.g. "m10" => 10 755 // "m5" => 5 756 sal_Int32 n1 = s1.copy( 1, s1.getLength()-1 ).toInt32(); 757 sal_Int32 n2 = s2.copy( 1, s2.getLength()-1 ).toInt32(); 758 // MUST be in [0,1] ... because it's a difference between 759 // insert-positions of given entries in sorted list! 760 return( n1<n2 ); 761 } 762 }; 763 764 class SelectByPrefix 765 { 766 public: 767 bool operator() ( const OUString& s ) const 768 { 769 // Prefer setup written entries by check first letter of given string. It must be a "s". 770 return( s.indexOf( PATHPREFIX_SETUP ) == 0 ); 771 } 772 }; 773 774 //***************************************************************************************************************** 775 // private method 776 //***************************************************************************************************************** 777 void SvtDynamicMenuOptions_Impl::impl_SortAndExpandPropertyNames( const Sequence< OUString >& lSource , 778 Sequence< OUString >& lDestination , 779 const OUString& sSetNode ) 780 { 781 OUString sFixPath ; 782 vector< OUString > lTemp ; 783 sal_Int32 nSourceCount = lSource.getLength() ; 784 sal_Int32 nDestinationStep = lDestination.getLength() ; // start on end of current list ...! 785 786 lDestination.realloc( (nSourceCount*PROPERTYCOUNT)+nDestinationStep ); // get enough memory for copy operations after nDestination ... 787 788 // Copy all items to temp. vector to use fast sort operations :-) 789 for( sal_Int32 nSourceStep=0; nSourceStep<nSourceCount; ++nSourceStep ) 790 lTemp.push_back( lSource[nSourceStep] ); 791 792 // Sort all entries by number ... 793 stable_sort( lTemp.begin(), lTemp.end(), CountWithPrefixSort() ); 794 // and split into setup & user written entries! 795 stable_partition( lTemp.begin(), lTemp.end(), SelectByPrefix() ); 796 797 // Copy sorted entries to destination and expand every item with 798 // 4 supported sub properties. 799 for( vector< OUString >::const_iterator pItem =lTemp.begin() ; 800 pItem!=lTemp.end() ; 801 ++pItem ) 802 { 803 sFixPath = sSetNode ; 804 sFixPath += PATHDELIMITER ; 805 sFixPath += *pItem ; 806 sFixPath += PATHDELIMITER ; 807 808 lDestination[nDestinationStep] = sFixPath ; 809 lDestination[nDestinationStep] += PROPERTYNAME_URL ; 810 ++nDestinationStep; 811 lDestination[nDestinationStep] = sFixPath ; 812 lDestination[nDestinationStep] += PROPERTYNAME_TITLE ; 813 ++nDestinationStep; 814 lDestination[nDestinationStep] = sFixPath ; 815 lDestination[nDestinationStep] += PROPERTYNAME_IMAGEIDENTIFIER ; 816 ++nDestinationStep; 817 lDestination[nDestinationStep] = sFixPath ; 818 lDestination[nDestinationStep] += PROPERTYNAME_TARGETNAME ; 819 ++nDestinationStep; 820 } 821 } 822 823 //***************************************************************************************************************** 824 // initialize static member 825 // DON'T DO IT IN YOUR HEADER! 826 // see definition for further informations 827 //***************************************************************************************************************** 828 SvtDynamicMenuOptions_Impl* SvtDynamicMenuOptions::m_pDataContainer = NULL ; 829 sal_Int32 SvtDynamicMenuOptions::m_nRefCount = 0 ; 830 831 //***************************************************************************************************************** 832 // constructor 833 //***************************************************************************************************************** 834 SvtDynamicMenuOptions::SvtDynamicMenuOptions() 835 { 836 // Global access, must be guarded (multithreading!). 837 MutexGuard aGuard( GetOwnStaticMutex() ); 838 // Increase ouer refcount ... 839 ++m_nRefCount; 840 // ... and initialize ouer data container only if it not already exist! 841 if( m_pDataContainer == NULL ) 842 { 843 m_pDataContainer = new SvtDynamicMenuOptions_Impl; 844 ItemHolder1::holdConfigItem(E_DYNAMICMENUOPTIONS); 845 } 846 } 847 848 //***************************************************************************************************************** 849 // destructor 850 //***************************************************************************************************************** 851 SvtDynamicMenuOptions::~SvtDynamicMenuOptions() 852 { 853 // Global access, must be guarded (multithreading!) 854 MutexGuard aGuard( GetOwnStaticMutex() ); 855 // Decrease ouer refcount. 856 --m_nRefCount; 857 // If last instance was deleted ... 858 // we must destroy ouer static data container! 859 if( m_nRefCount <= 0 ) 860 { 861 delete m_pDataContainer; 862 m_pDataContainer = NULL; 863 } 864 } 865 866 //***************************************************************************************************************** 867 // public method 868 //***************************************************************************************************************** 869 void SvtDynamicMenuOptions::Clear( EDynamicMenuType eMenu ) 870 { 871 MutexGuard aGuard( GetOwnStaticMutex() ); 872 m_pDataContainer->Clear( eMenu ); 873 } 874 875 //***************************************************************************************************************** 876 // public method 877 //***************************************************************************************************************** 878 Sequence< Sequence< PropertyValue > > SvtDynamicMenuOptions::GetMenu( EDynamicMenuType eMenu ) const 879 { 880 MutexGuard aGuard( GetOwnStaticMutex() ); 881 return m_pDataContainer->GetMenu( eMenu ); 882 } 883 884 //***************************************************************************************************************** 885 // public method 886 //***************************************************************************************************************** 887 void SvtDynamicMenuOptions::AppendItem( EDynamicMenuType eMenu , 888 const OUString& sURL , 889 const OUString& sTitle , 890 const OUString& sImageIdentifier, 891 const OUString& sTargetName ) 892 { 893 MutexGuard aGuard( GetOwnStaticMutex() ); 894 m_pDataContainer->AppendItem( eMenu, sURL, sTitle, sImageIdentifier, sTargetName ); 895 } 896 897 //***************************************************************************************************************** 898 // private method 899 //***************************************************************************************************************** 900 Mutex& SvtDynamicMenuOptions::GetOwnStaticMutex() 901 { 902 // Initialize static mutex only for one time! 903 static Mutex* pMutex = NULL; 904 // If these method first called (Mutex not already exist!) ... 905 if( pMutex == NULL ) 906 { 907 // ... we must create a new one. Protect follow code with the global mutex - 908 // It must be - we create a static variable! 909 MutexGuard aGuard( Mutex::getGlobalMutex() ); 910 // We must check our pointer again - because it can be that another instance of ouer class will be fastr then these! 911 if( pMutex == NULL ) 912 { 913 // Create the new mutex and set it for return on static variable. 914 static Mutex aMutex; 915 pMutex = &aMutex; 916 } 917 } 918 // Return new created or already existing mutex object. 919 return *pMutex; 920 } 921