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("Office.Common/Menus/")
43 : #define PATHDELIMITER OUString("/")
44 :
45 : #define SETNODE_NEWMENU OUString("New")
46 : #define SETNODE_WIZARDMENU OUString("Wizard")
47 : #define SETNODE_HELPBOOKMARKS OUString("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("m")
62 : #define PATHPREFIX_USER OUString("u")
63 :
64 : /*-****************************************************************************************************************
65 : @descr struct to hold information about one menu entry.
66 : ****************************************************************************************************************-*/
67 4230 : struct SvtDynMenuEntry
68 : {
69 : public:
70 810 : 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 180 : 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 separator items are supeflous ...
100 810 : void AppendSetupEntry( const SvtDynMenuEntry& rEntry )
101 : {
102 1680 : if(
103 2310 : ( lSetupEntries.size() < 1 ) ||
104 3060 : ( lSetupEntries.rbegin()->sURL != rEntry.sURL )
105 : )
106 : {
107 810 : lSetupEntries.push_back( rEntry );
108 : }
109 810 : }
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 separator 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 "sSeparator" to perform too ...
142 641 : Sequence< Sequence< PropertyValue > > GetList() const
143 : {
144 641 : sal_Int32 nSetupCount = (sal_Int32)lSetupEntries.size();
145 641 : sal_Int32 nUserCount = (sal_Int32)lUserEntries.size();
146 641 : sal_Int32 nStep = 0;
147 641 : Sequence< PropertyValue > lProperties ( PROPERTYCOUNT );
148 641 : Sequence< Sequence< PropertyValue > > lResult ( nSetupCount+nUserCount );
149 1282 : OUString sSeparator ( "private:separator" );
150 1282 : OUString sEmpty ;
151 641 : const vector< SvtDynMenuEntry >* pList = &lSetupEntries;
152 :
153 641 : lProperties[OFFSET_URL ].Name = PROPERTYNAME_URL ;
154 641 : lProperties[OFFSET_TITLE ].Name = PROPERTYNAME_TITLE ;
155 641 : lProperties[OFFSET_IMAGEIDENTIFIER].Name = PROPERTYNAME_IMAGEIDENTIFIER ;
156 641 : lProperties[OFFSET_TARGETNAME ].Name = PROPERTYNAME_TARGETNAME ;
157 :
158 2564 : while( pList != NULL )
159 : {
160 32691 : for( vector< SvtDynMenuEntry >::const_iterator pItem =pList->begin();
161 21794 : pItem!=pList->end() ;
162 : ++pItem )
163 : {
164 9615 : if( pItem->sURL == sSeparator )
165 : {
166 1923 : lProperties[OFFSET_URL ].Value <<= sSeparator ;
167 1923 : lProperties[OFFSET_TITLE ].Value <<= sEmpty ;
168 1923 : lProperties[OFFSET_IMAGEIDENTIFIER ].Value <<= sEmpty ;
169 1923 : lProperties[OFFSET_TARGETNAME ].Value <<= sEmpty ;
170 : }
171 : else
172 : {
173 7692 : lProperties[OFFSET_URL ].Value <<= pItem->sURL ;
174 7692 : lProperties[OFFSET_TITLE ].Value <<= pItem->sTitle ;
175 7692 : lProperties[OFFSET_IMAGEIDENTIFIER ].Value <<= pItem->sImageIdentifier;
176 7692 : lProperties[OFFSET_TARGETNAME ].Value <<= pItem->sTargetName ;
177 : }
178 9615 : lResult[nStep] = lProperties;
179 9615 : ++nStep;
180 : }
181 1282 : if( pList == &lSetupEntries )
182 641 : pList = &lUserEntries;
183 : else
184 641 : pList = NULL;
185 : }
186 1282 : 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.startsWith( PATHPREFIX_USER ) )
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 30 : SvtDynamicMenuOptions_Impl::SvtDynamicMenuOptions_Impl()
349 : // Init baseclasses first
350 30 : : ConfigItem( ROOTNODE_MENUS )
351 : // Init member then...
352 : {
353 : // Get names and values of all accessible menu entries and fill internal structures.
354 : // See impl_GetPropertyNames() for further information.
355 30 : sal_uInt32 nNewCount = 0;
356 30 : sal_uInt32 nWizardCount = 0;
357 30 : sal_uInt32 nHelpBookmarksCount = 0;
358 : Sequence< OUString > lNames = impl_GetPropertyNames ( nNewCount ,
359 : nWizardCount ,
360 30 : nHelpBookmarksCount );
361 60 : 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 30 : sal_uInt32 nItem = 0 ;
392 30 : sal_uInt32 nPosition = 0 ;
393 :
394 : // Get names/values for new menu.
395 : // 4 subkeys for every item!
396 480 : for( nItem=0; nItem<nNewCount; ++nItem )
397 : {
398 450 : SvtDynMenuEntry aItem ;
399 450 : lValues[nPosition] >>= aItem.sURL ;
400 450 : ++nPosition;
401 450 : lValues[nPosition] >>= aItem.sTitle ;
402 450 : ++nPosition;
403 450 : lValues[nPosition] >>= aItem.sImageIdentifier ;
404 450 : ++nPosition;
405 450 : lValues[nPosition] >>= aItem.sTargetName ;
406 450 : ++nPosition;
407 450 : m_aNewMenu.AppendSetupEntry( aItem );
408 450 : }
409 :
410 : // Attention: Don't reset nPosition here!
411 :
412 : // Get names/values for wizard menu.
413 : // 4 subkeys for every item!
414 390 : for( nItem=0; nItem<nWizardCount; ++nItem )
415 : {
416 360 : SvtDynMenuEntry aItem ;
417 360 : lValues[nPosition] >>= aItem.sURL ;
418 360 : ++nPosition;
419 360 : lValues[nPosition] >>= aItem.sTitle ;
420 360 : ++nPosition;
421 360 : lValues[nPosition] >>= aItem.sImageIdentifier ;
422 360 : ++nPosition;
423 360 : lValues[nPosition] >>= aItem.sTargetName ;
424 360 : ++nPosition;
425 360 : m_aWizardMenu.AppendSetupEntry( aItem );
426 360 : }
427 :
428 : // Attention: Don't reset nPosition here!
429 :
430 : // Get names/values for wizard menu.
431 : // 4 subkeys for every item!
432 30 : for( nItem=0; nItem<nHelpBookmarksCount; ++nItem )
433 : {
434 0 : SvtDynMenuEntry aItem ;
435 0 : lValues[nPosition] >>= aItem.sURL ;
436 0 : ++nPosition;
437 0 : lValues[nPosition] >>= aItem.sTitle ;
438 0 : ++nPosition;
439 0 : lValues[nPosition] >>= aItem.sImageIdentifier ;
440 0 : ++nPosition;
441 0 : lValues[nPosition] >>= aItem.sTargetName ;
442 0 : ++nPosition;
443 0 : m_aHelpBookmarksMenu.AppendSetupEntry( aItem );
444 30 : }
445 :
446 : /*TODO: Not used in the moment! see Notify() ...
447 : // Enable notification mechanism of ouer baseclass.
448 : // We need it to get information about changes outside these class on ouer used configuration keys!
449 : EnableNotification( lNames );
450 : */
451 30 : }
452 :
453 : //*****************************************************************************************************************
454 : // destructor
455 : //*****************************************************************************************************************
456 90 : SvtDynamicMenuOptions_Impl::~SvtDynamicMenuOptions_Impl()
457 : {
458 : // We must save our current values .. if user forget it!
459 30 : if( IsModified() == sal_True )
460 : {
461 0 : Commit();
462 : }
463 60 : }
464 :
465 : //*****************************************************************************************************************
466 : // public method
467 : //*****************************************************************************************************************
468 0 : void SvtDynamicMenuOptions_Impl::Notify( const Sequence< OUString >& )
469 : {
470 : 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" );
471 0 : }
472 :
473 : //*****************************************************************************************************************
474 : // public method
475 : //*****************************************************************************************************************
476 0 : void SvtDynamicMenuOptions_Impl::Commit()
477 : {
478 : OSL_FAIL( "SvtDynamicMenuOptions_Impl::Commit()\nNot implemented yet!\n" );
479 : /*
480 : // Write all properties!
481 : // Delete complete sets first.
482 : ClearNodeSet( SETNODE_NEWMENU );
483 : ClearNodeSet( SETNODE_WIZARDMENU );
484 : ClearNodeSet( SETNODE_HELPBOOKMARKS );
485 :
486 : MenuEntry aItem ;
487 : OUString sNode ;
488 : Sequence< PropertyValue > lPropertyValues( PROPERTYCOUNT );
489 : sal_uInt32 nItem = 0 ;
490 :
491 : // Copy "new" menu entries to save-list!
492 : sal_uInt32 nNewCount = m_aNewMenu.size();
493 : for( nItem=0; nItem<nNewCount; ++nItem )
494 : {
495 : aItem = m_aNewMenu[nItem];
496 : // Format: "New/1/URL"
497 : // "New/1/Title"
498 : // ...
499 : sNode = SETNODE_NEWMENU + PATHDELIMITER + PATHPREFIX + OUString::valueOf( (sal_Int32)nItem ) + PATHDELIMITER;
500 :
501 : lPropertyValues[OFFSET_URL ].Name = sNode + PROPERTYNAME_URL ;
502 : lPropertyValues[OFFSET_TITLE ].Name = sNode + PROPERTYNAME_TITLE ;
503 : lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Name = sNode + PROPERTYNAME_IMAGEIDENTIFIER ;
504 : lPropertyValues[OFFSET_TARGETNAME ].Name = sNode + PROPERTYNAME_TARGETNAME ;
505 :
506 : lPropertyValues[OFFSET_URL ].Value <<= aItem.sURL ;
507 : lPropertyValues[OFFSET_TITLE ].Value <<= aItem.sTitle ;
508 : lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Value <<= aItem.sImageIdentifier ;
509 : lPropertyValues[OFFSET_TARGETNAME ].Value <<= aItem.sTargetName ;
510 :
511 : SetSetProperties( SETNODE_NEWMENU, lPropertyValues );
512 : }
513 :
514 : // Copy "wizard" menu entries to save-list!
515 : sal_uInt32 nWizardCount = m_aWizardMenu.size();
516 : for( nItem=0; nItem<nWizardCount; ++nItem )
517 : {
518 : aItem = m_aWizardMenu[nItem];
519 : // Format: "Wizard/1/URL"
520 : // "Wizard/1/Title"
521 : // ...
522 : sNode = SETNODE_WIZARDMENU + PATHDELIMITER + PATHPREFIX + OUString::valueOf( (sal_Int32)nItem ) + PATHDELIMITER;
523 :
524 : lPropertyValues[OFFSET_URL ].Name = sNode + PROPERTYNAME_URL ;
525 : lPropertyValues[OFFSET_TITLE ].Name = sNode + PROPERTYNAME_TITLE ;
526 : lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Name = sNode + PROPERTYNAME_IMAGEIDENTIFIER ;
527 : lPropertyValues[OFFSET_TARGETNAME ].Name = sNode + PROPERTYNAME_TARGETNAME ;
528 :
529 : lPropertyValues[OFFSET_URL ].Value <<= aItem.sURL ;
530 : lPropertyValues[OFFSET_TITLE ].Value <<= aItem.sTitle ;
531 : lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Value <<= aItem.sImageIdentifier ;
532 : lPropertyValues[OFFSET_TARGETNAME ].Value <<= aItem.sTargetName ;
533 :
534 : SetSetProperties( SETNODE_WIZARDMENU, lPropertyValues );
535 : }
536 :
537 : // Copy help bookmarks entries to save-list!
538 : sal_uInt32 nHelpBookmarksCount = m_aHelpBookmarksMenu.size();
539 : for( nItem=0; nItem<nHelpBookmarksCount; ++nItem )
540 : {
541 : aItem = m_aHelpBookmarksMenu[nItem];
542 : // Format: "HelpBookmarks/1/URL"
543 : // "HelpBookmarks/1/Title"
544 : // ...
545 : sNode = SETNODE_HELPBOOKMARKS + PATHDELIMITER + PATHPREFIX + OUString::valueOf( (sal_Int32)nItem ) + PATHDELIMITER;
546 :
547 : lPropertyValues[OFFSET_URL ].Name = sNode + PROPERTYNAME_URL ;
548 : lPropertyValues[OFFSET_TITLE ].Name = sNode + PROPERTYNAME_TITLE ;
549 : lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Name = sNode + PROPERTYNAME_IMAGEIDENTIFIER ;
550 : lPropertyValues[OFFSET_TARGETNAME ].Name = sNode + PROPERTYNAME_TARGETNAME ;
551 :
552 : lPropertyValues[OFFSET_URL ].Value <<= aItem.sURL ;
553 : lPropertyValues[OFFSET_TITLE ].Value <<= aItem.sTitle ;
554 : lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Value <<= aItem.sImageIdentifier ;
555 : lPropertyValues[OFFSET_TARGETNAME ].Value <<= aItem.sTargetName ;
556 :
557 : SetSetProperties( SETNODE_HELPBOOKMARKS, lPropertyValues );
558 : }
559 : */
560 0 : }
561 :
562 : //*****************************************************************************************************************
563 : // public method
564 : //*****************************************************************************************************************
565 641 : Sequence< Sequence< PropertyValue > > SvtDynamicMenuOptions_Impl::GetMenu( EDynamicMenuType eMenu ) const
566 : {
567 641 : Sequence< Sequence< PropertyValue > > lReturn;
568 641 : switch( eMenu )
569 : {
570 : case E_NEWMENU : {
571 641 : lReturn = m_aNewMenu.GetList();
572 : }
573 641 : break;
574 :
575 : case E_WIZARDMENU : {
576 0 : lReturn = m_aWizardMenu.GetList();
577 : }
578 0 : break;
579 :
580 : case E_HELPBOOKMARKS : {
581 0 : lReturn = m_aHelpBookmarksMenu.GetList();
582 : }
583 0 : break;
584 : }
585 641 : return lReturn;
586 : }
587 :
588 : //*****************************************************************************************************************
589 : // private method
590 : //*****************************************************************************************************************
591 30 : Sequence< OUString > SvtDynamicMenuOptions_Impl::impl_GetPropertyNames( sal_uInt32& nNewCount, sal_uInt32& nWizardCount, sal_uInt32& nHelpBookmarksCount )
592 : {
593 : // First get ALL names of current existing list items in configuration!
594 30 : Sequence< OUString > lNewItems = GetNodeNames( SETNODE_NEWMENU );
595 60 : Sequence< OUString > lWizardItems = GetNodeNames( SETNODE_WIZARDMENU );
596 60 : Sequence< OUString > lHelpBookmarksItems = GetNodeNames( SETNODE_HELPBOOKMARKS );
597 :
598 : // Get information about list counts ...
599 30 : nNewCount = lNewItems.getLength ();
600 30 : nWizardCount = lWizardItems.getLength ();
601 30 : nHelpBookmarksCount = lHelpBookmarksItems.getLength();
602 :
603 : // Sort and expand all three list to result list ...
604 30 : Sequence< OUString > lProperties;
605 30 : impl_SortAndExpandPropertyNames( lNewItems , lProperties, SETNODE_NEWMENU );
606 30 : impl_SortAndExpandPropertyNames( lWizardItems , lProperties, SETNODE_WIZARDMENU );
607 30 : impl_SortAndExpandPropertyNames( lHelpBookmarksItems, lProperties, SETNODE_HELPBOOKMARKS );
608 :
609 : // Return result.
610 60 : return lProperties;
611 : }
612 :
613 : //*****************************************************************************************************************
614 : // private helper
615 : //*****************************************************************************************************************
616 : class CountWithPrefixSort
617 : {
618 : public:
619 2190 : int operator() ( const OUString& s1 ,
620 : const OUString& s2 ) const
621 : {
622 : // Get order numbers from entry name without prefix.
623 : // e.g. "m10" => 10
624 : // "m5" => 5
625 2190 : sal_Int32 n1 = s1.copy( 1, s1.getLength()-1 ).toInt32();
626 2190 : sal_Int32 n2 = s2.copy( 1, s2.getLength()-1 ).toInt32();
627 : // MUST be in [0,1] ... because it's a difference between
628 : // insert-positions of given entries in sorted list!
629 2190 : return( n1<n2 );
630 : }
631 : };
632 :
633 : class SelectByPrefix
634 : {
635 : public:
636 810 : bool operator() ( const OUString& s ) const
637 : {
638 : // Prefer setup written entries by check first letter of given string. It must be a "s".
639 810 : return( s.indexOf( PATHPREFIX_SETUP ) == 0 );
640 : }
641 : };
642 :
643 : //*****************************************************************************************************************
644 : // private method
645 : //*****************************************************************************************************************
646 90 : void SvtDynamicMenuOptions_Impl::impl_SortAndExpandPropertyNames( const Sequence< OUString >& lSource ,
647 : Sequence< OUString >& lDestination ,
648 : const OUString& sSetNode )
649 : {
650 90 : OUString sFixPath ;
651 180 : vector< OUString > lTemp ;
652 90 : sal_Int32 nSourceCount = lSource.getLength() ;
653 90 : sal_Int32 nDestinationStep = lDestination.getLength() ; // start on end of current list ...!
654 :
655 90 : lDestination.realloc( (nSourceCount*PROPERTYCOUNT)+nDestinationStep ); // get enough memory for copy operations after nDestination ...
656 :
657 : // Copy all items to temp. vector to use fast sort operations :-)
658 900 : for( sal_Int32 nSourceStep=0; nSourceStep<nSourceCount; ++nSourceStep )
659 810 : lTemp.push_back( lSource[nSourceStep] );
660 :
661 : // Sort all entries by number ...
662 90 : stable_sort( lTemp.begin(), lTemp.end(), CountWithPrefixSort() );
663 : // and split into setup & user written entries!
664 90 : stable_partition( lTemp.begin(), lTemp.end(), SelectByPrefix() );
665 :
666 : // Copy sorted entries to destination and expand every item with
667 : // 4 supported sub properties.
668 2700 : for( vector< OUString >::const_iterator pItem =lTemp.begin() ;
669 1800 : pItem!=lTemp.end() ;
670 : ++pItem )
671 : {
672 810 : sFixPath = sSetNode ;
673 810 : sFixPath += PATHDELIMITER ;
674 810 : sFixPath += *pItem ;
675 810 : sFixPath += PATHDELIMITER ;
676 :
677 810 : lDestination[nDestinationStep] = sFixPath ;
678 810 : lDestination[nDestinationStep] += PROPERTYNAME_URL ;
679 810 : ++nDestinationStep;
680 810 : lDestination[nDestinationStep] = sFixPath ;
681 810 : lDestination[nDestinationStep] += PROPERTYNAME_TITLE ;
682 810 : ++nDestinationStep;
683 810 : lDestination[nDestinationStep] = sFixPath ;
684 810 : lDestination[nDestinationStep] += PROPERTYNAME_IMAGEIDENTIFIER ;
685 810 : ++nDestinationStep;
686 810 : lDestination[nDestinationStep] = sFixPath ;
687 810 : lDestination[nDestinationStep] += PROPERTYNAME_TARGETNAME ;
688 810 : ++nDestinationStep;
689 90 : }
690 90 : }
691 :
692 : //*****************************************************************************************************************
693 : // initialize static member
694 : // DON'T DO IT IN YOUR HEADER!
695 : // see definition for further information
696 : //*****************************************************************************************************************
697 : SvtDynamicMenuOptions_Impl* SvtDynamicMenuOptions::m_pDataContainer = NULL ;
698 : sal_Int32 SvtDynamicMenuOptions::m_nRefCount = 0 ;
699 :
700 : //*****************************************************************************************************************
701 : // constructor
702 : //*****************************************************************************************************************
703 671 : SvtDynamicMenuOptions::SvtDynamicMenuOptions()
704 : {
705 : // Global access, must be guarded (multithreading!).
706 671 : MutexGuard aGuard( GetOwnStaticMutex() );
707 : // Increase ouer refcount ...
708 671 : ++m_nRefCount;
709 : // ... and initialize ouer data container only if it not already exist!
710 671 : if( m_pDataContainer == NULL )
711 : {
712 30 : m_pDataContainer = new SvtDynamicMenuOptions_Impl;
713 30 : ItemHolder1::holdConfigItem(E_DYNAMICMENUOPTIONS);
714 671 : }
715 671 : }
716 :
717 : //*****************************************************************************************************************
718 : // destructor
719 : //*****************************************************************************************************************
720 1372 : SvtDynamicMenuOptions::~SvtDynamicMenuOptions()
721 : {
722 : // Global access, must be guarded (multithreading!)
723 671 : MutexGuard aGuard( GetOwnStaticMutex() );
724 : // Decrease ouer refcount.
725 671 : --m_nRefCount;
726 : // If last instance was deleted ...
727 : // we must destroy ouer static data container!
728 671 : if( m_nRefCount <= 0 )
729 : {
730 30 : delete m_pDataContainer;
731 30 : m_pDataContainer = NULL;
732 671 : }
733 701 : }
734 :
735 : //*****************************************************************************************************************
736 : // public method
737 : //*****************************************************************************************************************
738 641 : Sequence< Sequence< PropertyValue > > SvtDynamicMenuOptions::GetMenu( EDynamicMenuType eMenu ) const
739 : {
740 641 : MutexGuard aGuard( GetOwnStaticMutex() );
741 641 : return m_pDataContainer->GetMenu( eMenu );
742 : }
743 :
744 : namespace
745 : {
746 : class theDynamicMenuOptionsMutex : public rtl::Static<osl::Mutex, theDynamicMenuOptionsMutex>{};
747 : }
748 :
749 : //*****************************************************************************************************************
750 : // private method
751 : //*****************************************************************************************************************
752 1983 : Mutex& SvtDynamicMenuOptions::GetOwnStaticMutex()
753 : {
754 1983 : return theDynamicMenuOptionsMutex::get();
755 : }
756 :
757 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|