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