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