diff options
Diffstat (limited to 'svx/source/smarttags/SmartTagMgr.cxx')
-rw-r--r-- | svx/source/smarttags/SmartTagMgr.cxx | 552 |
1 files changed, 552 insertions, 0 deletions
diff --git a/svx/source/smarttags/SmartTagMgr.cxx b/svx/source/smarttags/SmartTagMgr.cxx new file mode 100644 index 000000000000..0070646b3330 --- /dev/null +++ b/svx/source/smarttags/SmartTagMgr.cxx @@ -0,0 +1,552 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * 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. + * + ************************************************************************/ + +// SMARTTAGS + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svx.hxx" +#include <svx/SmartTagMgr.hxx> + +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#include <com/sun/star/smarttags/XSmartTagRecognizer.hpp> +#include <com/sun/star/smarttags/XSmartTagAction.hpp> +#include <com/sun/star/deployment/ExtensionManager.hpp> +#include <com/sun/star/text/XTextMarkup.hpp> +#include <com/sun/star/smarttags/SmartTagRecognizerMode.hpp> +#include <com/sun/star/i18n/XBreakIterator.hpp> +#include <com/sun/star/lang/Locale.hpp> +#include <com/sun/star/lang/EventObject.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleComponentFactory.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/util/XChangesBatch.hpp> +#include <com/sun/star/util/XChangesNotifier.hpp> +#include <comphelper/processfactory.hxx> +#include <rtl/ustring.hxx> +#include <tools/string.hxx> + +using namespace com::sun::star; +using namespace com::sun::star::uno; + +#define C2U(cChar) rtl::OUString::createFromAscii(cChar) + + +SmartTagMgr::SmartTagMgr( const rtl::OUString& rApplicationName ) + : maApplicationName( rApplicationName ), + maRecognizerList(), + maActionList(), + maDisabledSmartTagTypes(), + maSmartTagMap(), + mxMSF( ::comphelper::getProcessServiceFactory() ), + mbLabelTextWithSmartTags(true) +{ +} + +SmartTagMgr::~SmartTagMgr() +{ +} + +void SmartTagMgr::Init( const rtl::OUString& rConfigurationGroupName ) +{ + // get component context to pass to components: + if ( mxMSF.is() ) + { + Reference< beans::XPropertySet > xPropSet = Reference< beans::XPropertySet>( mxMSF, UNO_QUERY); + const Any aAny = xPropSet->getPropertyValue( C2U("DefaultContext")); + aAny >>= mxContext; + + if ( mxContext.is() ) + { + PrepareConfiguration( rConfigurationGroupName ); + ReadConfiguration( true, true ); + RegisterListener(); + LoadLibraries(); + } + } +} +void SmartTagMgr::CreateBreakIterator() const +{ + if ( !mxBreakIter.is() && mxMSF.is() && mxContext.is() ) + { + // get the break iterator + mxBreakIter.set(mxMSF->createInstance( C2U( "com.sun.star.i18n.BreakIterator" ) ), UNO_QUERY); + } +} + +/** Dispatches the recognize call to all installed smart tag recognizers +*/ +void SmartTagMgr::Recognize( const rtl::OUString& rText, + const Reference< text::XTextMarkup > xMarkup, + const Reference< frame::XController > xController, + const lang::Locale& rLocale, + sal_uInt32 nStart, sal_uInt32 nLen ) const +{ + for ( sal_uInt32 i = 0; i < maRecognizerList.size(); i++ ) + { + Reference < smarttags::XSmartTagRecognizer > xRecognizer = maRecognizerList[i]; + + // if all smart tag types supported by this recognizer have been + // disabled, we do not have to call the recognizer: + bool bCallRecognizer = false; + const sal_uInt32 nSmartTagCount = xRecognizer->getSmartTagCount(); + for ( sal_uInt32 j = 0; j < nSmartTagCount && !bCallRecognizer; ++j ) + { + const rtl::OUString aSmartTagName = xRecognizer->getSmartTagName(j); + if ( IsSmartTagTypeEnabled( aSmartTagName ) ) + bCallRecognizer = true; + } + + if ( bCallRecognizer ) + { + CreateBreakIterator(); + maRecognizerList[i]->recognize( rText, nStart, nLen, + smarttags::SmartTagRecognizerMode_PARAGRAPH, + rLocale, xMarkup, maApplicationName, xController, + mxBreakIter ); + } + } +} + +typedef std::multimap < rtl::OUString, ActionReference >::const_iterator SmartTagMapIter; + +void SmartTagMgr::GetActionSequences( Sequence < rtl::OUString >& rSmartTagTypes, + Sequence < Sequence< Reference< smarttags::XSmartTagAction > > >& rActionComponentsSequence, + Sequence < Sequence< sal_Int32 > >& rActionIndicesSequence ) const +{ + rActionComponentsSequence.realloc( rSmartTagTypes.getLength() ); + rActionIndicesSequence.realloc( rSmartTagTypes.getLength() ); + + for ( USHORT j = 0; j < rSmartTagTypes.getLength(); ++j ) + { + const rtl::OUString& rSmartTagType = rSmartTagTypes[j]; + + const sal_Int32 nNumberOfActionRefs = maSmartTagMap.count( rSmartTagType ); + + Sequence< Reference< smarttags::XSmartTagAction > > aActions( nNumberOfActionRefs ); + Sequence< sal_Int32 > aIndices( nNumberOfActionRefs ); + + USHORT i = 0; + SmartTagMapIter aActionsIter; + SmartTagMapIter aEnd = maSmartTagMap.upper_bound( rSmartTagType ); + + for ( aActionsIter = maSmartTagMap.lower_bound( rSmartTagType ); aActionsIter != aEnd; ++aActionsIter ) + { + aActions[ i ] = (*aActionsIter).second.mxSmartTagAction; + aIndices[ i++ ] = (*aActionsIter).second.mnSmartTagIndex; + } + + rActionComponentsSequence[ j ] = aActions; + rActionIndicesSequence[ j ] = aIndices; + } +} + +/** Returns the caption for a smart tag type. +*/ +rtl::OUString SmartTagMgr::GetSmartTagCaption( const rtl::OUString& rSmartTagType, const com::sun::star::lang::Locale& rLocale ) const +{ + rtl::OUString aRet; + + SmartTagMapIter aLower = maSmartTagMap.lower_bound( rSmartTagType ); + + if ( aLower != maSmartTagMap.end() ) + { + const ActionReference& rActionRef = (*aLower).second; + Reference< smarttags::XSmartTagAction > xAction = rActionRef.mxSmartTagAction; + + if ( xAction.is() ) + { + const sal_Int32 nSmartTagIndex = rActionRef.mnSmartTagIndex; + aRet = xAction->getSmartTagCaption( nSmartTagIndex, rLocale ); + } + } + + return aRet; +} + + +/** Returns true if the given smart tag type is enabled. +*/ +bool SmartTagMgr::IsSmartTagTypeEnabled( const rtl::OUString& rSmartTagType ) const +{ + return maDisabledSmartTagTypes.end() == maDisabledSmartTagTypes.find( rSmartTagType ); +} + +/** Writes currently disabled smart tag types to configuration. +*/ +void SmartTagMgr::WriteConfiguration( const bool* pIsLabelTextWithSmartTags, + const std::vector< rtl::OUString >* pDisabledTypes ) const +{ + if ( mxConfigurationSettings.is() ) + { + bool bCommit = false; + + if ( pIsLabelTextWithSmartTags ) + { + const Any aEnabled = makeAny( *pIsLabelTextWithSmartTags ); + + try + { + mxConfigurationSettings->setPropertyValue( C2U("RecognizeSmartTags"), aEnabled ); + bCommit = true; + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + if ( pDisabledTypes ) + { + const sal_Int32 nNumberOfDisabledSmartTagTypes = pDisabledTypes->size(); + Sequence< rtl::OUString > aTypes( nNumberOfDisabledSmartTagTypes ); + + std::vector< rtl::OUString >::const_iterator aIter; + sal_Int32 nCount = 0; + for ( aIter = pDisabledTypes->begin(); aIter != pDisabledTypes->end(); ++aIter ) + aTypes[ nCount++ ] = *aIter; + + const Any aNewTypes = makeAny( aTypes ); + + try + { + mxConfigurationSettings->setPropertyValue( C2U("ExcludedSmartTagTypes"), aNewTypes ); + bCommit = true; + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + + if ( bCommit ) + { + try + { + Reference< util::XChangesBatch >( mxConfigurationSettings, UNO_QUERY_THROW )->commitChanges(); + } + catch ( ::com::sun::star::uno::Exception& ) + { + } + } + } +} + +// ::com::sun::star::util::XModifyListener +void SmartTagMgr::modified( const lang::EventObject& ) throw( RuntimeException ) +{ + vos::OGuard aGuard(Application::GetSolarMutex()); + + maRecognizerList.clear(); + maActionList.clear(); + maSmartTagMap.clear(); + + LoadLibraries(); +} + +// ::com::sun::star::lang::XEventListener +void SmartTagMgr::disposing( const lang::EventObject& rEvent ) throw( RuntimeException ) +{ + vos::OGuard aGuard(Application::GetSolarMutex()); + + uno::Reference< frame::XModel > xModel( rEvent.Source, uno::UNO_QUERY ); + uno::Reference< util::XModifyBroadcaster > xMB(xModel, uno::UNO_QUERY); + uno::Reference< util::XChangesNotifier > xCN(xModel, uno::UNO_QUERY); + + try + { + if( xMB.is() ) + { + uno::Reference< util::XModifyListener > xListener( this ); + xMB->removeModifyListener( xListener ); + } + else if ( xCN.is() ) + { + uno::Reference< util::XChangesListener > xListener( this ); + xCN->removeChangesListener( xListener ); + } + } + catch(Exception& ) + { + } +} + +// ::com::sun::star::util::XChangesListener +void SmartTagMgr::changesOccurred( const util::ChangesEvent& rEvent ) throw( RuntimeException) +{ + vos::OGuard aGuard(Application::GetSolarMutex()); + + const util::ElementChange* pElementChanges = rEvent.Changes.getConstArray(); + const sal_Int32 nNumberOfChanges = rEvent.Changes.getLength(); + bool bExcludedTypes = false; + bool bRecognize = false; + + for( sal_Int32 i = 0; i < nNumberOfChanges; ++i) + { + rtl::OUString sTemp; + pElementChanges[i].Accessor >>= sTemp; + + if ( sTemp == C2U( "ExcludedSmartTagTypes" ) ) + bExcludedTypes = true; + else if ( sTemp == C2U( "RecognizeSmartTags" ) ) + bRecognize = true; + } + + ReadConfiguration( bExcludedTypes, bRecognize ); +} + +//------------- PRIVATE ----------------------------------------------- + +/** +*/ +void SmartTagMgr::LoadLibraries() +{ + Reference< container::XContentEnumerationAccess > rContent( mxMSF , UNO_QUERY ); + if ( !rContent.is() ) + return; + + // load recognizers: No recognizers -> nothing to do. + Reference < container::XEnumeration > rEnum = rContent->createContentEnumeration( C2U("com.sun.star.smarttags.SmartTagRecognizer")); + if ( !rEnum.is() || !rEnum->hasMoreElements() ) + return; + + // iterate over all implementations of the smart tag recognizer service: + while( rEnum->hasMoreElements()) + { + const Any a = rEnum->nextElement(); + Reference< lang::XSingleComponentFactory > xSCF; + Reference< lang::XServiceInfo > xsInfo; + + if (a >>= xsInfo) + xSCF = Reference< lang::XSingleComponentFactory >(xsInfo, UNO_QUERY); + else + continue; + + Reference< smarttags::XSmartTagRecognizer > xLib ( xSCF-> + createInstanceWithContext(mxContext), UNO_QUERY ); + + if (!xLib.is()) + continue; + + xLib->initialize( Sequence< Any >() ); + maRecognizerList.push_back(xLib); + } + + // load actions: No actions -> nothing to do. + rEnum = rContent->createContentEnumeration( C2U("com.sun.star.smarttags.SmartTagAction")); + if ( !rEnum.is() ) + return; + + // iterate over all implementations of the smart tag action service: + while( rEnum->hasMoreElements()) + { + const Any a = rEnum->nextElement(); + Reference< lang::XServiceInfo > xsInfo; + Reference< lang::XSingleComponentFactory > xSCF; + + if (a >>= xsInfo) + xSCF = Reference< lang::XSingleComponentFactory >(xsInfo, UNO_QUERY); + else + continue; + + Reference< smarttags::XSmartTagAction > xLib ( xSCF-> + createInstanceWithContext(mxContext), UNO_QUERY ); + + if (!xLib.is()) + continue; + + xLib->initialize( Sequence< Any >() ); + maActionList.push_back(xLib); + } + + AssociateActionsWithRecognizers(); + +} + +/** +*/ +void SmartTagMgr::PrepareConfiguration( const rtl::OUString& rConfigurationGroupName ) +{ + Any aAny = makeAny( C2U( "/org.openoffice.Office.Common/SmartTags/" ) + rConfigurationGroupName ); + beans::PropertyValue aPathArgument; + aPathArgument.Name = C2U( "nodepath" ); + aPathArgument.Value = aAny; + Sequence< Any > aArguments( 1 ); + aArguments[ 0 ] <<= aPathArgument; + Reference< lang::XMultiServiceFactory > xConfProv( mxMSF->createInstance(C2U ("com.sun.star.configuration.ConfigurationProvider")), UNO_QUERY ); + + if ( !xConfProv.is() ) + return; + + // try to get read-write access to configuration: + Reference< XInterface > xConfigurationAccess; + try + { + xConfigurationAccess = xConfProv->createInstanceWithArguments( + C2U("com.sun.star.configuration.ConfigurationUpdateAccess" ), aArguments ); + } + catch ( uno::Exception& ) + { + } + + // fallback: try read-only access to configuration: + if ( !xConfigurationAccess.is() ) + { + try + { + xConfigurationAccess = xConfProv->createInstanceWithArguments( + C2U("com.sun.star.configuration.ConfigurationAccess" ), aArguments ); + } + catch ( uno::Exception& ) + { + } + } + + if ( xConfigurationAccess.is() ) + { + mxConfigurationSettings = Reference< beans::XPropertySet >( xConfigurationAccess, UNO_QUERY ); + } +} + + +void SmartTagMgr::ReadConfiguration( bool bExcludedTypes, bool bRecognize ) +{ + if ( mxConfigurationSettings.is() ) + { + if ( bExcludedTypes ) + { + maDisabledSmartTagTypes.clear(); + + Any aAny = mxConfigurationSettings->getPropertyValue( C2U("ExcludedSmartTagTypes") ); + Sequence< rtl::OUString > aValues; + aAny >>= aValues; + + const sal_Int32 nValues = aValues.getLength(); + + for ( sal_Int32 nI = 0; nI < nValues; ++nI ) + maDisabledSmartTagTypes.insert( aValues[nI] ); + } + + if ( bRecognize ) + { + Any aAny = mxConfigurationSettings->getPropertyValue( C2U("RecognizeSmartTags") ); + sal_Bool bValue = sal_True; + aAny >>= bValue; + + mbLabelTextWithSmartTags = bValue; + } + } +} + +/** +*/ +void SmartTagMgr::RegisterListener() +{ + // register as listener at package manager + try + { + Reference<deployment::XExtensionManager> xExtensionManager( + deployment::ExtensionManager::get( mxContext ) ); + Reference< util::XModifyBroadcaster > xMB ( xExtensionManager, UNO_QUERY_THROW ); + + Reference< util::XModifyListener > xListener( this ); + xMB->addModifyListener( xListener ); + } + catch ( uno::Exception& ) + { + } + + // register as listener at configuration + try + { + Reference<util::XChangesNotifier> xCN( mxConfigurationSettings, UNO_QUERY_THROW ); + Reference< util::XChangesListener > xListener( this ); + xCN->addChangesListener( xListener ); + } + catch ( uno::Exception& ) + { + } +} + +typedef std::pair < const rtl::OUString, ActionReference > SmartTagMapElement; + +/** Sets up a map that maps smart tag type names to actions references. +*/ +void SmartTagMgr::AssociateActionsWithRecognizers() +{ + const sal_uInt32 nActionLibCount = maActionList.size(); + const sal_uInt32 nRecognizerCount = maRecognizerList.size(); + + for ( sal_uInt32 i = 0; i < nRecognizerCount; ++i ) + { + Reference < smarttags::XSmartTagRecognizer > xRecognizer = maRecognizerList[i]; + const sal_uInt32 nSmartTagCount = xRecognizer->getSmartTagCount(); + for ( sal_uInt32 j = 0; j < nSmartTagCount; ++j ) + { + const rtl::OUString aSmartTagName = xRecognizer->getSmartTagName(j); + + // check if smart tag type has already been processed: + if ( maSmartTagMap.find( aSmartTagName ) != maSmartTagMap.end() ) + continue; + + bool bFound = false; + for ( sal_uInt32 k = 0; k < nActionLibCount; ++k ) + { + Reference< smarttags::XSmartTagAction > xActionLib = maActionList[k]; + const sal_uInt32 nSmartTagCountInActionLib = xActionLib->getSmartTagCount(); + for ( sal_uInt32 l = 0; l < nSmartTagCountInActionLib; ++l ) + { + const rtl::OUString aSmartTagNameInActionLib = xActionLib->getSmartTagName(l); + if ( aSmartTagName.equals( aSmartTagNameInActionLib ) ) + { + // found actions and recognizer for same smarttag + ActionReference aActionRef( xActionLib, l ); + + // add recognizer/action pair to map + maSmartTagMap.insert( SmartTagMapElement( aSmartTagName, aActionRef )); + + bFound = true; + } + } + } + + if ( !bFound ) + { + // insert 'empty' action reference if there is no action associated with + // the current smart tag type: + Reference< smarttags::XSmartTagAction > xActionLib; + ActionReference aActionRef( xActionLib, 0 ); + + // add recognizer/action pair to map + maSmartTagMap.insert( SmartTagMapElement( aSmartTagName, aActionRef )); + } + } + } +} + |