| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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; |
| } |