diff options
Diffstat (limited to 'unotools/source/config/dynamicmenuoptions.cxx')
-rw-r--r-- | unotools/source/config/dynamicmenuoptions.cxx | 923 |
1 files changed, 923 insertions, 0 deletions
diff --git a/unotools/source/config/dynamicmenuoptions.cxx b/unotools/source/config/dynamicmenuoptions.cxx new file mode 100644 index 000000000000..d3fca4350a67 --- /dev/null +++ b/unotools/source/config/dynamicmenuoptions.cxx @@ -0,0 +1,923 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: dynamicmenuoptions.cxx,v $ + * $Revision: 1.18 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_unotools.hxx" +#ifndef GCC +#endif + +//_________________________________________________________________________________________________________________ +// includes +//_________________________________________________________________________________________________________________ + +#include <unotools/dynamicmenuoptions.hxx> +#include <unotools/moduleoptions.hxx> +#include <unotools/configmgr.hxx> +#include <unotools/configitem.hxx> +#include <tools/debug.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Sequence.hxx> + +#ifndef __SGI_STL_VECTOR +#include <vector> +#endif + +#include <itemholder1.hxx> + +#include <algorithm> + +//_________________________________________________________________________________________________________________ +// namespaces +//_________________________________________________________________________________________________________________ + +using namespace ::std ; +using namespace ::utl ; +using namespace ::rtl ; +using namespace ::osl ; +using namespace ::com::sun::star::uno ; +using namespace ::com::sun::star::beans ; + +//_________________________________________________________________________________________________________________ +// const +//_________________________________________________________________________________________________________________ + +#define ROOTNODE_MENUS OUString(RTL_CONSTASCII_USTRINGPARAM("Office.Common/Menus/" )) +#define PATHDELIMITER OUString(RTL_CONSTASCII_USTRINGPARAM("/" )) + +#define SETNODE_NEWMENU OUString(RTL_CONSTASCII_USTRINGPARAM("New" )) +#define SETNODE_WIZARDMENU OUString(RTL_CONSTASCII_USTRINGPARAM("Wizard" )) +#define SETNODE_HELPBOOKMARKS OUString(RTL_CONSTASCII_USTRINGPARAM("HelpBookmarks" )) + +#define PROPERTYNAME_URL DYNAMICMENU_PROPERTYNAME_URL +#define PROPERTYNAME_TITLE DYNAMICMENU_PROPERTYNAME_TITLE +#define PROPERTYNAME_IMAGEIDENTIFIER DYNAMICMENU_PROPERTYNAME_IMAGEIDENTIFIER +#define PROPERTYNAME_TARGETNAME DYNAMICMENU_PROPERTYNAME_TARGETNAME + +#define PROPERTYCOUNT 4 + +#define OFFSET_URL 0 +#define OFFSET_TITLE 1 +#define OFFSET_IMAGEIDENTIFIER 2 +#define OFFSET_TARGETNAME 3 + +#define PATHPREFIX_SETUP OUString(RTL_CONSTASCII_USTRINGPARAM("m" )) +#define PATHPREFIX_USER OUString(RTL_CONSTASCII_USTRINGPARAM("u" )) + +//_________________________________________________________________________________________________________________ +// private declarations! +//_________________________________________________________________________________________________________________ + +/*-**************************************************************************************************************** + @descr struct to hold information about one menu entry. +****************************************************************************************************************-*/ +struct SvtDynMenuEntry +{ + public: + SvtDynMenuEntry() {}; + + SvtDynMenuEntry( const OUString& sNewURL , + const OUString& sNewTitle , + const OUString& sNewImageIdentifier , + const OUString& sNewTargetName ) + { + sURL = sNewURL ; + sTitle = sNewTitle ; + sImageIdentifier = sNewImageIdentifier ; + sTargetName = sNewTargetName ; + } + + public: + OUString sName ; + OUString sURL ; + OUString sTitle ; + OUString sImageIdentifier ; + OUString sTargetName ; +}; + +/*-**************************************************************************************************************** + @descr support simple menu structures and operations on it +****************************************************************************************************************-*/ +class SvtDynMenu +{ + public: + //--------------------------------------------------------------------------------------------------------- + // append setup written menu entry + // Don't touch name of entry. It was defined by setup and must be the same everytime! + // Look for double menu entries here too ... may be some seperator items are supeflous ... + void AppendSetupEntry( const SvtDynMenuEntry& rEntry ) + { + if( + ( lSetupEntries.size() < 1 ) || + ( lSetupEntries.rbegin()->sURL != rEntry.sURL ) + ) + { + lSetupEntries.push_back( rEntry ); + } + } + + //--------------------------------------------------------------------------------------------------------- + // append user specific menu entry + // We must find unique name for it by using special prefix + // and next count of user setted entries! + // Look for double menu entries here too ... may be some seperator items are supeflous ... + void AppendUserEntry( SvtDynMenuEntry& rEntry ) + { + if( + ( lUserEntries.size() < 1 ) || + ( lUserEntries.rbegin()->sURL != rEntry.sURL ) + ) + { + rEntry.sName = PATHPREFIX_USER; + rEntry.sName += OUString::valueOf( (sal_Int32)impl_getNextUserEntryNr() ); + lUserEntries.push_back( rEntry ); + } + } + + //--------------------------------------------------------------------------------------------------------- + // the only way to free memory! + void Clear() + { + lSetupEntries.clear(); + lUserEntries.clear(); + } + + //--------------------------------------------------------------------------------------------------------- + // convert internal list to external format + // for using it on right menus realy + // Notice: We build a property list with 4 entries and set it on result list then. + // The while-loop starts with pointer on internal member list lSetupEntries, change to + // lUserEntries then and stop after that with NULL! + // Separator entries will be packed in another way then normal entries! We define + // special strings "sEmpty" and "sSeperator" to perform too ... + Sequence< Sequence< PropertyValue > > GetList() const + { + sal_Int32 nSetupCount = (sal_Int32)lSetupEntries.size(); + sal_Int32 nUserCount = (sal_Int32)lUserEntries.size(); + sal_Int32 nStep = 0; + Sequence< PropertyValue > lProperties ( PROPERTYCOUNT ); + Sequence< Sequence< PropertyValue > > lResult ( nSetupCount+nUserCount ); + OUString sSeperator ( RTL_CONSTASCII_USTRINGPARAM("private:separator") ); + OUString sEmpty ; + const vector< SvtDynMenuEntry >* pList = &lSetupEntries; + + lProperties[OFFSET_URL ].Name = PROPERTYNAME_URL ; + lProperties[OFFSET_TITLE ].Name = PROPERTYNAME_TITLE ; + lProperties[OFFSET_IMAGEIDENTIFIER].Name = PROPERTYNAME_IMAGEIDENTIFIER ; + lProperties[OFFSET_TARGETNAME ].Name = PROPERTYNAME_TARGETNAME ; + + while( pList != NULL ) + { + for( vector< SvtDynMenuEntry >::const_iterator pItem =pList->begin(); + pItem!=pList->end() ; + ++pItem ) + { + if( pItem->sURL == sSeperator ) + { + lProperties[OFFSET_URL ].Value <<= sSeperator ; + lProperties[OFFSET_TITLE ].Value <<= sEmpty ; + lProperties[OFFSET_IMAGEIDENTIFIER ].Value <<= sEmpty ; + lProperties[OFFSET_TARGETNAME ].Value <<= sEmpty ; + } + else + { + lProperties[OFFSET_URL ].Value <<= pItem->sURL ; + lProperties[OFFSET_TITLE ].Value <<= pItem->sTitle ; + lProperties[OFFSET_IMAGEIDENTIFIER ].Value <<= pItem->sImageIdentifier; + lProperties[OFFSET_TARGETNAME ].Value <<= pItem->sTargetName ; + } + lResult[nStep] = lProperties; + ++nStep; + } + if( pList == &lSetupEntries ) + pList = &lUserEntries; + else + pList = NULL; + } + return lResult; + } + + private: + //--------------------------------------------------------------------------------------------------------- + // search for an entry named "ux" with x=[0..i] inside our menu + // which has set highest number x. So we can add another user entry. + sal_Int32 impl_getNextUserEntryNr() const + { + sal_Int32 nNr = 0; + for( vector< SvtDynMenuEntry >::const_iterator pItem =lUserEntries.begin(); + pItem!=lUserEntries.end() ; + ++pItem ) + { + if( pItem->sName.compareTo( PATHPREFIX_USER, 1 ) == 0 ) + { + OUString sNr = pItem->sName.copy( 1, pItem->sName.getLength()-1 ); + sal_Int32 nCheckNr = sNr.toInt32(); + if( nCheckNr > nNr ) + nNr = nCheckNr; + } + } + // Attention: Code isn't prepared for recyling of unused fragmented numbers! + // If we reach end of sal_Int32 range ... we must stop further working ... + // But I think nobody expand a menu to more then 1000 ... 100000 ... entries ... or? + DBG_ASSERT( !(nNr>0x7fffffff), "Menu::impl_getNextUserEntryNr()\nUser count can be out of range next time ...\n" ); + return nNr; + } + + private: + vector< SvtDynMenuEntry > lSetupEntries; + vector< SvtDynMenuEntry > lUserEntries ; +}; + +class SvtDynamicMenuOptions_Impl : public ConfigItem +{ + //------------------------------------------------------------------------------------------------------------- + // public methods + //------------------------------------------------------------------------------------------------------------- + + public: + + //--------------------------------------------------------------------------------------------------------- + // constructor / destructor + //--------------------------------------------------------------------------------------------------------- + + SvtDynamicMenuOptions_Impl(); + ~SvtDynamicMenuOptions_Impl(); + + //--------------------------------------------------------------------------------------------------------- + // overloaded methods of baseclass + //--------------------------------------------------------------------------------------------------------- + + /*-****************************************************************************************************//** + @short called for notify of configmanager + @descr These method is called from the ConfigManager before application ends or from the + PropertyChangeListener if the sub tree broadcasts changes. You must update your + internal values. + + @seealso baseclass ConfigItem + + @param "lPropertyNames" is the list of properties which should be updated. + @return - + + @onerror - + *//*-*****************************************************************************************************/ + + virtual void Notify( const Sequence< OUString >& lPropertyNames ); + + /*-****************************************************************************************************//** + @short write changes to configuration + @descr These method writes the changed values into the sub tree + and should always called in our destructor to guarantee consistency of config data. + + @seealso baseclass ConfigItem + + @param - + @return - + + @onerror - + *//*-*****************************************************************************************************/ + + virtual void Commit(); + + //--------------------------------------------------------------------------------------------------------- + // public interface + //--------------------------------------------------------------------------------------------------------- + + /*-****************************************************************************************************//** + @short base implementation of public interface for "SvtDynamicMenuOptions"! + @descr These class is used as static member of "SvtDynamicMenuOptions" ... + => The code exist only for one time and isn't duplicated for every instance! + + @seealso - + + @param - + @return - + + @onerror - + *//*-*****************************************************************************************************/ + + void Clear ( EDynamicMenuType eMenu ); + Sequence< Sequence< PropertyValue > > GetMenu ( EDynamicMenuType eMenu ) const ; + void AppendItem ( EDynamicMenuType eMenu , + const OUString& sURL , + const OUString& sTitle , + const OUString& sImageIdentifier, + const OUString& sTargetName ); + + //------------------------------------------------------------------------------------------------------------- + // private methods + //------------------------------------------------------------------------------------------------------------- + + private: + + /*-****************************************************************************************************//** + @short return list of key names of our configuration management which represent oue module tree + @descr These methods return the current list of key names! We need it to get needed values from our + configuration management and support dynamical menu item lists! + + @seealso - + + @param "nNewCount" , returns count of menu entries for "new" + @param "nWizardCount" , returns count of menu entries for "wizard" + @return A list of configuration key names is returned. + + @onerror - + *//*-*****************************************************************************************************/ + + Sequence< OUString > impl_GetPropertyNames( sal_uInt32& nNewCount, sal_uInt32& nWizardCount, sal_uInt32& nHelpBookmarksCount ); + + /*-****************************************************************************************************//** + @short sort given source list and expand it for all well known properties to destination + @descr We must support sets of entries with count inside the name .. but some of them could be missing! + e.g. s1-s2-s3-s0-u1-s6-u5-u7 + Then we must sort it by name and expand it to the follow one: + sSetNode/s0/URL + sSetNode/s0/Title + sSetNode/s0/... + sSetNode/s1/URL + sSetNode/s1/Title + sSetNode/s1/... + ... + sSetNode/s6/URL + sSetNode/s6/Title + sSetNode/s6/... + sSetNode/u1/URL + sSetNode/u1/Title + sSetNode/u1/... + ... + sSetNode/u7/URL + sSetNode/u7/Title + sSetNode/u7/... + Rules: We start with all setup written entries names "sx" and x=[0..n]. + Then we handle all "ux" items. Inside these blocks we sort it ascending by number. + + @attention We add these expanded list to the end of given "lDestination" list! + So we must start on "lDestination.getLength()". + Reallocation of memory of destination list is done by us! + + @seealso method impl_GetPropertyNames() + + @param "lSource" , original list (e.g. [m1-m2-m3-m6-m0] ) + @param "lDestination" , destination of operation + @param "sSetNode" , name of configuration set to build complete path + @return A list of configuration key names is returned. + + @onerror - + *//*-*****************************************************************************************************/ + + void impl_SortAndExpandPropertyNames( const Sequence< OUString >& lSource , + Sequence< OUString >& lDestination , + const OUString& sSetNode ); + + //------------------------------------------------------------------------------------------------------------- + // private member + //------------------------------------------------------------------------------------------------------------- + + private: + + SvtDynMenu m_aNewMenu ; + SvtDynMenu m_aWizardMenu ; + SvtDynMenu m_aHelpBookmarksMenu ; +}; + +//_________________________________________________________________________________________________________________ +// definitions +//_________________________________________________________________________________________________________________ + +//***************************************************************************************************************** +// constructor +//***************************************************************************************************************** +SvtDynamicMenuOptions_Impl::SvtDynamicMenuOptions_Impl() + // Init baseclasses first + : ConfigItem( ROOTNODE_MENUS ) + // Init member then... +{ + // Get names and values of all accessable menu entries and fill internal structures. + // See impl_GetPropertyNames() for further informations. + sal_uInt32 nNewCount = 0; + sal_uInt32 nWizardCount = 0; + sal_uInt32 nHelpBookmarksCount = 0; + Sequence< OUString > lNames = impl_GetPropertyNames ( nNewCount , + nWizardCount , + nHelpBookmarksCount ); + Sequence< Any > lValues = GetProperties ( lNames ); + + // Safe impossible cases. + // We need values from ALL configuration keys. + // Follow assignment use order of values in relation to our list of key names! + DBG_ASSERT( !(lNames.getLength()!=lValues.getLength()), "SvtDynamicMenuOptions_Impl::SvtDynamicMenuOptions_Impl()\nI miss some values of configuration keys!\n" ); + + // Copy values from list in right order to ouer internal member. + // Attention: List for names and values have an internal construction pattern! + // + // first "New" menu ... + // Name Value + // /New/1/URL "private:factory/swriter" + // /New/1/Title "Neues Writer Dokument" + // /New/1/ImageIdentifier "icon_writer" + // /New/1/TargetName "_blank" + // + // /New/2/URL "private:factory/scalc" + // /New/2/Title "Neues Calc Dokument" + // /New/2/ImageIdentifier "icon_calc" + // /New/2/TargetName "_blank" + // + // second "Wizard" menu ... + // /Wizard/1/URL "file://b" + // /Wizard/1/Title "MalWas" + // /Wizard/1/ImageIdentifier "icon_?" + // /Wizard/1/TargetName "_self" + // + // ... and so on ... + + sal_uInt32 nItem = 0 ; + sal_uInt32 nPosition = 0 ; + OUString sName ; + + // We must use these one instance object(!) to get information about installed modules. + // These information are used to filter menu entries wich need not installed modules ... + // Such entries shouldnt be available then! + // see impl_IsEntrySupported() too + SvtModuleOptions aModuleOptions; + + // Get names/values for new menu. + // 4 subkeys for every item! + for( nItem=0; nItem<nNewCount; ++nItem ) + { + SvtDynMenuEntry aItem ; + lValues[nPosition] >>= aItem.sURL ; + ++nPosition; + lValues[nPosition] >>= aItem.sTitle ; + ++nPosition; + lValues[nPosition] >>= aItem.sImageIdentifier ; + ++nPosition; + lValues[nPosition] >>= aItem.sTargetName ; + ++nPosition; + m_aNewMenu.AppendSetupEntry( aItem ); + } + + // Attention: Don't reset nPosition here! + + // Get names/values for wizard menu. + // 4 subkeys for every item! + for( nItem=0; nItem<nWizardCount; ++nItem ) + { + SvtDynMenuEntry aItem ; + lValues[nPosition] >>= aItem.sURL ; + ++nPosition; + lValues[nPosition] >>= aItem.sTitle ; + ++nPosition; + lValues[nPosition] >>= aItem.sImageIdentifier ; + ++nPosition; + lValues[nPosition] >>= aItem.sTargetName ; + ++nPosition; + m_aWizardMenu.AppendSetupEntry( aItem ); + } + + // Attention: Don't reset nPosition here! + + // Get names/values for wizard menu. + // 4 subkeys for every item! + for( nItem=0; nItem<nHelpBookmarksCount; ++nItem ) + { + SvtDynMenuEntry aItem ; + lValues[nPosition] >>= aItem.sURL ; + ++nPosition; + lValues[nPosition] >>= aItem.sTitle ; + ++nPosition; + lValues[nPosition] >>= aItem.sImageIdentifier ; + ++nPosition; + lValues[nPosition] >>= aItem.sTargetName ; + ++nPosition; + m_aHelpBookmarksMenu.AppendSetupEntry( aItem ); + } + +/*TODO: Not used in the moment! see Notify() ... + // Enable notification mechanism of ouer baseclass. + // We need it to get information about changes outside these class on ouer used configuration keys! + EnableNotification( lNames ); +*/ +} + +//***************************************************************************************************************** +// destructor +//***************************************************************************************************************** +SvtDynamicMenuOptions_Impl::~SvtDynamicMenuOptions_Impl() +{ + // We must save our current values .. if user forget it! + if( IsModified() == sal_True ) + { + Commit(); + } +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +void SvtDynamicMenuOptions_Impl::Notify( const Sequence< OUString >& ) +{ + 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" ); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +void SvtDynamicMenuOptions_Impl::Commit() +{ + DBG_ERROR( "SvtDynamicMenuOptions_Impl::Commit()\nNot implemented yet!\n" ); + /* + // Write all properties! + // Delete complete sets first. + ClearNodeSet( SETNODE_NEWMENU ); + ClearNodeSet( SETNODE_WIZARDMENU ); + ClearNodeSet( SETNODE_HELPBOOKMARKS ); + + MenuEntry aItem ; + OUString sNode ; + Sequence< PropertyValue > lPropertyValues( PROPERTYCOUNT ); + sal_uInt32 nItem = 0 ; + + // Copy "new" menu entries to save-list! + sal_uInt32 nNewCount = m_aNewMenu.size(); + for( nItem=0; nItem<nNewCount; ++nItem ) + { + aItem = m_aNewMenu[nItem]; + // Format: "New/1/URL" + // "New/1/Title" + // ... + sNode = SETNODE_NEWMENU + PATHDELIMITER + PATHPREFIX + OUString::valueOf( (sal_Int32)nItem ) + PATHDELIMITER; + + lPropertyValues[OFFSET_URL ].Name = sNode + PROPERTYNAME_URL ; + lPropertyValues[OFFSET_TITLE ].Name = sNode + PROPERTYNAME_TITLE ; + lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Name = sNode + PROPERTYNAME_IMAGEIDENTIFIER ; + lPropertyValues[OFFSET_TARGETNAME ].Name = sNode + PROPERTYNAME_TARGETNAME ; + + lPropertyValues[OFFSET_URL ].Value <<= aItem.sURL ; + lPropertyValues[OFFSET_TITLE ].Value <<= aItem.sTitle ; + lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Value <<= aItem.sImageIdentifier ; + lPropertyValues[OFFSET_TARGETNAME ].Value <<= aItem.sTargetName ; + + SetSetProperties( SETNODE_NEWMENU, lPropertyValues ); + } + + // Copy "wizard" menu entries to save-list! + sal_uInt32 nWizardCount = m_aWizardMenu.size(); + for( nItem=0; nItem<nWizardCount; ++nItem ) + { + aItem = m_aWizardMenu[nItem]; + // Format: "Wizard/1/URL" + // "Wizard/1/Title" + // ... + sNode = SETNODE_WIZARDMENU + PATHDELIMITER + PATHPREFIX + OUString::valueOf( (sal_Int32)nItem ) + PATHDELIMITER; + + lPropertyValues[OFFSET_URL ].Name = sNode + PROPERTYNAME_URL ; + lPropertyValues[OFFSET_TITLE ].Name = sNode + PROPERTYNAME_TITLE ; + lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Name = sNode + PROPERTYNAME_IMAGEIDENTIFIER ; + lPropertyValues[OFFSET_TARGETNAME ].Name = sNode + PROPERTYNAME_TARGETNAME ; + + lPropertyValues[OFFSET_URL ].Value <<= aItem.sURL ; + lPropertyValues[OFFSET_TITLE ].Value <<= aItem.sTitle ; + lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Value <<= aItem.sImageIdentifier ; + lPropertyValues[OFFSET_TARGETNAME ].Value <<= aItem.sTargetName ; + + SetSetProperties( SETNODE_WIZARDMENU, lPropertyValues ); + } + + // Copy help bookmarks entries to save-list! + sal_uInt32 nHelpBookmarksCount = m_aHelpBookmarksMenu.size(); + for( nItem=0; nItem<nHelpBookmarksCount; ++nItem ) + { + aItem = m_aHelpBookmarksMenu[nItem]; + // Format: "HelpBookmarks/1/URL" + // "HelpBookmarks/1/Title" + // ... + sNode = SETNODE_HELPBOOKMARKS + PATHDELIMITER + PATHPREFIX + OUString::valueOf( (sal_Int32)nItem ) + PATHDELIMITER; + + lPropertyValues[OFFSET_URL ].Name = sNode + PROPERTYNAME_URL ; + lPropertyValues[OFFSET_TITLE ].Name = sNode + PROPERTYNAME_TITLE ; + lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Name = sNode + PROPERTYNAME_IMAGEIDENTIFIER ; + lPropertyValues[OFFSET_TARGETNAME ].Name = sNode + PROPERTYNAME_TARGETNAME ; + + lPropertyValues[OFFSET_URL ].Value <<= aItem.sURL ; + lPropertyValues[OFFSET_TITLE ].Value <<= aItem.sTitle ; + lPropertyValues[OFFSET_IMAGEIDENTIFIER ].Value <<= aItem.sImageIdentifier ; + lPropertyValues[OFFSET_TARGETNAME ].Value <<= aItem.sTargetName ; + + SetSetProperties( SETNODE_HELPBOOKMARKS, lPropertyValues ); + } + */ +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +void SvtDynamicMenuOptions_Impl::Clear( EDynamicMenuType eMenu ) +{ + switch( eMenu ) + { + case E_NEWMENU : { + m_aNewMenu.Clear(); + SetModified(); + } + break; + + case E_WIZARDMENU : { + m_aWizardMenu.Clear(); + SetModified(); + } + break; + + case E_HELPBOOKMARKS : { + m_aHelpBookmarksMenu.Clear(); + SetModified(); + } + break; + } +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +Sequence< Sequence< PropertyValue > > SvtDynamicMenuOptions_Impl::GetMenu( EDynamicMenuType eMenu ) const +{ + Sequence< Sequence< PropertyValue > > lReturn; + switch( eMenu ) + { + case E_NEWMENU : { + lReturn = m_aNewMenu.GetList(); + } + break; + + case E_WIZARDMENU : { + lReturn = m_aWizardMenu.GetList(); + } + break; + + case E_HELPBOOKMARKS : { + lReturn = m_aHelpBookmarksMenu.GetList(); + } + break; + } + return lReturn; +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +void SvtDynamicMenuOptions_Impl::AppendItem( EDynamicMenuType eMenu , + const OUString& sURL , + const OUString& sTitle , + const OUString& sImageIdentifier, + const OUString& sTargetName ) +{ + SvtDynMenuEntry aItem( sURL, sTitle, sImageIdentifier, sTargetName ); + + switch( eMenu ) + { + case E_NEWMENU : { + m_aNewMenu.AppendUserEntry( aItem ); + SetModified(); + } + break; + + case E_WIZARDMENU : { + m_aWizardMenu.AppendUserEntry( aItem ); + SetModified(); + } + break; + + case E_HELPBOOKMARKS : { + m_aHelpBookmarksMenu.AppendUserEntry( aItem ); + SetModified(); + } + break; + } +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +Sequence< OUString > SvtDynamicMenuOptions_Impl::impl_GetPropertyNames( sal_uInt32& nNewCount, sal_uInt32& nWizardCount, sal_uInt32& nHelpBookmarksCount ) +{ + // First get ALL names of current existing list items in configuration! + Sequence< OUString > lNewItems = GetNodeNames( SETNODE_NEWMENU ); + Sequence< OUString > lWizardItems = GetNodeNames( SETNODE_WIZARDMENU ); + Sequence< OUString > lHelpBookmarksItems = GetNodeNames( SETNODE_HELPBOOKMARKS ); + + // Get information about list counts ... + nNewCount = lNewItems.getLength (); + nWizardCount = lWizardItems.getLength (); + nHelpBookmarksCount = lHelpBookmarksItems.getLength(); + + // Sort and expand all three list to result list ... + Sequence< OUString > lProperties; + impl_SortAndExpandPropertyNames( lNewItems , lProperties, SETNODE_NEWMENU ); + impl_SortAndExpandPropertyNames( lWizardItems , lProperties, SETNODE_WIZARDMENU ); + impl_SortAndExpandPropertyNames( lHelpBookmarksItems, lProperties, SETNODE_HELPBOOKMARKS ); + + // Return result. + return lProperties; +} + +//***************************************************************************************************************** +// private helper +//***************************************************************************************************************** +class CountWithPrefixSort +{ + public: + int operator() ( const OUString& s1 , + const OUString& s2 ) const + { + // Get order numbers from entry name without prefix. + // e.g. "m10" => 10 + // "m5" => 5 + sal_Int32 n1 = s1.copy( 1, s1.getLength()-1 ).toInt32(); + sal_Int32 n2 = s2.copy( 1, s2.getLength()-1 ).toInt32(); + // MUST be in [0,1] ... because it's a difference between + // insert-positions of given entries in sorted list! + return( n1<n2 ); + } +}; + +class SelectByPrefix +{ + public: + bool operator() ( const OUString& s ) const + { + // Prefer setup written entries by check first letter of given string. It must be a "s". + return( s.indexOf( PATHPREFIX_SETUP ) == 0 ); + } +}; + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +void SvtDynamicMenuOptions_Impl::impl_SortAndExpandPropertyNames( const Sequence< OUString >& lSource , + Sequence< OUString >& lDestination , + const OUString& sSetNode ) +{ + OUString sFixPath ; + vector< OUString > lTemp ; + sal_Int32 nSourceCount = lSource.getLength() ; + sal_Int32 nDestinationStep = lDestination.getLength() ; // start on end of current list ...! + + lDestination.realloc( (nSourceCount*PROPERTYCOUNT)+nDestinationStep ); // get enough memory for copy operations after nDestination ... + + // Copy all items to temp. vector to use fast sort operations :-) + for( sal_Int32 nSourceStep=0; nSourceStep<nSourceCount; ++nSourceStep ) + lTemp.push_back( lSource[nSourceStep] ); + + // Sort all entries by number ... + stable_sort( lTemp.begin(), lTemp.end(), CountWithPrefixSort() ); + // and split into setup & user written entries! + stable_partition( lTemp.begin(), lTemp.end(), SelectByPrefix() ); + + // Copy sorted entries to destination and expand every item with + // 4 supported sub properties. + for( vector< OUString >::const_iterator pItem =lTemp.begin() ; + pItem!=lTemp.end() ; + ++pItem ) + { + sFixPath = sSetNode ; + sFixPath += PATHDELIMITER ; + sFixPath += *pItem ; + sFixPath += PATHDELIMITER ; + + lDestination[nDestinationStep] = sFixPath ; + lDestination[nDestinationStep] += PROPERTYNAME_URL ; + ++nDestinationStep; + lDestination[nDestinationStep] = sFixPath ; + lDestination[nDestinationStep] += PROPERTYNAME_TITLE ; + ++nDestinationStep; + lDestination[nDestinationStep] = sFixPath ; + lDestination[nDestinationStep] += PROPERTYNAME_IMAGEIDENTIFIER ; + ++nDestinationStep; + lDestination[nDestinationStep] = sFixPath ; + lDestination[nDestinationStep] += PROPERTYNAME_TARGETNAME ; + ++nDestinationStep; + } +} + +//***************************************************************************************************************** +// initialize static member +// DON'T DO IT IN YOUR HEADER! +// see definition for further informations +//***************************************************************************************************************** +SvtDynamicMenuOptions_Impl* SvtDynamicMenuOptions::m_pDataContainer = NULL ; +sal_Int32 SvtDynamicMenuOptions::m_nRefCount = 0 ; + +//***************************************************************************************************************** +// constructor +//***************************************************************************************************************** +SvtDynamicMenuOptions::SvtDynamicMenuOptions() +{ + // Global access, must be guarded (multithreading!). + MutexGuard aGuard( GetOwnStaticMutex() ); + // Increase ouer refcount ... + ++m_nRefCount; + // ... and initialize ouer data container only if it not already exist! + if( m_pDataContainer == NULL ) + { + m_pDataContainer = new SvtDynamicMenuOptions_Impl; + ItemHolder1::holdConfigItem(E_DYNAMICMENUOPTIONS); + } +} + +//***************************************************************************************************************** +// destructor +//***************************************************************************************************************** +SvtDynamicMenuOptions::~SvtDynamicMenuOptions() +{ + // Global access, must be guarded (multithreading!) + MutexGuard aGuard( GetOwnStaticMutex() ); + // Decrease ouer refcount. + --m_nRefCount; + // If last instance was deleted ... + // we must destroy ouer static data container! + if( m_nRefCount <= 0 ) + { + delete m_pDataContainer; + m_pDataContainer = NULL; + } +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +void SvtDynamicMenuOptions::Clear( EDynamicMenuType eMenu ) +{ + MutexGuard aGuard( GetOwnStaticMutex() ); + m_pDataContainer->Clear( eMenu ); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +Sequence< Sequence< PropertyValue > > SvtDynamicMenuOptions::GetMenu( EDynamicMenuType eMenu ) const +{ + MutexGuard aGuard( GetOwnStaticMutex() ); + return m_pDataContainer->GetMenu( eMenu ); +} + +//***************************************************************************************************************** +// public method +//***************************************************************************************************************** +void SvtDynamicMenuOptions::AppendItem( EDynamicMenuType eMenu , + const OUString& sURL , + const OUString& sTitle , + const OUString& sImageIdentifier, + const OUString& sTargetName ) +{ + MutexGuard aGuard( GetOwnStaticMutex() ); + m_pDataContainer->AppendItem( eMenu, sURL, sTitle, sImageIdentifier, sTargetName ); +} + +//***************************************************************************************************************** +// private method +//***************************************************************************************************************** +Mutex& SvtDynamicMenuOptions::GetOwnStaticMutex() +{ + // Initialize static mutex only for one time! + static Mutex* pMutex = NULL; + // If these method first called (Mutex not already exist!) ... + if( pMutex == NULL ) + { + // ... we must create a new one. Protect follow code with the global mutex - + // It must be - we create a static variable! + MutexGuard aGuard( Mutex::getGlobalMutex() ); + // We must check our pointer again - because it can be that another instance of ouer class will be fastr then these! + if( pMutex == NULL ) + { + // Create the new mutex and set it for return on static variable. + static Mutex aMutex; + pMutex = &aMutex; + } + } + // Return new created or already existing mutex object. + return *pMutex; +} |