tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / scripting / source / provider / BrowseNodeFactoryImpl.cxx
blob003cb999f520bd1bd655c25c991c72b533e88003
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <cppuhelper/implbase.hxx>
22 #include <cppuhelper/supportsservice.hxx>
23 #include <unotools/mediadescriptor.hxx>
25 #include <com/sun/star/document/XEmbeddedScripts.hpp>
26 #include <com/sun/star/frame/XModel.hpp>
27 #include <com/sun/star/reflection/ProxyFactory.hpp>
29 #include <com/sun/star/script/provider/theMasterScriptProviderFactory.hpp>
30 #include <com/sun/star/script/browse/BrowseNodeFactoryViewTypes.hpp>
31 #include <com/sun/star/script/browse/BrowseNodeTypes.hpp>
33 #include <comphelper/diagnose_ex.hxx>
35 #include "BrowseNodeFactoryImpl.hxx"
36 #include <util/MiscUtils.hxx>
38 #include <vector>
39 #include <algorithm>
40 #include <memory>
41 #include <optional>
42 #include <string_view>
44 using namespace ::com::sun::star;
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::script;
47 using namespace ::sf_misc;
49 namespace browsenodefactory
51 namespace {
52 class BrowseNodeAggregator :
53 public ::cppu::WeakImplHelper< browse::XBrowseNode >
55 private:
56 OUString m_Name;
57 std::vector< Reference< browse::XBrowseNode > > m_Nodes;
59 public:
61 explicit BrowseNodeAggregator( const Reference< browse::XBrowseNode >& node )
62 : m_Name(node->getName())
64 m_Nodes.resize( 1 );
65 m_Nodes[ 0 ] = node;
68 void addBrowseNode( const Reference< browse::XBrowseNode>& node )
70 m_Nodes.push_back( node );
73 virtual OUString
74 SAL_CALL getName() override
76 return m_Name;
79 virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL
80 getChildNodes() override
82 std::vector< Sequence< Reference < browse::XBrowseNode > > > seqs;
83 seqs.reserve( m_Nodes.size() );
85 sal_Int32 numChildren = 0;
87 for (Reference<XBrowseNode> & xNode : m_Nodes)
89 Sequence< Reference < browse::XBrowseNode > > children;
90 try
92 children = xNode->getChildNodes();
93 seqs.push_back( children );
94 numChildren += children.getLength();
96 catch ( Exception& )
98 // some form of exception getting child nodes so they
99 // won't be displayed
103 Sequence< Reference < browse::XBrowseNode > > result( numChildren );
104 sal_Int32 index = 0;
105 for ( const Sequence< Reference < browse::XBrowseNode > >& children : seqs )
107 std::copy(children.begin(), children.end(), std::next(result.getArray(), index));
108 index += children.getLength();
110 if (index >= numChildren)
111 break;
113 return result;
116 virtual sal_Bool SAL_CALL
117 hasChildNodes() override
119 for (Reference<XBrowseNode> & xNode : m_Nodes)
123 if ( xNode->hasChildNodes() )
125 return true;
128 catch ( Exception& )
130 // some form of exception getting child nodes so move
131 // on to the next one
135 return false;
138 virtual sal_Int16 SAL_CALL getType() override
140 return browse::BrowseNodeTypes::CONTAINER;
144 struct alphaSort
146 bool operator()( std::u16string_view a, std::u16string_view b )
148 return a.compare( b ) < 0;
151 class LocationBrowseNode :
152 public ::cppu::WeakImplHelper< browse::XBrowseNode >
154 private:
155 std::optional<std::unordered_map< OUString, Reference< browse::XBrowseNode > >> m_hBNA;
156 std::vector< OUString > m_vStr;
157 OUString m_sNodeName;
158 Reference< browse::XBrowseNode > m_origNode;
160 public:
162 explicit LocationBrowseNode( const Reference< browse::XBrowseNode >& node )
163 : m_sNodeName(node->getName())
165 m_origNode.set( node );
169 // XBrowseNode
171 virtual OUString SAL_CALL getName() override
173 return m_sNodeName;
176 virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL
177 getChildNodes() override
179 if ( !m_hBNA )
181 loadChildNodes();
184 Sequence< Reference< browse::XBrowseNode > > children( m_hBNA->size() );
185 auto childrenRange = asNonConstRange(children);
186 sal_Int32 index = 0;
188 for ( const auto& str : m_vStr )
190 childrenRange[ index ].set( m_hBNA->find( str )->second );
191 ++index;
194 return children;
197 virtual sal_Bool SAL_CALL hasChildNodes() override
199 return true;
202 virtual sal_Int16 SAL_CALL getType() override
204 return browse::BrowseNodeTypes::CONTAINER;
207 private:
209 void loadChildNodes()
211 m_hBNA.emplace();
213 const Sequence< Reference< browse::XBrowseNode > > langNodes =
214 m_origNode->getChildNodes();
216 for ( const auto& rLangNode : langNodes )
218 Reference< browse::XBrowseNode > xbn;
219 if ( rLangNode->getName() == "uno_packages" )
221 xbn.set( new LocationBrowseNode( rLangNode ) );
223 else
225 xbn.set( rLangNode );
228 const Sequence< Reference< browse::XBrowseNode > > grandchildren =
229 xbn->getChildNodes();
231 for ( const Reference< browse::XBrowseNode >& grandchild : grandchildren )
233 auto h_it =
234 m_hBNA->find( grandchild->getName() );
236 if ( h_it != m_hBNA->end() )
238 BrowseNodeAggregator* bna = static_cast< BrowseNodeAggregator* >( h_it->second.get() );
239 bna->addBrowseNode( grandchild );
241 else
243 Reference< browse::XBrowseNode > bna(
244 new BrowseNodeAggregator( grandchild ) );
245 (*m_hBNA)[ grandchild->getName() ].set( bna );
246 m_vStr.push_back( grandchild->getName() );
250 // sort children alphabetically
251 ::std::sort( m_vStr.begin(), m_vStr.end(), alphaSort() );
255 std::vector< Reference< browse::XBrowseNode > > getAllBrowseNodes( const Reference< XComponentContext >& xCtx )
257 const Sequence< OUString > openDocs =
258 MiscUtils::allOpenTDocUrls( xCtx );
260 Reference< provider::XScriptProviderFactory > xFac;
261 sal_Int32 initialSize = openDocs.getLength() + 2;
262 sal_Int32 mspIndex = 0;
264 std::vector< Reference < browse::XBrowseNode > > locnBNs( initialSize );
267 xFac = provider::theMasterScriptProviderFactory::get( xCtx );
269 locnBNs[ mspIndex++ ].set( xFac->createScriptProvider( Any( u"user"_ustr ) ), UNO_QUERY_THROW );
270 locnBNs[ mspIndex++ ].set( xFac->createScriptProvider( Any( u"share"_ustr ) ), UNO_QUERY_THROW );
272 // TODO proper exception handling, should throw
273 catch( const Exception& )
275 TOOLS_WARN_EXCEPTION("scripting", "Caught" );
276 locnBNs.resize( mspIndex );
277 return locnBNs;
280 for ( const auto& rDoc : openDocs )
284 Reference< frame::XModel > model( MiscUtils::tDocUrlToModel( rDoc ), UNO_SET_THROW );
286 // #i44599 Check if it's a real document or something special like Hidden/Preview
287 css::uno::Reference< css::frame::XController > xCurrentController = model->getCurrentController();
288 if( xCurrentController.is() )
290 utl::MediaDescriptor aMD( model->getArgs() );
291 bool bDefault = false;
292 bool bHidden = aMD.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_HIDDEN, bDefault );
293 bool bPreview = aMD.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_PREVIEW, bDefault );
294 if( !bHidden && !bPreview )
296 Reference< document::XEmbeddedScripts > xScripts( model, UNO_QUERY );
297 if ( xScripts.is() )
298 locnBNs[ mspIndex++ ].set( xFac->createScriptProvider( Any( model ) ), UNO_QUERY_THROW );
302 catch( const Exception& )
304 DBG_UNHANDLED_EXCEPTION("scripting");
309 std::vector< Reference < browse::XBrowseNode > > locnBNs_Return( mspIndex );
310 for ( sal_Int32 j = 0; j < mspIndex; j++ )
311 locnBNs_Return[j] = locnBNs[j];
313 return locnBNs_Return;
316 } // namespace
318 typedef ::std::vector< Reference< browse::XBrowseNode > > vXBrowseNodes;
320 namespace {
322 struct alphaSortForBNodes
324 bool operator()( const Reference< browse::XBrowseNode >& a, const Reference< browse::XBrowseNode >& b )
326 return a->getName().compareTo( b->getName() ) < 0;
332 typedef ::cppu::WeakImplHelper< browse::XBrowseNode > t_BrowseNodeBase;
334 namespace {
336 class DefaultBrowseNode :
337 public t_BrowseNodeBase
340 private:
341 Reference< browse::XBrowseNode > m_xWrappedBrowseNode;
342 Reference< lang::XTypeProvider > m_xWrappedTypeProv;
343 Reference< XAggregation > m_xAggProxy;
344 Reference< XComponentContext > m_xCtx;
346 public:
347 DefaultBrowseNode( const Reference< XComponentContext >& xCtx, const Reference< browse::XBrowseNode>& xNode ) : m_xWrappedBrowseNode( xNode ), m_xWrappedTypeProv( xNode, UNO_QUERY ), m_xCtx( xCtx )
349 OSL_ENSURE( m_xWrappedBrowseNode.is(), "DefaultBrowseNode::DefaultBrowseNode(): No BrowseNode to wrap" );
350 OSL_ENSURE( m_xWrappedTypeProv.is(), "DefaultBrowseNode::DefaultBrowseNode(): No BrowseNode to wrap" );
351 OSL_ENSURE( m_xCtx.is(), "DefaultBrowseNode::DefaultBrowseNode(): No ComponentContext" );
352 // Use proxy factory service to create aggregatable proxy.
355 Reference< reflection::XProxyFactory > xProxyFac =
356 reflection::ProxyFactory::create( m_xCtx );
357 m_xAggProxy = xProxyFac->createProxy( m_xWrappedBrowseNode );
359 catch( uno::Exception& )
361 TOOLS_WARN_EXCEPTION( "scripting", "DefaultBrowseNode::DefaultBrowseNode" );
363 OSL_ENSURE( m_xAggProxy.is(),
364 "DefaultBrowseNode::DefaultBrowseNode: Wrapped BrowseNode cannot be aggregated!" );
366 if ( !m_xAggProxy.is() )
367 return;
369 osl_atomic_increment( &m_refCount );
371 /* i35609 - Fix crash on Solaris. The setDelegator call needs
372 to be in its own block to ensure that all temporary Reference
373 instances that are acquired during the call are released
374 before m_refCount is decremented again */
376 m_xAggProxy->setDelegator(
377 getXWeak() );
380 osl_atomic_decrement( &m_refCount );
383 virtual ~DefaultBrowseNode() override
385 if ( m_xAggProxy.is() )
387 m_xAggProxy->setDelegator( uno::Reference< uno::XInterface >() );
391 virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL
392 getChildNodes() override
394 if ( hasChildNodes() )
396 vXBrowseNodes aVNodes;
397 const Sequence < Reference< browse::XBrowseNode > > nodes =
398 m_xWrappedBrowseNode->getChildNodes();
399 for ( const Reference< browse::XBrowseNode >& xBrowseNode : nodes )
401 OSL_ENSURE( xBrowseNode.is(), "DefaultBrowseNode::getChildNodes(): Invalid BrowseNode" );
402 if( xBrowseNode.is() )
403 aVNodes.push_back( new DefaultBrowseNode( m_xCtx, xBrowseNode ) );
406 ::std::sort( aVNodes.begin(), aVNodes.end(), alphaSortForBNodes() );
407 Sequence < Reference< browse::XBrowseNode > > children( aVNodes.size() );
408 auto childrenRange = asNonConstRange(children);
409 sal_Int32 i = 0;
410 for ( const auto& rxNode : aVNodes )
412 childrenRange[ i ].set( rxNode );
413 i++;
415 return children;
417 else
419 // no nodes
421 Sequence < Reference< browse::XBrowseNode > > none;
422 return none;
426 virtual sal_Int16 SAL_CALL getType() override
428 return m_xWrappedBrowseNode->getType();
431 virtual OUString
432 SAL_CALL getName() override
434 return m_xWrappedBrowseNode->getName();
437 virtual sal_Bool SAL_CALL
438 hasChildNodes() override
440 return m_xWrappedBrowseNode->hasChildNodes();
443 // XInterface
444 virtual Any SAL_CALL queryInterface( const Type& aType ) override
446 Any aRet = t_BrowseNodeBase::queryInterface( aType );
447 if ( aRet.hasValue() )
449 return aRet;
451 if ( m_xAggProxy.is() )
453 return m_xAggProxy->queryAggregation( aType );
455 else
457 return Any();
461 // XTypeProvider (implemented by base, but needs to be overridden for
462 // delegating to aggregate)
463 virtual Sequence< Type > SAL_CALL getTypes() override
465 return m_xWrappedTypeProv->getTypes();
467 virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override
469 return css::uno::Sequence<sal_Int8>();
473 class DefaultRootBrowseNode :
474 public ::cppu::WeakImplHelper< browse::XBrowseNode >
477 private:
478 vXBrowseNodes m_vNodes;
479 OUString m_Name;
481 public:
482 explicit DefaultRootBrowseNode( const Reference< XComponentContext >& xCtx )
484 std::vector< Reference< browse::XBrowseNode > > nodes =
485 getAllBrowseNodes( xCtx );
487 for (Reference< browse::XBrowseNode > & xNode : nodes)
489 m_vNodes.push_back( new DefaultBrowseNode( xCtx, xNode ) );
491 m_Name = "Root";
494 virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL
495 getChildNodes() override
497 // no need to sort user, share, doc1...docN
498 //::std::sort( m_vNodes.begin(), m_vNodes.end(), alphaSortForBNodes() );
499 Sequence < Reference< browse::XBrowseNode > > children( m_vNodes.size() );
500 auto childrenRange = asNonConstRange(children);
501 sal_Int32 i = 0;
502 for ( const auto& rxNode : m_vNodes )
504 childrenRange[ i ].set( rxNode );
505 i++;
507 return children;
510 virtual sal_Int16 SAL_CALL getType() override
512 return browse::BrowseNodeTypes::ROOT;
515 virtual OUString
516 SAL_CALL getName() override
518 return m_Name;
521 virtual sal_Bool SAL_CALL
522 hasChildNodes() override
524 bool result = true;
525 if ( m_vNodes.empty() )
527 result = false;
529 return result;
534 class SelectorBrowseNode :
535 public ::cppu::WeakImplHelper< browse::XBrowseNode >
537 private:
538 Reference< XComponentContext > m_xComponentContext;
540 public:
541 explicit SelectorBrowseNode( const Reference< XComponentContext >& xContext )
542 : m_xComponentContext( xContext )
546 virtual OUString SAL_CALL getName() override
548 return u"Root"_ustr;
551 virtual Sequence< Reference< browse::XBrowseNode > > SAL_CALL
552 getChildNodes() override
555 std::vector< Reference < browse::XBrowseNode > > locnBNs = getAllBrowseNodes( m_xComponentContext );
557 Sequence< Reference< browse::XBrowseNode > > children(
558 locnBNs.size() );
559 auto childrenRange = asNonConstRange(children);
561 for ( size_t j = 0; j < locnBNs.size(); j++ )
563 childrenRange[j] = new LocationBrowseNode( locnBNs[j] );
566 return children;
569 virtual sal_Bool SAL_CALL hasChildNodes() override
571 return true; // will always be user and share
574 virtual sal_Int16 SAL_CALL getType() override
576 return browse::BrowseNodeTypes::CONTAINER;
582 BrowseNodeFactoryImpl::BrowseNodeFactoryImpl(
583 Reference< XComponentContext > const & xComponentContext )
584 : m_xComponentContext( xComponentContext )
588 BrowseNodeFactoryImpl::~BrowseNodeFactoryImpl()
593 // Implementation of XBrowseNodeFactory
597 * The selector hierarchy is the standard hierarchy for organizers with the
598 * language nodes removed.
600 Reference< browse::XBrowseNode > SAL_CALL
601 BrowseNodeFactoryImpl::createView( sal_Int16 viewType )
603 switch( viewType )
605 case browse::BrowseNodeFactoryViewTypes::MACROSELECTOR:
606 return new SelectorBrowseNode( m_xComponentContext );
607 case browse::BrowseNodeFactoryViewTypes::MACROORGANIZER:
608 return getOrganizerHierarchy();
609 default:
610 throw RuntimeException( u"Unknown view type"_ustr );
614 Reference< browse::XBrowseNode >
615 BrowseNodeFactoryImpl::getOrganizerHierarchy() const
617 Reference< browse::XBrowseNode > xRet = new DefaultRootBrowseNode( m_xComponentContext );
618 return xRet;
621 // Implementation of XServiceInfo
624 OUString SAL_CALL
625 BrowseNodeFactoryImpl::getImplementationName()
627 return u"com.sun.star.script.browse.BrowseNodeFactory"_ustr;
630 Sequence< OUString > SAL_CALL
631 BrowseNodeFactoryImpl::getSupportedServiceNames()
633 return { u"com.sun.star.script.browse.BrowseNodeFactory"_ustr };
636 sal_Bool BrowseNodeFactoryImpl::supportsService(OUString const & serviceName )
638 return cppu::supportsService(this, serviceName);
641 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
642 scripting_BrowseNodeFactoryImpl_get_implementation(
643 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
645 return cppu::acquire(new BrowseNodeFactoryImpl(context));
648 } // namespace browsenodefactory
650 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */