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