2c0906bcee
Found with bin/find-unneeded-includes Only removal proposals are dealt with here. Change-Id: I014631ec79242d9a5f735d7401fe0f5e323c69a3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/95649 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
664 lines
18 KiB
C++
664 lines
18 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* 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 .
|
|
*/
|
|
|
|
|
|
#include <cppuhelper/implbase.hxx>
|
|
#include <cppuhelper/supportsservice.hxx>
|
|
#include <unotools/mediadescriptor.hxx>
|
|
|
|
#include <com/sun/star/frame/XModel.hpp>
|
|
#include <com/sun/star/reflection/ProxyFactory.hpp>
|
|
|
|
#include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
|
|
#include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp>
|
|
#include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
|
|
|
|
#include <tools/diagnose_ex.h>
|
|
|
|
#include "BrowseNodeFactoryImpl.hxx"
|
|
#include "MasterScriptProvider.hxx"
|
|
#include <util/MiscUtils.hxx>
|
|
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include <memory>
|
|
|
|
using namespace ::com::sun::star;
|
|
using namespace ::com::sun::star::uno;
|
|
using namespace ::com::sun::star::script;
|
|
using namespace ::sf_misc;
|
|
|
|
namespace browsenodefactory
|
|
{
|
|
namespace {
|
|
class BrowseNodeAggregator :
|
|
public ::cppu::WeakImplHelper< browse::XBrowseNode >
|
|
{
|
|
private:
|
|
OUString m_Name;
|
|
std::vector< Reference< browse::XBrowseNode > > m_Nodes;
|
|
|
|
public:
|
|
|
|
explicit BrowseNodeAggregator( const Reference< browse::XBrowseNode >& node )
|
|
: m_Name(node->getName())
|
|
{
|
|
m_Nodes.resize( 1 );
|
|
m_Nodes[ 0 ] = node;
|
|
}
|
|
|
|
void addBrowseNode( const Reference< browse::XBrowseNode>& node )
|
|
{
|
|
m_Nodes.push_back( node );
|
|
}
|
|
|
|
virtual OUString
|
|
SAL_CALL getName() override
|
|
{
|
|
return m_Name;
|
|
}
|
|
|
|
virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL
|
|
getChildNodes() override
|
|
{
|
|
std::vector< Sequence< Reference < browse::XBrowseNode > > > seqs;
|
|
seqs.reserve( m_Nodes.size() );
|
|
|
|
sal_Int32 numChildren = 0;
|
|
|
|
for (Reference<XBrowseNode> & xNode : m_Nodes)
|
|
{
|
|
Sequence< Reference < browse::XBrowseNode > > children;
|
|
try
|
|
{
|
|
children = xNode->getChildNodes();
|
|
seqs.push_back( children );
|
|
numChildren += children.getLength();
|
|
}
|
|
catch ( Exception& )
|
|
{
|
|
// some form of exception getting child nodes so they
|
|
// won't be displayed
|
|
}
|
|
}
|
|
|
|
Sequence< Reference < browse::XBrowseNode > > result( numChildren );
|
|
sal_Int32 index = 0;
|
|
for ( Sequence< Reference < browse::XBrowseNode > >& children : seqs )
|
|
{
|
|
std::copy(children.begin(), children.end(), std::next(result.begin(), index));
|
|
index += children.getLength();
|
|
|
|
if (index >= numChildren)
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
virtual sal_Bool SAL_CALL
|
|
hasChildNodes() override
|
|
{
|
|
for (Reference<XBrowseNode> & xNode : m_Nodes)
|
|
{
|
|
try
|
|
{
|
|
if ( xNode->hasChildNodes() )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
catch ( Exception& )
|
|
{
|
|
// some form of exception getting child nodes so move
|
|
// on to the next one
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
virtual sal_Int16 SAL_CALL getType() override
|
|
{
|
|
return browse::BrowseNodeTypes::CONTAINER;
|
|
}
|
|
};
|
|
|
|
struct alphaSort
|
|
{
|
|
bool operator()( const OUString& a, const OUString& b )
|
|
{
|
|
return a.compareTo( b ) < 0;
|
|
}
|
|
};
|
|
class LocationBrowseNode :
|
|
public ::cppu::WeakImplHelper< browse::XBrowseNode >
|
|
{
|
|
private:
|
|
std::unique_ptr<std::unordered_map< OUString, Reference< browse::XBrowseNode > >> m_hBNA;
|
|
std::vector< OUString > m_vStr;
|
|
OUString m_sNodeName;
|
|
Reference< browse::XBrowseNode > m_origNode;
|
|
|
|
public:
|
|
|
|
explicit LocationBrowseNode( const Reference< browse::XBrowseNode >& node )
|
|
: m_sNodeName(node->getName())
|
|
{
|
|
m_origNode.set( node );
|
|
}
|
|
|
|
|
|
// XBrowseNode
|
|
|
|
virtual OUString SAL_CALL getName() override
|
|
{
|
|
return m_sNodeName;
|
|
}
|
|
|
|
virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL
|
|
getChildNodes() override
|
|
{
|
|
if ( m_hBNA == nullptr )
|
|
{
|
|
loadChildNodes();
|
|
}
|
|
|
|
Sequence< Reference< browse::XBrowseNode > > children( m_hBNA->size() );
|
|
sal_Int32 index = 0;
|
|
|
|
for ( const auto& str : m_vStr )
|
|
{
|
|
children[ index ].set( m_hBNA->find( str )->second );
|
|
++index;
|
|
}
|
|
|
|
return children;
|
|
}
|
|
|
|
virtual sal_Bool SAL_CALL hasChildNodes() override
|
|
{
|
|
return true;
|
|
}
|
|
|
|
virtual sal_Int16 SAL_CALL getType() override
|
|
{
|
|
return browse::BrowseNodeTypes::CONTAINER;
|
|
}
|
|
|
|
private:
|
|
|
|
void loadChildNodes()
|
|
{
|
|
m_hBNA.reset( new std::unordered_map< OUString, Reference< browse::XBrowseNode > > );
|
|
|
|
const Sequence< Reference< browse::XBrowseNode > > langNodes =
|
|
m_origNode->getChildNodes();
|
|
|
|
for ( const auto& rLangNode : langNodes )
|
|
{
|
|
Reference< browse::XBrowseNode > xbn;
|
|
if ( rLangNode->getName() == "uno_packages" )
|
|
{
|
|
xbn.set( new LocationBrowseNode( rLangNode ) );
|
|
}
|
|
else
|
|
{
|
|
xbn.set( rLangNode );
|
|
}
|
|
|
|
const Sequence< Reference< browse::XBrowseNode > > grandchildren =
|
|
xbn->getChildNodes();
|
|
|
|
for ( const Reference< browse::XBrowseNode >& grandchild : grandchildren )
|
|
{
|
|
auto h_it =
|
|
m_hBNA->find( grandchild->getName() );
|
|
|
|
if ( h_it != m_hBNA->end() )
|
|
{
|
|
BrowseNodeAggregator* bna = static_cast< BrowseNodeAggregator* >( h_it->second.get() );
|
|
bna->addBrowseNode( grandchild );
|
|
}
|
|
else
|
|
{
|
|
Reference< browse::XBrowseNode > bna(
|
|
new BrowseNodeAggregator( grandchild ) );
|
|
(*m_hBNA)[ grandchild->getName() ].set( bna );
|
|
m_vStr.push_back( grandchild->getName() );
|
|
}
|
|
}
|
|
}
|
|
// sort children alphabetically
|
|
::std::sort( m_vStr.begin(), m_vStr.end(), alphaSort() );
|
|
}
|
|
};
|
|
|
|
std::vector< Reference< browse::XBrowseNode > > getAllBrowseNodes( const Reference< XComponentContext >& xCtx )
|
|
{
|
|
const Sequence< OUString > openDocs =
|
|
MiscUtils::allOpenTDocUrls( xCtx );
|
|
|
|
Reference< provider::XScriptProviderFactory > xFac;
|
|
sal_Int32 initialSize = openDocs.getLength() + 2;
|
|
sal_Int32 mspIndex = 0;
|
|
|
|
std::vector< Reference < browse::XBrowseNode > > locnBNs( initialSize );
|
|
try
|
|
{
|
|
xFac = provider::theMasterScriptProviderFactory::get( xCtx );
|
|
|
|
locnBNs[ mspIndex++ ].set( xFac->createScriptProvider( makeAny( OUString("user") ) ), UNO_QUERY_THROW );
|
|
locnBNs[ mspIndex++ ].set( xFac->createScriptProvider( makeAny( OUString("share") ) ), UNO_QUERY_THROW );
|
|
}
|
|
// TODO proper exception handling, should throw
|
|
catch( const Exception& )
|
|
{
|
|
TOOLS_WARN_EXCEPTION("scripting", "Caught" );
|
|
locnBNs.resize( mspIndex );
|
|
return locnBNs;
|
|
}
|
|
|
|
for ( const auto& rDoc : openDocs )
|
|
{
|
|
try
|
|
{
|
|
Reference< frame::XModel > model( MiscUtils::tDocUrlToModel( rDoc ), UNO_SET_THROW );
|
|
|
|
// #i44599 Check if it's a real document or something special like Hidden/Preview
|
|
css::uno::Reference< css::frame::XController > xCurrentController = model->getCurrentController();
|
|
if( xCurrentController.is() )
|
|
{
|
|
utl::MediaDescriptor aMD( model->getArgs() );
|
|
bool bDefault = false;
|
|
bool bHidden = aMD.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_HIDDEN(), bDefault );
|
|
bool bPreview = aMD.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_PREVIEW(), bDefault );
|
|
if( !bHidden && !bPreview )
|
|
{
|
|
Reference< document::XEmbeddedScripts > xScripts( model, UNO_QUERY );
|
|
if ( xScripts.is() )
|
|
locnBNs[ mspIndex++ ].set( xFac->createScriptProvider( makeAny( model ) ), UNO_QUERY_THROW );
|
|
}
|
|
}
|
|
}
|
|
catch( const Exception& )
|
|
{
|
|
DBG_UNHANDLED_EXCEPTION("scripting");
|
|
}
|
|
|
|
}
|
|
|
|
std::vector< Reference < browse::XBrowseNode > > locnBNs_Return( mspIndex );
|
|
for ( sal_Int32 j = 0; j < mspIndex; j++ )
|
|
locnBNs_Return[j] = locnBNs[j];
|
|
|
|
return locnBNs_Return;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
typedef ::std::vector< Reference< browse::XBrowseNode > > vXBrowseNodes;
|
|
|
|
namespace {
|
|
|
|
struct alphaSortForBNodes
|
|
{
|
|
bool operator()( const Reference< browse::XBrowseNode >& a, const Reference< browse::XBrowseNode >& b )
|
|
{
|
|
return a->getName().compareTo( b->getName() ) < 0;
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
typedef ::cppu::WeakImplHelper< browse::XBrowseNode > t_BrowseNodeBase;
|
|
|
|
namespace {
|
|
|
|
class DefaultBrowseNode :
|
|
public t_BrowseNodeBase
|
|
{
|
|
|
|
private:
|
|
Reference< browse::XBrowseNode > m_xWrappedBrowseNode;
|
|
Reference< lang::XTypeProvider > m_xWrappedTypeProv;
|
|
Reference< XAggregation > m_xAggProxy;
|
|
Reference< XComponentContext > m_xCtx;
|
|
|
|
public:
|
|
DefaultBrowseNode( const Reference< XComponentContext >& xCtx, const Reference< browse::XBrowseNode>& xNode ) : m_xWrappedBrowseNode( xNode ), m_xWrappedTypeProv( xNode, UNO_QUERY ), m_xCtx( xCtx )
|
|
{
|
|
OSL_ENSURE( m_xWrappedBrowseNode.is(), "DefaultBrowseNode::DefaultBrowseNode(): No BrowseNode to wrap" );
|
|
OSL_ENSURE( m_xWrappedTypeProv.is(), "DefaultBrowseNode::DefaultBrowseNode(): No BrowseNode to wrap" );
|
|
OSL_ENSURE( m_xCtx.is(), "DefaultBrowseNode::DefaultBrowseNode(): No ComponentContext" );
|
|
// Use proxy factory service to create aggregatable proxy.
|
|
try
|
|
{
|
|
Reference< reflection::XProxyFactory > xProxyFac =
|
|
reflection::ProxyFactory::create( m_xCtx );
|
|
m_xAggProxy = xProxyFac->createProxy( m_xWrappedBrowseNode );
|
|
}
|
|
catch( uno::Exception& )
|
|
{
|
|
OSL_FAIL( "DefaultBrowseNode::DefaultBrowseNode: Caught exception!" );
|
|
}
|
|
OSL_ENSURE( m_xAggProxy.is(),
|
|
"DefaultBrowseNode::DefaultBrowseNode: Wrapped BrowseNode cannot be aggregated!" );
|
|
|
|
if ( !m_xAggProxy.is() )
|
|
return;
|
|
|
|
osl_atomic_increment( &m_refCount );
|
|
|
|
/* i35609 - Fix crash on Solaris. The setDelegator call needs
|
|
to be in its own block to ensure that all temporary Reference
|
|
instances that are acquired during the call are released
|
|
before m_refCount is decremented again */
|
|
{
|
|
m_xAggProxy->setDelegator(
|
|
static_cast< cppu::OWeakObject * >( this ) );
|
|
}
|
|
|
|
osl_atomic_decrement( &m_refCount );
|
|
}
|
|
|
|
virtual ~DefaultBrowseNode() override
|
|
{
|
|
if ( m_xAggProxy.is() )
|
|
{
|
|
m_xAggProxy->setDelegator( uno::Reference< uno::XInterface >() );
|
|
}
|
|
}
|
|
|
|
virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL
|
|
getChildNodes() override
|
|
{
|
|
if ( hasChildNodes() )
|
|
{
|
|
vXBrowseNodes aVNodes;
|
|
const Sequence < Reference< browse::XBrowseNode > > nodes =
|
|
m_xWrappedBrowseNode->getChildNodes();
|
|
for ( const Reference< browse::XBrowseNode >& xBrowseNode : nodes )
|
|
{
|
|
OSL_ENSURE( xBrowseNode.is(), "DefaultBrowseNode::getChildNodes(): Invalid BrowseNode" );
|
|
if( xBrowseNode.is() )
|
|
aVNodes.push_back( new DefaultBrowseNode( m_xCtx, xBrowseNode ) );
|
|
}
|
|
|
|
::std::sort( aVNodes.begin(), aVNodes.end(), alphaSortForBNodes() );
|
|
Sequence < Reference< browse::XBrowseNode > > children( aVNodes.size() );
|
|
sal_Int32 i = 0;
|
|
for ( const auto& rxNode : aVNodes )
|
|
{
|
|
children[ i ].set( rxNode );
|
|
i++;
|
|
}
|
|
return children;
|
|
}
|
|
else
|
|
{
|
|
// no nodes
|
|
|
|
Sequence < Reference< browse::XBrowseNode > > none;
|
|
return none;
|
|
}
|
|
}
|
|
|
|
virtual sal_Int16 SAL_CALL getType() override
|
|
{
|
|
return m_xWrappedBrowseNode->getType();
|
|
}
|
|
|
|
virtual OUString
|
|
SAL_CALL getName() override
|
|
{
|
|
return m_xWrappedBrowseNode->getName();
|
|
}
|
|
|
|
virtual sal_Bool SAL_CALL
|
|
hasChildNodes() override
|
|
{
|
|
return m_xWrappedBrowseNode->hasChildNodes();
|
|
}
|
|
|
|
// XInterface
|
|
virtual Any SAL_CALL queryInterface( const Type& aType ) override
|
|
{
|
|
Any aRet = t_BrowseNodeBase::queryInterface( aType );
|
|
if ( aRet.hasValue() )
|
|
{
|
|
return aRet;
|
|
}
|
|
if ( m_xAggProxy.is() )
|
|
{
|
|
return m_xAggProxy->queryAggregation( aType );
|
|
}
|
|
else
|
|
{
|
|
return Any();
|
|
}
|
|
}
|
|
|
|
// XTypeProvider (implemnented by base, but needs to be overridden for
|
|
// delegating to aggregate)
|
|
virtual Sequence< Type > SAL_CALL getTypes() override
|
|
{
|
|
return m_xWrappedTypeProv->getTypes();
|
|
}
|
|
virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override
|
|
{
|
|
return css::uno::Sequence<sal_Int8>();
|
|
}
|
|
};
|
|
|
|
class DefaultRootBrowseNode :
|
|
public ::cppu::WeakImplHelper< browse::XBrowseNode >
|
|
{
|
|
|
|
private:
|
|
vXBrowseNodes m_vNodes;
|
|
OUString m_Name;
|
|
|
|
public:
|
|
explicit DefaultRootBrowseNode( const Reference< XComponentContext >& xCtx )
|
|
{
|
|
std::vector< Reference< browse::XBrowseNode > > nodes =
|
|
getAllBrowseNodes( xCtx );
|
|
|
|
for (Reference< browse::XBrowseNode > & xNode : nodes)
|
|
{
|
|
m_vNodes.push_back( new DefaultBrowseNode( xCtx, xNode ) );
|
|
}
|
|
m_Name = "Root";
|
|
}
|
|
|
|
virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL
|
|
getChildNodes() override
|
|
{
|
|
// no need to sort user, share, doc1...docN
|
|
//::std::sort( m_vNodes.begin(), m_vNodes.end(), alphaSortForBNodes() );
|
|
Sequence < Reference< browse::XBrowseNode > > children( m_vNodes.size() );
|
|
sal_Int32 i = 0;
|
|
for ( const auto& rxNode : m_vNodes )
|
|
{
|
|
children[ i ].set( rxNode );
|
|
i++;
|
|
}
|
|
return children;
|
|
}
|
|
|
|
virtual sal_Int16 SAL_CALL getType() override
|
|
{
|
|
return browse::BrowseNodeTypes::ROOT;
|
|
}
|
|
|
|
virtual OUString
|
|
SAL_CALL getName() override
|
|
{
|
|
return m_Name;
|
|
}
|
|
|
|
virtual sal_Bool SAL_CALL
|
|
hasChildNodes() override
|
|
{
|
|
bool result = true;
|
|
if ( m_vNodes.empty() )
|
|
{
|
|
result = false;
|
|
}
|
|
return result;
|
|
}
|
|
};
|
|
|
|
|
|
class SelectorBrowseNode :
|
|
public ::cppu::WeakImplHelper< browse::XBrowseNode >
|
|
{
|
|
private:
|
|
Reference< XComponentContext > m_xComponentContext;
|
|
|
|
public:
|
|
explicit SelectorBrowseNode( const Reference< XComponentContext >& xContext )
|
|
: m_xComponentContext( xContext )
|
|
{
|
|
}
|
|
|
|
virtual OUString SAL_CALL getName() override
|
|
{
|
|
return "Root";
|
|
}
|
|
|
|
virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL
|
|
getChildNodes() override
|
|
{
|
|
|
|
std::vector< Reference < browse::XBrowseNode > > locnBNs = getAllBrowseNodes( m_xComponentContext );
|
|
|
|
Sequence< Reference< browse::XBrowseNode > > children(
|
|
locnBNs.size() );
|
|
|
|
for ( size_t j = 0; j < locnBNs.size(); j++ )
|
|
{
|
|
children[j] = new LocationBrowseNode( locnBNs[j] );
|
|
}
|
|
|
|
return children;
|
|
}
|
|
|
|
virtual sal_Bool SAL_CALL hasChildNodes() override
|
|
{
|
|
return true; // will always be user and share
|
|
}
|
|
|
|
virtual sal_Int16 SAL_CALL getType() override
|
|
{
|
|
return browse::BrowseNodeTypes::CONTAINER;
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
BrowseNodeFactoryImpl::BrowseNodeFactoryImpl(
|
|
Reference< XComponentContext > const & xComponentContext )
|
|
: m_xComponentContext( xComponentContext )
|
|
{
|
|
}
|
|
|
|
BrowseNodeFactoryImpl::~BrowseNodeFactoryImpl()
|
|
{
|
|
}
|
|
|
|
|
|
// Implementation of XBrowseNodeFactory
|
|
|
|
|
|
/*
|
|
* The selector hierarchy is the standard hierarchy for organizers with the
|
|
* language nodes removed.
|
|
*/
|
|
Reference< browse::XBrowseNode > SAL_CALL
|
|
BrowseNodeFactoryImpl::createView( sal_Int16 viewType )
|
|
{
|
|
switch( viewType )
|
|
{
|
|
case browse::BrowseNodeFactoryViewTypes::MACROSELECTOR:
|
|
return new SelectorBrowseNode( m_xComponentContext );
|
|
case browse::BrowseNodeFactoryViewTypes::MACROORGANIZER:
|
|
return getOrganizerHierarchy();
|
|
default:
|
|
throw RuntimeException( "Unknown view type" );
|
|
}
|
|
}
|
|
|
|
Reference< browse::XBrowseNode >
|
|
BrowseNodeFactoryImpl::getOrganizerHierarchy() const
|
|
{
|
|
Reference< browse::XBrowseNode > xRet = new DefaultRootBrowseNode( m_xComponentContext );
|
|
return xRet;
|
|
}
|
|
|
|
// Helper methods
|
|
|
|
|
|
// Namespace global methods for setting up BrowseNodeFactory service
|
|
|
|
|
|
Sequence< OUString >
|
|
bnf_getSupportedServiceNames( )
|
|
{
|
|
return { "com.sun.star.script.browse.BrowseNodeFactory" };
|
|
}
|
|
|
|
OUString
|
|
bnf_getImplementationName( )
|
|
{
|
|
return
|
|
"com.sun.star.script.browse.BrowseNodeFactory";
|
|
}
|
|
|
|
Reference< XInterface >
|
|
bnf_create( Reference< XComponentContext > const & xComponentContext )
|
|
{
|
|
return static_cast< ::cppu::OWeakObject * >(
|
|
new BrowseNodeFactoryImpl( xComponentContext ) );
|
|
}
|
|
|
|
|
|
// Implementation of XServiceInfo
|
|
|
|
|
|
OUString SAL_CALL
|
|
BrowseNodeFactoryImpl::getImplementationName()
|
|
{
|
|
return bnf_getImplementationName();
|
|
}
|
|
|
|
Sequence< OUString > SAL_CALL
|
|
BrowseNodeFactoryImpl::getSupportedServiceNames()
|
|
{
|
|
return bnf_getSupportedServiceNames();
|
|
}
|
|
|
|
sal_Bool BrowseNodeFactoryImpl::supportsService(OUString const & serviceName )
|
|
{
|
|
return cppu::supportsService(this, serviceName);
|
|
}
|
|
|
|
} // namespace browsenodefactory
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|