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:
SvtDynMenuEntrySvtDynMenuEntry96 SvtDynMenuEntry() {};
97
SvtDynMenuEntrySvtDynMenuEntry98 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 every time!
126 // Look for double menu entries here too ... may be some seperator items are supeflous ...
AppendSetupEntry(const SvtDynMenuEntry & rEntry)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 set entries!
142 // Look for double menu entries here too ... may be some seperator items are supeflous ...
AppendUserEntry(SvtDynMenuEntry & rEntry)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!
Clear()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 really
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 ...
GetList() const172 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.
impl_getNextUserEntryNr() const223 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 our 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 //*****************************************************************************************************************
SvtDynamicMenuOptions_Impl()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 accessible 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 our 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 which need not installed modules ...
457 // Such entries shouldn't 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 our baseclass.
515 // We need it to get information about changes outside these class on our used configuration keys!
516 EnableNotification( lNames );
517 */
518 }
519
520 //*****************************************************************************************************************
521 // destructor
522 //*****************************************************************************************************************
~SvtDynamicMenuOptions_Impl()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 //*****************************************************************************************************************
Notify(const Sequence<OUString> &)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 //*****************************************************************************************************************
Commit()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 //*****************************************************************************************************************
Clear(EDynamicMenuType eMenu)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 //*****************************************************************************************************************
GetMenu(EDynamicMenuType eMenu) const659 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 //*****************************************************************************************************************
AppendItem(EDynamicMenuType eMenu,const OUString & sURL,const OUString & sTitle,const OUString & sImageIdentifier,const OUString & sTargetName)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 //*****************************************************************************************************************
impl_GetPropertyNames(sal_uInt32 & nNewCount,sal_uInt32 & nWizardCount,sal_uInt32 & nHelpBookmarksCount)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:
operator ()(const OUString & s1,const OUString & s2) const746 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:
operator ()(const OUString & s) const763 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 //*****************************************************************************************************************
impl_SortAndExpandPropertyNames(const Sequence<OUString> & lSource,Sequence<OUString> & lDestination,const OUString & sSetNode)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 //*****************************************************************************************************************
SvtDynamicMenuOptions()830 SvtDynamicMenuOptions::SvtDynamicMenuOptions()
831 {
832 // Global access, must be guarded (multithreading!).
833 MutexGuard aGuard( GetOwnStaticMutex() );
834 // Increase our refcount ...
835 ++m_nRefCount;
836 // ... and initialize our 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 //*****************************************************************************************************************
~SvtDynamicMenuOptions()847 SvtDynamicMenuOptions::~SvtDynamicMenuOptions()
848 {
849 // Global access, must be guarded (multithreading!)
850 MutexGuard aGuard( GetOwnStaticMutex() );
851 // Decrease our refcount.
852 --m_nRefCount;
853 // If last instance was deleted ...
854 // we must destroy our 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 //*****************************************************************************************************************
Clear(EDynamicMenuType eMenu)865 void SvtDynamicMenuOptions::Clear( EDynamicMenuType eMenu )
866 {
867 MutexGuard aGuard( GetOwnStaticMutex() );
868 m_pDataContainer->Clear( eMenu );
869 }
870
871 //*****************************************************************************************************************
872 // public method
873 //*****************************************************************************************************************
GetMenu(EDynamicMenuType eMenu) const874 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 //*****************************************************************************************************************
AppendItem(EDynamicMenuType eMenu,const OUString & sURL,const OUString & sTitle,const OUString & sImageIdentifier,const OUString & sTargetName)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 //*****************************************************************************************************************
GetOwnStaticMutex()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 our class will be faster than 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