Avoid potential negative array index access to cached text.
[LibreOffice.git] / extensions / source / propctrlr / submissionhandler.cxx
blobf3cc5dad60db9c72e86e7cd00f7b51216cdba925
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 <sal/config.h>
22 #include "submissionhandler.hxx"
23 #include "formmetadata.hxx"
24 #include "formstrings.hxx"
25 #include "handlerhelper.hxx"
27 #include <com/sun/star/form/FormButtonType.hpp>
28 #include <com/sun/star/form/submission/XSubmissionSupplier.hpp>
29 #include <com/sun/star/inspection/XObjectInspectorUI.hpp>
30 #include <com/sun/star/lang/NullPointerException.hpp>
31 #include <tools/debug.hxx>
32 #include <comphelper/diagnose_ex.hxx>
35 namespace pcr
39 using namespace ::comphelper;
40 using namespace ::com::sun::star;
41 using namespace ::com::sun::star::uno;
42 using namespace ::com::sun::star::lang;
43 using namespace ::com::sun::star::beans;
44 using namespace ::com::sun::star::script;
45 using namespace ::com::sun::star::form;
46 using namespace ::com::sun::star::xforms;
47 using namespace ::com::sun::star::container;
48 using namespace ::com::sun::star::inspection;
51 //= SubmissionHelper
54 SubmissionHelper::SubmissionHelper( ::osl::Mutex& _rMutex, const Reference< XPropertySet >& _rxIntrospectee, const Reference< frame::XModel >& _rxContextDocument )
55 :EFormsHelper( _rMutex, _rxIntrospectee, _rxContextDocument )
57 OSL_ENSURE( canTriggerSubmissions( _rxIntrospectee, _rxContextDocument ),
58 "SubmissionHelper::SubmissionHelper: you should not have instantiated me!" );
62 bool SubmissionHelper::canTriggerSubmissions( const Reference< XPropertySet >& _rxControlModel,
63 const Reference< frame::XModel >& _rxContextDocument )
65 if ( !EFormsHelper::isEForm( _rxContextDocument ) )
66 return false;
68 try
70 Reference< submission::XSubmissionSupplier > xSubmissionSupp( _rxControlModel, UNO_QUERY );
71 if ( xSubmissionSupp.is() )
72 return true;
74 catch( const Exception& )
76 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "SubmissionHelper::canTriggerSubmissions" );
78 return false;
82 //= SubmissionPropertyHandler
85 SubmissionPropertyHandler::SubmissionPropertyHandler( const Reference< XComponentContext >& _rxContext )
86 :PropertyHandlerComponent( _rxContext )
87 ,OPropertyChangeListener( m_aMutex )
92 SubmissionPropertyHandler::~SubmissionPropertyHandler( )
94 disposeAdapter();
98 OUString SubmissionPropertyHandler::getImplementationName( )
100 return "com.sun.star.comp.extensions.SubmissionPropertyHandler";
104 Sequence< OUString > SubmissionPropertyHandler::getSupportedServiceNames( )
106 return { "com.sun.star.form.inspection.SubmissionPropertyHandler" };
110 Any SAL_CALL SubmissionPropertyHandler::getPropertyValue( const OUString& _rPropertyName )
112 ::osl::MutexGuard aGuard( m_aMutex );
113 PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) );
115 OSL_ENSURE(m_pHelper, "SubmissionPropertyHandler::getPropertyValue: inconsistency!");
116 // if we survived impl_getPropertyId_throwUnknownProperty, we should have a helper, since no helper implies no properties
118 Any aReturn;
121 switch ( nPropId )
123 case PROPERTY_ID_SUBMISSION_ID:
125 Reference< submission::XSubmissionSupplier > xSubmissionSupp( m_xComponent, UNO_QUERY );
126 OSL_ENSURE( xSubmissionSupp.is(), "SubmissionPropertyHandler::getPropertyValue: this should never happen ..." );
127 // this handler is not intended for components which are no XSubmissionSupplier
128 Reference< submission::XSubmission > xSubmission;
129 if ( xSubmissionSupp.is() )
130 xSubmission = xSubmissionSupp->getSubmission( );
131 aReturn <<= xSubmission;
133 break;
135 case PROPERTY_ID_XFORMS_BUTTONTYPE:
137 FormButtonType eType = FormButtonType_PUSH;
138 OSL_VERIFY( m_xComponent->getPropertyValue( PROPERTY_BUTTONTYPE ) >>= eType );
139 if ( ( eType != FormButtonType_PUSH ) && ( eType != FormButtonType_SUBMIT ) )
140 eType = FormButtonType_PUSH;
141 aReturn <<= eType;
143 break;
145 default:
146 OSL_FAIL( "SubmissionPropertyHandler::getPropertyValue: cannot handle this property!" );
147 break;
150 catch( const Exception& )
152 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "SubmissionPropertyHandler::getPropertyValue" );
155 return aReturn;
159 void SAL_CALL SubmissionPropertyHandler::setPropertyValue( const OUString& _rPropertyName, const Any& _rValue )
161 ::osl::MutexGuard aGuard( m_aMutex );
162 PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) );
164 OSL_ENSURE(m_pHelper, "SubmissionPropertyHandler::setPropertyValue: inconsistency!");
165 // if we survived impl_getPropertyId_throwUnknownProperty, we should have a helper, since no helper implies no properties
169 switch ( nPropId )
171 case PROPERTY_ID_SUBMISSION_ID:
173 Reference< submission::XSubmission > xSubmission;
174 OSL_VERIFY( _rValue >>= xSubmission );
176 Reference< submission::XSubmissionSupplier > xSubmissionSupp( m_xComponent, UNO_QUERY );
177 OSL_ENSURE( xSubmissionSupp.is(), "SubmissionPropertyHandler::setPropertyValue: this should never happen ..." );
178 // this handler is not intended for components which are no XSubmissionSupplier
179 if ( xSubmissionSupp.is() )
181 xSubmissionSupp->setSubmission( xSubmission );
182 impl_setContextDocumentModified_nothrow();
185 break;
187 case PROPERTY_ID_XFORMS_BUTTONTYPE:
188 m_xComponent->setPropertyValue( PROPERTY_BUTTONTYPE, _rValue );
189 break;
191 default:
192 OSL_FAIL( "SubmissionPropertyHandler::setPropertyValue: cannot handle this id!" );
195 catch( const Exception& )
197 TOOLS_WARN_EXCEPTION( "extensions.propctrlr", "SubmissionPropertyHandler::setPropertyValue" );
202 Sequence< OUString > SAL_CALL SubmissionPropertyHandler::getActuatingProperties( )
204 ::osl::MutexGuard aGuard( m_aMutex );
205 if (!m_pHelper)
206 return Sequence< OUString >();
208 Sequence<OUString> aReturn { PROPERTY_XFORMS_BUTTONTYPE };
209 return aReturn;
213 Sequence< OUString > SAL_CALL SubmissionPropertyHandler::getSupersededProperties( )
215 ::osl::MutexGuard aGuard( m_aMutex );
216 if (!m_pHelper)
217 return Sequence< OUString >();
219 Sequence< OUString > aReturn{ PROPERTY_TARGET_URL,
220 PROPERTY_TARGET_FRAME,
221 PROPERTY_BUTTONTYPE };
222 return aReturn;
226 void SubmissionPropertyHandler::onNewComponent()
228 if ( m_xPropChangeMultiplexer.is() )
230 m_xPropChangeMultiplexer->dispose();
231 m_xPropChangeMultiplexer.clear();
234 PropertyHandlerComponent::onNewComponent();
236 Reference< frame::XModel > xDocument( impl_getContextDocument_nothrow() );
237 DBG_ASSERT( xDocument.is(), "SubmissionPropertyHandler::onNewComponent: no document!" );
239 m_pHelper.reset();
241 if ( SubmissionHelper::canTriggerSubmissions( m_xComponent, xDocument ) )
243 m_pHelper.reset( new SubmissionHelper( m_aMutex, m_xComponent, xDocument ) );
245 m_xPropChangeMultiplexer = new OPropertyChangeMultiplexer( this, m_xComponent );
246 m_xPropChangeMultiplexer->addProperty( PROPERTY_BUTTONTYPE );
251 Sequence< Property > SubmissionPropertyHandler::doDescribeSupportedProperties() const
253 std::vector< Property > aProperties;
254 if (m_pHelper)
256 implAddPropertyDescription( aProperties, PROPERTY_SUBMISSION_ID, cppu::UnoType<submission::XSubmission>::get() );
257 implAddPropertyDescription( aProperties, PROPERTY_XFORMS_BUTTONTYPE, ::cppu::UnoType<FormButtonType>::get() );
259 if ( aProperties.empty() )
260 return Sequence< Property >();
261 return comphelper::containerToSequence(aProperties);
265 LineDescriptor SAL_CALL SubmissionPropertyHandler::describePropertyLine( const OUString& _rPropertyName,
266 const Reference< XPropertyControlFactory >& _rxControlFactory )
268 ::osl::MutexGuard aGuard( m_aMutex );
269 if ( !_rxControlFactory.is() )
270 throw NullPointerException();
271 if (!m_pHelper)
272 throw RuntimeException();
274 std::vector< OUString > aListEntries;
275 PropertyId nPropId( impl_getPropertyId_throwUnknownProperty( _rPropertyName ) );
276 switch ( nPropId )
278 case PROPERTY_ID_SUBMISSION_ID:
279 m_pHelper->getAllElementUINames(EFormsHelper::Submission, aListEntries, false);
280 break;
282 case PROPERTY_ID_XFORMS_BUTTONTYPE:
284 // available options are nearly the same as for the "normal" button type, but only the
285 // first two options
286 aListEntries = m_pInfoService->getPropertyEnumRepresentations( PROPERTY_ID_BUTTONTYPE );
287 aListEntries.resize( 2 );
289 break;
291 default:
292 OSL_FAIL( "SubmissionPropertyHandler::describePropertyLine: cannot handle this id!" );
293 return LineDescriptor();
296 LineDescriptor aDescriptor;
297 aDescriptor.Control = PropertyHandlerHelper::createListBoxControl( _rxControlFactory, std::move(aListEntries), false, true );
298 aDescriptor.DisplayName = m_pInfoService->getPropertyTranslation( nPropId );
299 aDescriptor.Category = "General";
300 aDescriptor.HelpURL = HelpIdUrl::getHelpURL( m_pInfoService->getPropertyHelpId( nPropId ) );
301 return aDescriptor;
305 void SAL_CALL SubmissionPropertyHandler::actuatingPropertyChanged( const OUString& _rActuatingPropertyName, const Any& _rNewValue, const Any& /*_rOldValue*/, const Reference< XObjectInspectorUI >& _rxInspectorUI, sal_Bool )
307 if ( !_rxInspectorUI.is() )
308 throw NullPointerException();
310 ::osl::MutexGuard aGuard( m_aMutex );
311 PropertyId nActuatingPropId( impl_getPropertyId_throwRuntime( _rActuatingPropertyName ) );
312 OSL_PRECOND(m_pHelper,
313 "SubmissionPropertyHandler::actuatingPropertyChanged: inconsistency!");
314 // if we survived impl_getPropertyId_throwRuntime, we should have a helper, since no helper implies no properties
316 switch ( nActuatingPropId )
318 case PROPERTY_ID_XFORMS_BUTTONTYPE:
320 FormButtonType eType = FormButtonType_PUSH;
321 OSL_VERIFY( _rNewValue >>= eType );
322 _rxInspectorUI->enablePropertyUI( PROPERTY_SUBMISSION_ID, eType == FormButtonType_SUBMIT );
324 break;
326 default:
327 OSL_FAIL( "SubmissionPropertyHandler::actuatingPropertyChanged: cannot handle this id!" );
332 Any SAL_CALL SubmissionPropertyHandler::convertToPropertyValue( const OUString& _rPropertyName, const Any& _rControlValue )
334 ::osl::MutexGuard aGuard( m_aMutex );
335 Any aPropertyValue;
337 OSL_ENSURE(
338 m_pHelper,
339 "SubmissionPropertyHandler::convertToPropertyValue: we have no SupportedProperties!");
340 if (!m_pHelper)
341 return aPropertyValue;
343 OUString sControlValue;
344 OSL_VERIFY( _rControlValue >>= sControlValue );
346 PropertyId nPropId( m_pInfoService->getPropertyId( _rPropertyName ) );
347 switch ( nPropId )
349 case PROPERTY_ID_SUBMISSION_ID:
351 Reference< XSubmission > xSubmission( m_pHelper->getModelElementFromUIName( EFormsHelper::Submission, sControlValue ), UNO_QUERY );
352 aPropertyValue <<= xSubmission;
354 break;
356 case PROPERTY_ID_XFORMS_BUTTONTYPE:
358 ::rtl::Reference< IPropertyEnumRepresentation > aEnumConversion(
359 new DefaultEnumRepresentation( *m_pInfoService, ::cppu::UnoType<FormButtonType>::get(), PROPERTY_ID_BUTTONTYPE ) );
360 // TODO/UNOize: make aEnumConversion a member?
361 aEnumConversion->getValueFromDescription( sControlValue, aPropertyValue );
363 break;
365 default:
366 OSL_FAIL( "SubmissionPropertyHandler::convertToPropertyValue: cannot handle this id!" );
369 return aPropertyValue;
373 Any SAL_CALL SubmissionPropertyHandler::convertToControlValue( const OUString& _rPropertyName, const Any& _rPropertyValue, const Type& _rControlValueType )
375 ::osl::MutexGuard aGuard( m_aMutex );
376 Any aControlValue;
378 OSL_ENSURE(
379 m_pHelper,
380 "SubmissionPropertyHandler::convertToControlValue: we have no SupportedProperties!");
381 if (!m_pHelper)
382 return aControlValue;
384 OSL_ENSURE( _rControlValueType.getTypeClass() == TypeClass_STRING,
385 "SubmissionPropertyHandler::convertToControlValue: all our controls should use strings for value exchange!" );
387 PropertyId nPropId( m_pInfoService->getPropertyId( _rPropertyName ) );
388 switch ( nPropId )
390 case PROPERTY_ID_SUBMISSION_ID:
392 Reference< XPropertySet > xSubmission( _rPropertyValue, UNO_QUERY );
393 if ( xSubmission.is() )
394 aControlValue <<= EFormsHelper::getModelElementUIName( EFormsHelper::Submission, xSubmission );
396 break;
398 case PROPERTY_ID_XFORMS_BUTTONTYPE:
400 ::rtl::Reference< IPropertyEnumRepresentation > aEnumConversion(
401 new DefaultEnumRepresentation( *m_pInfoService, _rPropertyValue.getValueType(), PROPERTY_ID_BUTTONTYPE ) );
402 // TODO/UNOize: make aEnumConversion a member?
403 aControlValue <<= aEnumConversion->getDescriptionForValue( _rPropertyValue );
405 break;
407 default:
408 OSL_FAIL( "SubmissionPropertyHandler::convertToControlValue: cannot handle this id!" );
411 return aControlValue;
415 void SubmissionPropertyHandler::_propertyChanged( const PropertyChangeEvent& _rEvent )
417 if ( _rEvent.PropertyName == PROPERTY_BUTTONTYPE )
418 firePropertyChange( PROPERTY_XFORMS_BUTTONTYPE, PROPERTY_ID_XFORMS_BUTTONTYPE, _rEvent.OldValue, _rEvent.NewValue );
422 } // namespace pcr
424 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
425 extensions_propctrlr_SubmissionPropertyHandler_get_implementation(
426 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
428 return cppu::acquire(new pcr::SubmissionPropertyHandler(context));
431 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */