tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / dbaccess / source / core / dataaccess / ContentHelper.cxx
blob6736e22d9bd6c56f8351c61857458efdd715b37b
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 .
20 #include <ContentHelper.hxx>
21 #include <rtl/ref.hxx>
22 #include <rtl/ustrbuf.hxx>
23 #include <ucbhelper/cancelcommandexecution.hxx>
24 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
25 #include <com/sun/star/lang/IllegalArgumentException.hpp>
26 #include <com/sun/star/lang/IllegalAccessException.hpp>
27 #include <com/sun/star/beans/IllegalTypeException.hpp>
28 #include <com/sun/star/beans/PropertyAttribute.hpp>
29 #include <com/sun/star/beans/PropertyValue.hpp>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <com/sun/star/container/ElementExistException.hpp>
32 #include <ucbhelper/propertyvalueset.hxx>
33 #include <ucbhelper/contentidentifier.hxx>
34 #include <comphelper/servicehelper.hxx>
35 #include <comphelper/diagnose_ex.hxx>
36 #include <sdbcoretools.hxx>
37 #include <stringconstants.hxx>
38 #include <strings.hxx>
40 #include <map>
41 #include <utility>
43 namespace dbaccess
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::ucb;
47 using namespace ::com::sun::star::beans;
48 using namespace ::com::sun::star::lang;
49 using namespace ::com::sun::star::sdbc;
50 using namespace ::com::sun::star::io;
51 using namespace ::com::sun::star::container;
52 using namespace ::cppu;
54 OContentHelper_Impl::OContentHelper_Impl()
55 : m_pDataSource(nullptr)
59 OContentHelper_Impl::~OContentHelper_Impl()
63 OContentHelper::OContentHelper(const Reference< XComponentContext >& _xORB
64 ,const Reference< XInterface >& _xParentContainer
65 ,TContentPtr _pImpl)
66 : OContentHelper_COMPBASE(m_aMutex)
67 ,m_aContentListeners(m_aMutex)
68 ,m_aPropertyChangeListeners(m_aMutex)
69 ,m_xParentContainer( _xParentContainer )
70 ,m_aContext( _xORB )
71 ,m_pImpl(std::move(_pImpl))
72 ,m_nCommandId(0)
76 void SAL_CALL OContentHelper::disposing()
78 ::osl::MutexGuard aGuard(m_aMutex);
80 // say goodbye to our listeners
81 EventObject aEvt(*this);
82 m_aContentListeners.disposeAndClear(aEvt);
84 m_xParentContainer = nullptr;
87 OUString SAL_CALL OContentHelper::getImplementationName()
89 return u"com.sun.star.comp.sdb.Content"_ustr;
91 sal_Bool SAL_CALL OContentHelper::supportsService(const OUString& _rServiceName)
93 const css::uno::Sequence< OUString > aSupported(getSupportedServiceNames());
94 for (const OUString& s : aSupported)
95 if (s == _rServiceName)
96 return true;
98 return false;
100 css::uno::Sequence< OUString > SAL_CALL OContentHelper::getSupportedServiceNames()
102 return { u"com.sun.star.ucb.Content"_ustr };
106 css::uno::Sequence<sal_Int8> OContentHelper::getImplementationId()
108 return css::uno::Sequence<sal_Int8>();
111 // XContent
112 Reference< XContentIdentifier > SAL_CALL OContentHelper::getIdentifier( )
114 ::osl::MutexGuard aGuard(m_aMutex);
115 OUString aIdentifier( "private:" + impl_getHierarchicalName( true ) );
116 return new ::ucbhelper::ContentIdentifier( aIdentifier );
119 OUString OContentHelper::impl_getHierarchicalName( bool _includingRootContainer ) const
121 OUStringBuffer aHierarchicalName( m_pImpl->m_aProps.aTitle );
122 Reference< XInterface > xParent = m_xParentContainer;
123 while( xParent.is() )
125 Reference<XPropertySet> xProp( xParent, UNO_QUERY );
126 Reference< XChild > xChild( xParent, UNO_QUERY );
127 xParent.set( xChild.is() ? xChild->getParent() : Reference< XInterface >(), UNO_QUERY );
128 if ( xProp.is() && xParent.is() )
130 OUString sName;
131 xProp->getPropertyValue( PROPERTY_NAME ) >>= sName;
133 OUString sPrevious = aHierarchicalName.makeStringAndClear();
134 aHierarchicalName.append( sName + "/" + sPrevious );
137 OUString sHierarchicalName( aHierarchicalName.makeStringAndClear() );
138 if ( !_includingRootContainer )
139 sHierarchicalName = sHierarchicalName.copy( sHierarchicalName.indexOf( '/' ) + 1 );
140 return sHierarchicalName;
143 OUString SAL_CALL OContentHelper::getContentType()
145 ::osl::MutexGuard aGuard(m_aMutex);
147 if ( !m_pImpl->m_aProps.aContentType )
148 { // content type not yet retrieved
149 m_pImpl->m_aProps.aContentType = determineContentType();
152 return *m_pImpl->m_aProps.aContentType;
155 void SAL_CALL OContentHelper::addContentEventListener( const Reference< XContentEventListener >& _rxListener )
157 ::osl::MutexGuard aGuard(m_aMutex);
158 if ( _rxListener.is() )
159 m_aContentListeners.addInterface(_rxListener);
162 void SAL_CALL OContentHelper::removeContentEventListener( const Reference< XContentEventListener >& _rxListener )
164 ::osl::MutexGuard aGuard(m_aMutex);
165 if (_rxListener.is())
166 m_aContentListeners.removeInterface(_rxListener);
169 // XCommandProcessor
170 sal_Int32 SAL_CALL OContentHelper::createCommandIdentifier( )
172 ::osl::MutexGuard aGuard(m_aMutex);
173 // Just increase counter on every call to generate an identifier.
174 return ++m_nCommandId;
177 Any SAL_CALL OContentHelper::execute( const Command& aCommand, sal_Int32 /*CommandId*/, const Reference< XCommandEnvironment >& Environment )
179 Any aRet;
180 if ( aCommand.Name == "getPropertyValues" )
182 // getPropertyValues
184 Sequence< Property > Properties;
185 if ( !( aCommand.Argument >>= Properties ) )
187 OSL_FAIL( "Wrong argument type!" );
188 ucbhelper::cancelCommandExecution(
189 Any( IllegalArgumentException(
190 OUString(),
191 static_cast< cppu::OWeakObject * >( this ),
192 -1 ) ),
193 Environment );
194 // Unreachable
196 aRet <<= getPropertyValues( Properties);
198 else if ( aCommand.Name == "setPropertyValues" )
200 // setPropertyValues
202 Sequence< PropertyValue > aProperties;
203 if ( !( aCommand.Argument >>= aProperties ) )
205 OSL_FAIL( "Wrong argument type!" );
206 ucbhelper::cancelCommandExecution(
207 Any( IllegalArgumentException(
208 OUString(),
209 static_cast< cppu::OWeakObject * >( this ),
210 -1 ) ),
211 Environment );
212 // Unreachable
215 if ( !aProperties.hasElements() )
217 OSL_FAIL( "No properties!" );
218 ucbhelper::cancelCommandExecution(
219 Any( IllegalArgumentException(
220 OUString(),
221 static_cast< cppu::OWeakObject * >( this ),
222 -1 ) ),
223 Environment );
224 // Unreachable
227 aRet <<= setPropertyValues( aProperties );
229 else if ( aCommand.Name == "getPropertySetInfo" )
231 // getPropertySetInfo
233 Reference<XPropertySet> xProp(*this,UNO_QUERY);
234 if ( xProp.is() )
235 aRet <<= xProp->getPropertySetInfo();
236 // aRet <<= getPropertySetInfo(); // TODO
238 else
240 // Unsupported command
242 OSL_FAIL( "Content::execute - unsupported command!" );
244 ucbhelper::cancelCommandExecution(
245 Any( UnsupportedCommandException(
246 OUString(),
247 static_cast< cppu::OWeakObject * >( this ) ) ),
248 Environment );
249 // Unreachable
252 return aRet;
255 void SAL_CALL OContentHelper::abort( sal_Int32 /*CommandId*/ )
259 // XPropertiesChangeNotifier
260 void SAL_CALL OContentHelper::addPropertiesChangeListener( const Sequence< OUString >& PropertyNames, const Reference< XPropertiesChangeListener >& Listener )
262 ::osl::MutexGuard aGuard(m_aMutex);
263 if (!PropertyNames.hasElements())
265 // Note: An empty sequence means a listener for "all" properties.
266 m_aPropertyChangeListeners.addInterface(OUString(), Listener );
268 else
270 for (auto& rName : PropertyNames)
271 if ( !rName.isEmpty() )
272 m_aPropertyChangeListeners.addInterface(rName, Listener );
276 void SAL_CALL OContentHelper::removePropertiesChangeListener( const Sequence< OUString >& PropertyNames, const Reference< XPropertiesChangeListener >& Listener )
278 ::osl::MutexGuard aGuard(m_aMutex);
279 if (!PropertyNames.hasElements())
281 // Note: An empty sequence means a listener for "all" properties.
282 m_aPropertyChangeListeners.removeInterface( OUString(), Listener );
284 else
286 for (auto& rName : PropertyNames)
287 if ( !rName.isEmpty() )
288 m_aPropertyChangeListeners.removeInterface( rName, Listener );
292 // XPropertyContainer
293 void SAL_CALL OContentHelper::addProperty( const OUString& /*Name*/, sal_Int16 /*Attributes*/, const Any& /*DefaultValue*/ )
295 OSL_FAIL( "OContentHelper::addProperty: not implemented!" );
298 void SAL_CALL OContentHelper::removeProperty( const OUString& /*Name*/ )
300 OSL_FAIL( "OContentHelper::removeProperty: not implemented!" );
303 // XInitialization
304 void SAL_CALL OContentHelper::initialize( const Sequence< Any >& _aArguments )
306 for (auto& arg : _aArguments)
308 PropertyValue aValue;
309 arg >>= aValue;
310 if ( aValue.Name == "Parent" )
312 m_xParentContainer.set(aValue.Value,UNO_QUERY);
314 else if ( aValue.Name == PROPERTY_NAME )
316 aValue.Value >>= m_pImpl->m_aProps.aTitle;
318 else if ( aValue.Name == PROPERTY_PERSISTENT_NAME )
320 aValue.Value >>= m_pImpl->m_aProps.sPersistentName;
325 Sequence< Any > OContentHelper::setPropertyValues(const Sequence< PropertyValue >& rValues )
327 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
329 Sequence< Any > aRet( rValues.getLength() );
330 auto aRetRange = asNonConstRange(aRet);
331 Sequence< PropertyChangeEvent > aChanges( rValues.getLength() );
332 sal_Int32 nChanged = 0;
334 PropertyChangeEvent aEvent;
335 aEvent.Source = static_cast< cppu::OWeakObject * >( this );
336 aEvent.Further = false;
337 aEvent.PropertyHandle = -1;
339 for (sal_Int32 n = 0; n < rValues.getLength(); ++n)
341 const PropertyValue& rValue = rValues[n];
343 if ( rValue.Name == "ContentType" || rValue.Name == "IsDocument" || rValue.Name == "IsFolder" )
345 // Read-only property!
346 aRetRange[ n ] <<= IllegalAccessException(u"Property is read-only!"_ustr,
347 static_cast< cppu::OWeakObject * >( this ) );
349 else if ( rValue.Name == "Title" )
351 OUString aNewValue;
352 if ( rValue.Value >>= aNewValue )
354 if ( aNewValue != m_pImpl->m_aProps.aTitle )
356 aEvent.PropertyName = rValue.Name;
357 aEvent.OldValue <<= m_pImpl->m_aProps.aTitle;
361 impl_rename_throw( aNewValue ,false);
362 OSL_ENSURE( m_pImpl->m_aProps.aTitle == aNewValue, "OContentHelper::setPropertyValues('Title'): rename did not work!" );
364 aEvent.NewValue <<= aNewValue;
365 aChanges.getArray()[ nChanged ] = aEvent;
366 nChanged++;
368 catch( const Exception& )
370 TOOLS_WARN_EXCEPTION( "dbaccess", "OContentHelper::setPropertyValues('Title'): caught an exception while renaming!" );
373 else
375 // Old value equals new value. No error!
378 else
380 aRetRange[ n ] <<= IllegalTypeException(u"Property value has wrong type!"_ustr,
381 static_cast< cppu::OWeakObject * >( this ) );
385 else
387 aRetRange[ n ] <<= Exception(u"No property set for storing the value!"_ustr,
388 static_cast< cppu::OWeakObject * >( this ) );
392 if ( nChanged > 0 )
394 notifyDataSourceModified();
395 aGuard.clear();
396 aChanges.realloc( nChanged );
397 notifyPropertiesChange( aChanges );
400 return aRet;
403 // static
404 Reference< XRow > OContentHelper::getPropertyValues( const Sequence< Property >& rProperties)
406 // Note: Empty sequence means "get values of all supported properties".
408 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow = new ::ucbhelper::PropertyValueSet( m_aContext );
410 if (rProperties.hasElements())
412 for (auto& rProp : rProperties)
414 // Process Core properties.
416 if ( rProp.Name == "ContentType" )
418 xRow->appendString ( rProp, getContentType() );
420 else if ( rProp.Name == "Title" )
422 xRow->appendString ( rProp, m_pImpl->m_aProps.aTitle );
424 else if ( rProp.Name == "IsDocument" )
426 xRow->appendBoolean( rProp, m_pImpl->m_aProps.bIsDocument );
428 else if ( rProp.Name == "IsFolder" )
430 xRow->appendBoolean( rProp, m_pImpl->m_aProps.bIsFolder );
432 else
433 xRow->appendVoid(rProp);
436 else
438 // Append all Core Properties.
439 xRow->appendString (
440 Property( u"ContentType"_ustr, -1,
441 cppu::UnoType<OUString>::get(),
442 PropertyAttribute::BOUND
443 | PropertyAttribute::READONLY ),
444 getContentType() );
445 xRow->appendString (
446 Property( u"Title"_ustr, -1,
447 cppu::UnoType<OUString>::get(),
448 PropertyAttribute::BOUND ),
449 m_pImpl->m_aProps.aTitle );
450 xRow->appendBoolean(
451 Property( u"IsDocument"_ustr, -1,
452 cppu::UnoType<bool>::get(),
453 PropertyAttribute::BOUND
454 | PropertyAttribute::READONLY ),
455 m_pImpl->m_aProps.bIsDocument );
456 xRow->appendBoolean(
457 Property( u"IsFolder"_ustr, -1,
458 cppu::UnoType<bool>::get(),
459 PropertyAttribute::BOUND
460 | PropertyAttribute::READONLY ),
461 m_pImpl->m_aProps.bIsFolder );
463 // @@@ Append other properties supported directly.
466 return xRow;
469 void OContentHelper::notifyPropertiesChange( const Sequence< PropertyChangeEvent >& evt ) const
472 sal_Int32 nCount = evt.getLength();
473 if ( !nCount )
474 return;
476 // First, notify listeners interested in changes of every property.
477 comphelper::OInterfaceContainerHelper3<XPropertiesChangeListener>* pAllPropsContainer = m_aPropertyChangeListeners.getContainer( OUString() );
478 if ( pAllPropsContainer )
479 pAllPropsContainer->notifyEach( &XPropertiesChangeListener::propertiesChange, evt );
481 typedef std::map< XPropertiesChangeListener*, Sequence< PropertyChangeEvent > > PropertiesEventListenerMap;
482 PropertiesEventListenerMap aListeners;
484 for (sal_Int32 n = 0; n < nCount; ++n)
486 const PropertyChangeEvent& rEvent = evt[n];
487 const OUString& rName = rEvent.PropertyName;
489 comphelper::OInterfaceContainerHelper3<XPropertiesChangeListener>* pPropsContainer = m_aPropertyChangeListeners.getContainer( rName );
490 if ( pPropsContainer )
492 comphelper::OInterfaceIteratorHelper3 aIter( *pPropsContainer );
493 while ( aIter.hasMoreElements() )
495 Sequence< PropertyChangeEvent >* propertyEvents;
497 XPropertiesChangeListener* pListener = aIter.next().get();
498 PropertiesEventListenerMap::iterator it = aListeners.find( pListener );
499 if ( it == aListeners.end() )
501 // Not in map - create and insert new entry.
502 auto pair = aListeners.emplace( pListener, Sequence< PropertyChangeEvent >( nCount ));
503 propertyEvents = &pair.first->second;
505 else
506 propertyEvents = &(*it).second;
508 asNonConstRange(*propertyEvents)[n] = rEvent;
513 // Notify listeners.
514 for (auto & rPair : aListeners)
516 XPropertiesChangeListener* pListener = rPair.first;
517 Sequence< PropertyChangeEvent >& rSeq = rPair.second;
519 // Propagate event.
520 pListener->propertiesChange( rSeq );
524 Reference< XInterface > SAL_CALL OContentHelper::getParent( )
526 ::osl::MutexGuard aGuard(m_aMutex);
527 return m_xParentContainer;
530 void SAL_CALL OContentHelper::setParent( const Reference< XInterface >& _xParent )
532 ::osl::MutexGuard aGuard(m_aMutex);
533 m_xParentContainer = _xParent;
536 void OContentHelper::impl_rename_throw(const OUString& _sNewName,bool _bNotify )
538 osl::ClearableGuard< osl::Mutex > aGuard(m_aMutex);
539 if ( _sNewName == m_pImpl->m_aProps.aTitle )
540 return;
543 Sequence<PropertyChangeEvent> aChanges{
544 { /* Source */ static_cast<cppu::OWeakObject*>(this),
545 /* PropertyName */ PROPERTY_NAME,
546 /* Further */ false,
547 /* PropertyHandle */ PROPERTY_ID_NAME,
548 /* OldValue */ Any(m_pImpl->m_aProps.aTitle),
549 /* NewValue */ Any(_sNewName) }
552 aGuard.clear();
554 m_pImpl->m_aProps.aTitle = _sNewName;
555 if ( _bNotify )
556 notifyPropertiesChange( aChanges );
557 notifyDataSourceModified();
559 catch(const PropertyVetoException&)
561 throw ElementExistException(_sNewName,*this);
565 void SAL_CALL OContentHelper::rename( const OUString& newName )
568 impl_rename_throw(newName);
572 void OContentHelper::notifyDataSourceModified()
574 ::dbaccess::notifyDataSourceModified(m_xParentContainer);
577 } // namespace dbaccess
579 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */