diff options
Diffstat (limited to 'reportdesign/source/ui/inspection')
-rw-r--r-- | reportdesign/source/ui/inspection/DataProviderHandler.cxx | 513 | ||||
-rw-r--r-- | reportdesign/source/ui/inspection/DefaultInspection.cxx | 214 | ||||
-rw-r--r-- | reportdesign/source/ui/inspection/GeometryHandler.cxx | 2215 | ||||
-rw-r--r-- | reportdesign/source/ui/inspection/ReportComponentHandler.cxx | 199 | ||||
-rw-r--r-- | reportdesign/source/ui/inspection/metadata.cxx | 293 |
5 files changed, 3434 insertions, 0 deletions
diff --git a/reportdesign/source/ui/inspection/DataProviderHandler.cxx b/reportdesign/source/ui/inspection/DataProviderHandler.cxx new file mode 100644 index 000000000..9e789db4c --- /dev/null +++ b/reportdesign/source/ui/inspection/DataProviderHandler.cxx @@ -0,0 +1,513 @@ +/* -*- 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 <sal/config.h> + +#include <string_view> + +#include <DataProviderHandler.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/types.hxx> +#include <comphelper/propertysequence.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <strings.hxx> +#include <com/sun/star/form/inspection/FormComponentPropertyHandler.hpp> +#include <com/sun/star/inspection/PropertyControlType.hpp> +#include <com/sun/star/inspection/PropertyLineElement.hpp> +#include <com/sun/star/lang/NullPointerException.hpp> +#include <com/sun/star/chart/ChartDataRowSource.hpp> +#include <com/sun/star/chart2/FormattedString.hpp> +#include <com/sun/star/chart2/XTitled.hpp> +#include <com/sun/star/chart2/XTitle.hpp> +#include <com/sun/star/chart2/data/XDataReceiver.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/report/XReportDefinition.hpp> +#include <com/sun/star/script/Converter.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <metadata.hxx> +#include <osl/mutex.hxx> +#include <tools/diagnose_ex.h> +#include <core_resource.hxx> +#include <helpids.h> +#include <strings.hrc> +#include <PropertyForward.hxx> + +namespace rptui +{ + +using namespace ::com::sun::star; + +DataProviderHandler::DataProviderHandler(uno::Reference< uno::XComponentContext > const & context) + :DataProviderHandler_Base(m_aMutex) + ,m_xContext(context) +{ + try + { + m_xFormComponentHandler = form::inspection::FormComponentPropertyHandler::create(m_xContext); + m_xTypeConverter = script::Converter::create(m_xContext); + + }catch(const uno::Exception &) + { + } +} + +OUString SAL_CALL DataProviderHandler::getImplementationName( ) +{ + return "com.sun.star.comp.report.DataProviderHandler"; +} + +sal_Bool SAL_CALL DataProviderHandler::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +uno::Sequence< OUString > SAL_CALL DataProviderHandler::getSupportedServiceNames( ) +{ + return { "com.sun.star.report.inspection.DataProviderHandler" }; +} + +// override WeakComponentImplHelperBase::disposing() +// This function is called upon disposing the component, +// if your component needs special work when it becomes +// disposed, do it here. +void SAL_CALL DataProviderHandler::disposing() +{ + ::comphelper::disposeComponent(m_xFormComponentHandler); + ::comphelper::disposeComponent( m_xMasterDetails ); + ::comphelper::disposeComponent(m_xTypeConverter); +} +void SAL_CALL DataProviderHandler::addEventListener(const uno::Reference< lang::XEventListener > & xListener) +{ + m_xFormComponentHandler->addEventListener(xListener); +} + +void SAL_CALL DataProviderHandler::removeEventListener(const uno::Reference< lang::XEventListener > & aListener) +{ + m_xFormComponentHandler->removeEventListener(aListener); +} + +// inspection::XPropertyHandler: + +/********************************************************************************/ +void SAL_CALL DataProviderHandler::inspect(const uno::Reference< uno::XInterface > & Component) +{ + try + { + uno::Reference< container::XNameContainer > xNameCont(Component,uno::UNO_QUERY); + static const OUStringLiteral sFormComponent(u"FormComponent"); + if ( xNameCont->hasByName(sFormComponent) ) + { + uno::Reference<beans::XPropertySet> xProp(xNameCont->getByName(sFormComponent),uno::UNO_QUERY); + static const OUStringLiteral sModel(u"Model"); + if ( xProp.is() && xProp->getPropertySetInfo()->hasPropertyByName(sModel) ) + { + m_xChartModel.set(xProp->getPropertyValue(sModel),uno::UNO_QUERY); + if ( m_xChartModel.is() ) + m_xFormComponent = m_xChartModel->getDataProvider(); + } + } + m_xDataProvider.set(m_xFormComponent,uno::UNO_QUERY); + m_xReportComponent.set( xNameCont->getByName("ReportComponent"), uno::UNO_QUERY ); + if ( m_xDataProvider.is() ) + { + auto aNoConverter = std::make_shared<AnyConverter>(); + TPropertyNamePair aPropertyMediation; + aPropertyMediation.emplace( PROPERTY_MASTERFIELDS, TPropertyConverter(PROPERTY_MASTERFIELDS,aNoConverter) ); + aPropertyMediation.emplace( PROPERTY_DETAILFIELDS, TPropertyConverter(PROPERTY_DETAILFIELDS,aNoConverter) ); + + m_xMasterDetails = new OPropertyMediator( m_xDataProvider, m_xReportComponent, std::move(aPropertyMediation), true ); + } + } + catch(const uno::Exception &) + { + throw lang::NullPointerException(); + } + if ( m_xFormComponent.is() ) + { + m_xFormComponentHandler->inspect(m_xFormComponent); + } +} + +uno::Any SAL_CALL DataProviderHandler::getPropertyValue(const OUString & PropertyName) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + uno::Any aPropertyValue; + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + switch(nId) + { + case PROPERTY_ID_CHARTTYPE: + // TODO: We need a possibility to get the UI of the selected chart type + // LEM: this business of ignoring ChartType seems very fishy! + //if( m_xChartModel.is() ) + //{ + // uno::Reference< chart2::XDiagram > xDiagram( m_xChartModel->getFirstDiagram() ); + // if( xDiagram.is() ) + // { + // OUString sChartTypes; + // uno::Reference< chart2::XCoordinateSystemContainer > xCooSysCnt( xDiagram, uno::UNO_QUERY_THROW ); + // const uno::Sequence< uno::Reference< chart2::XCoordinateSystem > > aCooSysSeq( xCooSysCnt->getCoordinateSystems()); + // const uno::Reference< chart2::XCoordinateSystem >* pIter = aCooSysSeq.getConstArray(); + // const uno::Reference< chart2::XCoordinateSystem >* pEnd = pIter + aCooSysSeq.getLength(); + // for(;pIter != pEnd;++pIter) + // { + // const uno::Reference< chart2::XChartTypeContainer > xCTCnt( *pIter, uno::UNO_QUERY_THROW ); + // const uno::Sequence< uno::Reference< chart2::XChartType > > aCTSeq( xCTCnt->getChartTypes()); + // const uno::Reference< chart2::XChartType >* pChartTypeIter = aCTSeq.getConstArray(); + // const uno::Reference< chart2::XChartType >* pChartTypeEnd = pChartTypeIter + aCTSeq.getLength(); + // for(;pChartTypeIter != pChartTypeEnd;++pChartTypeIter) + // { + // sChartTypes += (*pChartTypeIter)->getChartType(); + // sChartTypes += ";"; + // } + // } + // aPropertyValue;// <<= sChartTypes; + // } + //} + break; + case PROPERTY_ID_PREVIEW_COUNT: + if (m_xDataProvider) // tdf#117159 crash with chart in database report otherwise + aPropertyValue <<= m_xDataProvider->getRowLimit(); + break; + default: + aPropertyValue = m_xFormComponentHandler->getPropertyValue( PropertyName ); + break; + } + return aPropertyValue; +} + +void SAL_CALL DataProviderHandler::setPropertyValue(const OUString & PropertyName, const uno::Any & Value) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + switch(nId) + { + case PROPERTY_ID_CHARTTYPE: + break; + case PROPERTY_ID_PREVIEW_COUNT: + m_xDataProvider->setPropertyValue(PropertyName,Value); + break; + default: + m_xFormComponentHandler->setPropertyValue(PropertyName, Value); + break; + } +} + +void DataProviderHandler::impl_updateChartTitle_throw(const uno::Any& _aValue) +{ + uno::Reference<chart2::XTitled> xTitled(m_xChartModel,uno::UNO_QUERY); + if ( !xTitled.is() ) + return; + + uno::Reference<chart2::XTitle> xTitle = xTitled->getTitleObject(); + if ( !xTitle.is() ) + { + xTitle.set(m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.chart2.Title",m_xContext),uno::UNO_QUERY); + xTitled->setTitleObject(xTitle); + } + if ( xTitle.is() ) + { + uno::Reference< chart2::XFormattedString2> xFormatted = chart2::FormattedString::create(m_xContext); + OUString sStr; + _aValue >>= sStr; + xFormatted->setString(sStr); + xTitle->setText({ xFormatted }); + } +} + +beans::PropertyState SAL_CALL DataProviderHandler::getPropertyState(const OUString & PropertyName) +{ + return m_xFormComponentHandler->getPropertyState(PropertyName); +} + +inspection::LineDescriptor SAL_CALL DataProviderHandler::describePropertyLine(const OUString & PropertyName, const uno::Reference< inspection::XPropertyControlFactory > & _xControlFactory) +{ + inspection::LineDescriptor aOut; + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + switch(nId) + { + case PROPERTY_ID_CHARTTYPE: + aOut.PrimaryButtonId = UID_RPT_PROP_CHARTTYPE_DLG; + aOut.Control = _xControlFactory->createPropertyControl(inspection::PropertyControlType::TextField , true); + aOut.HasPrimaryButton = true; + break; + case PROPERTY_ID_PREVIEW_COUNT: + aOut.Control = _xControlFactory->createPropertyControl(inspection::PropertyControlType::NumericField , false); + break; + case PROPERTY_ID_MASTERFIELDS: + case PROPERTY_ID_DETAILFIELDS: + aOut.Control = _xControlFactory->createPropertyControl(inspection::PropertyControlType::StringListField , false); + aOut.PrimaryButtonId = UID_RPT_PROP_DLG_LINKFIELDS; + aOut.HasPrimaryButton = true; + break; + default: + aOut = m_xFormComponentHandler->describePropertyLine(PropertyName, _xControlFactory); + } + if ( nId != -1 ) + { + aOut.Category = (OPropertyInfoService::getPropertyUIFlags(nId ) & PropUIFlags::DataProperty) ? + std::u16string_view(u"Data") + : + std::u16string_view(u"General"); + aOut.HelpURL = HelpIdUrl::getHelpURL( OPropertyInfoService::getPropertyHelpId( nId ) ); + aOut.DisplayName = OPropertyInfoService::getPropertyTranslation(nId); + } + return aOut; +} + +uno::Any SAL_CALL DataProviderHandler::convertToPropertyValue(const OUString & _rPropertyValue, const uno::Any & _rControlValue) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + uno::Any aPropertyValue( _rControlValue ); + const sal_Int32 nId = OPropertyInfoService::getPropertyId(_rPropertyValue); + switch(nId) + { + case PROPERTY_ID_CHARTTYPE: + break; + case PROPERTY_ID_PREVIEW_COUNT: + try + { + aPropertyValue = m_xTypeConverter->convertTo( _rControlValue, ::cppu::UnoType<sal_Int32>::get()); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "DataProviderHandler::convertToPropertyValue: caught an exception while converting via TypeConverter!" ); + } + break; + case PROPERTY_ID_MASTERFIELDS: + case PROPERTY_ID_DETAILFIELDS: + break; + default: + aPropertyValue = m_xFormComponentHandler->convertToPropertyValue(_rPropertyValue, _rControlValue); + } + return aPropertyValue; +} + +uno::Any SAL_CALL DataProviderHandler::convertToControlValue(const OUString & _rPropertyName, const uno::Any & _rPropertyValue, const uno::Type & ControlValueType) +{ + uno::Any aControlValue( _rPropertyValue ); + if ( !aControlValue.hasValue() ) + // NULL is converted to NULL + return aControlValue; + + ::osl::MutexGuard aGuard( m_aMutex ); + const sal_Int32 nId = OPropertyInfoService::getPropertyId(_rPropertyName); + switch(nId) + { + case PROPERTY_ID_CHARTTYPE: + break; + case PROPERTY_ID_MASTERFIELDS: + case PROPERTY_ID_DETAILFIELDS: + case PROPERTY_ID_PREVIEW_COUNT: + try + { + aControlValue = m_xTypeConverter->convertTo( _rPropertyValue, ControlValueType); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "GeometryHandler::convertToPropertyValue: caught an exception while converting via TypeConverter!" ); + } + break; + default: + aControlValue = m_xFormComponentHandler->convertToControlValue(_rPropertyName, _rPropertyValue, ControlValueType); + } + return aControlValue; +} + +void SAL_CALL DataProviderHandler::addPropertyChangeListener(const uno::Reference< beans::XPropertyChangeListener > & Listener) +{ + m_xFormComponentHandler->addPropertyChangeListener(Listener); +} + +void SAL_CALL DataProviderHandler::removePropertyChangeListener(const uno::Reference< beans::XPropertyChangeListener > & _rxListener) +{ + m_xFormComponentHandler->removePropertyChangeListener(_rxListener); +} + +uno::Sequence< beans::Property > SAL_CALL DataProviderHandler::getSupportedProperties() +{ + ::std::vector< beans::Property > aNewProps; + if( m_xChartModel.is() ) + { + rptui::OPropertyInfoService::getExcludeProperties( aNewProps, m_xFormComponentHandler ); + beans::Property aValue; + static const std::u16string_view s_pProperties[] = + { + u"" PROPERTY_CHARTTYPE + ,u"" PROPERTY_MASTERFIELDS + ,u"" PROPERTY_DETAILFIELDS + ,u"" PROPERTY_PREVIEW_COUNT + }; + + for (const auto & rName : s_pProperties) + { + aValue.Name = rName; + aNewProps.push_back(aValue); + } + } + return uno::Sequence< beans::Property >(aNewProps.data(), aNewProps.size()); +} + +uno::Sequence< OUString > SAL_CALL DataProviderHandler::getSupersededProperties() +{ + uno::Sequence< OUString > aRet { PROPERTY_TITLE }; // have a look at OPropertyInfoService::getExcludeProperties + return aRet; +} + +uno::Sequence< OUString > SAL_CALL DataProviderHandler::getActuatingProperties() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + uno::Sequence< OUString > aSeq { PROPERTY_TITLE }; + return ::comphelper::concatSequences(m_xFormComponentHandler->getActuatingProperties(),aSeq); +} + +sal_Bool SAL_CALL DataProviderHandler::isComposable( const OUString& _rPropertyName ) +{ + return OPropertyInfoService::isComposable( _rPropertyName, m_xFormComponentHandler ); +} + +inspection::InteractiveSelectionResult SAL_CALL DataProviderHandler::onInteractivePropertySelection(const OUString & PropertyName, sal_Bool Primary, uno::Any & out_Data, const uno::Reference< inspection::XObjectInspectorUI > & _rxInspectorUI) +{ + if ( !_rxInspectorUI.is() ) + throw lang::NullPointerException(); + + inspection::InteractiveSelectionResult eResult = inspection::InteractiveSelectionResult_Cancelled; + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + switch(nId) + { + case PROPERTY_ID_CHARTTYPE: + if ( impl_dialogChartType_nothrow(aGuard) ) + eResult = inspection::InteractiveSelectionResult_ObtainedValue; + break; + case PROPERTY_ID_MASTERFIELDS: + case PROPERTY_ID_DETAILFIELDS: + if ( impl_dialogLinkedFields_nothrow( aGuard ) ) + eResult = inspection::InteractiveSelectionResult_Success; + break; + default: + eResult = m_xFormComponentHandler->onInteractivePropertySelection(PropertyName, Primary, out_Data, _rxInspectorUI); + } + + return eResult; +} + +void SAL_CALL DataProviderHandler::actuatingPropertyChanged(const OUString & ActuatingPropertyName, const uno::Any & NewValue, const uno::Any & OldValue, const uno::Reference< inspection::XObjectInspectorUI > & InspectorUI, sal_Bool FirstTimeInit) +{ + osl::MutexGuard aGuard( m_aMutex ); + + if ( ActuatingPropertyName == PROPERTY_COMMAND ) + { + if ( NewValue != OldValue ) + { + uno::Reference< report::XReportDefinition> xReport = m_xReportComponent->getSection()->getReportDefinition(); + bool bDoEnableMasterDetailFields = xReport.is() && !xReport->getCommand().isEmpty() && !m_xDataProvider->getCommand().isEmpty(); + InspectorUI->enablePropertyUIElements( PROPERTY_DETAILFIELDS, inspection::PropertyLineElement::PrimaryButton, bDoEnableMasterDetailFields ); + InspectorUI->enablePropertyUIElements( PROPERTY_MASTERFIELDS, inspection::PropertyLineElement::PrimaryButton, bDoEnableMasterDetailFields ); + + bool bModified = xReport->isModified(); + // this fills the chart again + ::comphelper::NamedValueCollection aArgs; + aArgs.put( "CellRangeRepresentation", uno::Any( OUString( "all" ) ) ); + aArgs.put( "HasCategories", uno::Any( true ) ); + aArgs.put( "FirstCellAsLabel", uno::Any( true ) ); + aArgs.put( "DataRowSource", uno::Any( chart::ChartDataRowSource_COLUMNS ) ); + uno::Reference< chart2::data::XDataReceiver > xReceiver(m_xChartModel,uno::UNO_QUERY_THROW); + xReceiver->setArguments( aArgs.getPropertyValues() ); + if ( !bModified ) + xReport->setModified(false); + } + m_xFormComponentHandler->actuatingPropertyChanged(ActuatingPropertyName, NewValue, OldValue, InspectorUI, FirstTimeInit); + } + else if ( ActuatingPropertyName == PROPERTY_TITLE ) + { + if ( NewValue != OldValue ) + impl_updateChartTitle_throw(NewValue); + } + else + { + const sal_Int32 nId = OPropertyInfoService::getPropertyId(ActuatingPropertyName); + switch(nId) + { + + case PROPERTY_ID_MASTERFIELDS: + break; + case PROPERTY_ID_DETAILFIELDS: + break; + default: + m_xFormComponentHandler->actuatingPropertyChanged(ActuatingPropertyName, NewValue, OldValue, InspectorUI, FirstTimeInit); + } + } +} + +sal_Bool SAL_CALL DataProviderHandler::suspend(sal_Bool Suspend) +{ + return m_xFormComponentHandler->suspend(Suspend); +} +bool DataProviderHandler::impl_dialogLinkedFields_nothrow( ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const +{ + uno::Sequence<uno::Any> aSeq(comphelper::InitAnyPropertySequence( + { + {"ParentWindow", m_xContext->getValueByName("DialogParentWindow")}, + {"Detail", uno::Any(m_xDataProvider)}, + {"Master", uno::Any(m_xReportComponent->getSection()->getReportDefinition())}, + {"Explanation", uno::Any(RptResId(TranslateId(nullptr, RID_STR_EXPLANATION)))}, + {"DetailLabel", uno::Any(RptResId(RID_STR_DETAILLABEL))}, + {"MasterLabel", uno::Any(RptResId(RID_STR_MASTERLABEL))}, + })); + + uno::Reference< ui::dialogs::XExecutableDialog > xDialog( + m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext( + "org.openoffice.comp.form.ui.MasterDetailLinkDialog", aSeq, m_xContext), + uno::UNO_QUERY); + + _rClearBeforeDialog.clear(); + return ( xDialog->execute() != 0 ); +} + +bool DataProviderHandler::impl_dialogChartType_nothrow( ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const +{ + uno::Sequence<uno::Any> aSeq(comphelper::InitAnyPropertySequence( + { + {"ParentWindow", m_xContext->getValueByName("DialogParentWindow")}, + {"ChartModel", uno::Any(m_xChartModel)} + })); + + uno::Reference< ui::dialogs::XExecutableDialog > xDialog( + m_xContext->getServiceManager()->createInstanceWithArgumentsAndContext( + "com.sun.star.comp.chart2.ChartTypeDialog", aSeq, m_xContext), + uno::UNO_QUERY); + + _rClearBeforeDialog.clear(); + return ( xDialog->execute() != 0 ); +} + +} // namespace rptui + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +reportdesign_DataProviderHandler_get_implementation( + css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new rptui::DataProviderHandler(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inspection/DefaultInspection.cxx b/reportdesign/source/ui/inspection/DefaultInspection.cxx new file mode 100644 index 000000000..80269f433 --- /dev/null +++ b/reportdesign/source/ui/inspection/DefaultInspection.cxx @@ -0,0 +1,214 @@ +/* -*- 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 <DefaultInspection.hxx> +#include <com/sun/star/ucb/AlreadyInitializedException.hpp> +#include <com/sun/star/lang/IllegalArgumentException.hpp> +#include <strings.hrc> +#include <core_resource.hxx> +#include <helpids.h> +#include <cppuhelper/supportsservice.hxx> +#include <tools/debug.hxx> +#include <metadata.hxx> +#include <tools/urlobj.hxx> + + +namespace rptui +{ + OUString HelpIdUrl::getHelpURL( std::string_view sHelpId ) + { + OUString aTmp( OStringToOUString(sHelpId, RTL_TEXTENCODING_UTF8) ); + DBG_ASSERT( INetURLObject( aTmp ).GetProtocol() == INetProtocol::NotValid, "Wrong HelpId!" ); + return INET_HID_SCHEME + aTmp; + } + + using namespace com::sun::star::uno; + using namespace com::sun::star; + using com::sun::star::inspection::PropertyCategoryDescriptor; + + + //= DefaultComponentInspectorModel + + + DefaultComponentInspectorModel::DefaultComponentInspectorModel( const Reference< XComponentContext >& _rxContext) + :m_xContext( _rxContext ) + ,m_bConstructed( false ) + ,m_bHasHelpSection( false ) + ,m_bIsReadOnly(false) + ,m_nMinHelpTextLines( 3 ) + ,m_nMaxHelpTextLines( 8 ) + { + } + + DefaultComponentInspectorModel::~DefaultComponentInspectorModel() + { + } + + OUString SAL_CALL DefaultComponentInspectorModel::getImplementationName( ) + { + return "com.sun.star.comp.report.DefaultComponentInspectorModel"; + } + + sal_Bool SAL_CALL DefaultComponentInspectorModel::supportsService( const OUString& ServiceName ) + { + return cppu::supportsService(this, ServiceName); + } + + Sequence< OUString > SAL_CALL DefaultComponentInspectorModel::getSupportedServiceNames( ) + { + return { "com.sun.star.report.inspection.DefaultComponentInspectorModel" }; + } + + Sequence< Any > SAL_CALL DefaultComponentInspectorModel::getHandlerFactories() + { + // service names for all our handlers + return Sequence<Any> { + Any(OUString( "com.sun.star.report.inspection.ReportComponentHandler")), + Any(OUString( "com.sun.star.form.inspection.EditPropertyHandler")), + Any(OUString( "com.sun.star.report.inspection.DataProviderHandler")), + Any(OUString( "com.sun.star.report.inspection.GeometryHandler")) + }; + } + + sal_Bool SAL_CALL DefaultComponentInspectorModel::getHasHelpSection() + { + ::osl::MutexGuard aGuard(m_aMutex); + return m_bHasHelpSection; + } + + + ::sal_Int32 SAL_CALL DefaultComponentInspectorModel::getMinHelpTextLines() + { + ::osl::MutexGuard aGuard(m_aMutex); + return m_nMinHelpTextLines; + } + + sal_Bool SAL_CALL DefaultComponentInspectorModel::getIsReadOnly() + { + ::osl::MutexGuard aGuard(m_aMutex); + return m_bIsReadOnly; + } + + void SAL_CALL DefaultComponentInspectorModel::setIsReadOnly( sal_Bool _isreadonly ) + { + ::osl::MutexGuard aGuard(m_aMutex); + m_bIsReadOnly = _isreadonly; + } + + + ::sal_Int32 SAL_CALL DefaultComponentInspectorModel::getMaxHelpTextLines() + { + ::osl::MutexGuard aGuard(m_aMutex); + return m_nMaxHelpTextLines; + } + + void SAL_CALL DefaultComponentInspectorModel::initialize( const Sequence< Any >& _arguments ) + { + ::osl::MutexGuard aGuard(m_aMutex); + if ( m_bConstructed ) + throw ucb::AlreadyInitializedException(); + + if ( !_arguments.hasElements() ) + { // constructor: "createDefault()" + m_bConstructed = true; + return; + } + + if ( _arguments.getLength() == 2 ) + { // constructor: "createWithHelpSection( long, long )" + sal_Int32 nMinHelpTextLines( 0 ), nMaxHelpTextLines( 0 ); + if ( !( _arguments[0] >>= nMinHelpTextLines ) || !( _arguments[1] >>= nMaxHelpTextLines ) ) + throw lang::IllegalArgumentException( OUString(), *this, 0 ); + createWithHelpSection( nMinHelpTextLines, nMaxHelpTextLines ); + return; + } + + throw lang::IllegalArgumentException( OUString(), *this, 0 ); + } + + + void DefaultComponentInspectorModel::createWithHelpSection( sal_Int32 _nMinHelpTextLines, sal_Int32 _nMaxHelpTextLines ) + { + if ( ( _nMinHelpTextLines <= 0 ) || ( _nMaxHelpTextLines <= 0 ) || ( _nMinHelpTextLines > _nMaxHelpTextLines ) ) + throw lang::IllegalArgumentException( OUString(), *this, 0 ); + + m_bHasHelpSection = true; + m_nMinHelpTextLines = _nMinHelpTextLines; + m_nMaxHelpTextLines = _nMaxHelpTextLines; + m_bConstructed = true; + } + + Sequence< PropertyCategoryDescriptor > SAL_CALL DefaultComponentInspectorModel::describeCategories( ) + { + ::osl::MutexGuard aGuard( m_aMutex ); + + const struct + { + const char* programmaticName; + TranslateId uiNameResId; + OString helpId; + } aCategories[] = { + { "General", RID_STR_PROPPAGE_DEFAULT, HID_RPT_PROPDLG_TAB_GENERAL }, + { "Data", RID_STR_PROPPAGE_DATA, HID_RPT_PROPDLG_TAB_DATA }, + }; + + const size_t nCategories = SAL_N_ELEMENTS( aCategories ); + Sequence< PropertyCategoryDescriptor > aReturn( nCategories ); + PropertyCategoryDescriptor* pReturn = aReturn.getArray(); + for ( size_t i=0; i<nCategories; ++i, ++pReturn ) + { + pReturn->ProgrammaticName = OUString::createFromAscii( aCategories[i].programmaticName ); + pReturn->UIName = RptResId( aCategories[i].uiNameResId ); + pReturn->HelpURL = HelpIdUrl::getHelpURL( aCategories[i].helpId ); + } + + return aReturn; + } + + + ::sal_Int32 SAL_CALL DefaultComponentInspectorModel::getPropertyOrderIndex( const OUString& _rPropertyName ) + { + ::osl::MutexGuard aGuard(m_aMutex); + const sal_Int32 nPropertyId( OPropertyInfoService::getPropertyId( _rPropertyName ) ); + if ( nPropertyId != -1 ) + return nPropertyId; + + if ( !m_xComponent.is() ) + try + { + m_xComponent.set(m_xContext->getServiceManager()->createInstanceWithContext("com.sun.star.form.inspection.DefaultFormComponentInspectorModel",m_xContext),UNO_QUERY_THROW); + } + catch(const Exception &) + { + return 0; + } + + return m_xComponent->getPropertyOrderIndex(_rPropertyName); + } + + +} // namespace rptui + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +reportdesign_DefaultComponentInspectorModel_get_implementation( + css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new rptui::DefaultComponentInspectorModel(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inspection/GeometryHandler.cxx b/reportdesign/source/ui/inspection/GeometryHandler.cxx new file mode 100644 index 000000000..66852237b --- /dev/null +++ b/reportdesign/source/ui/inspection/GeometryHandler.cxx @@ -0,0 +1,2215 @@ +/* -*- 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 <sal/config.h> + +#include <iterator> +#include <map> +#include <string_view> + +#include <GeometryHandler.hxx> + +#include <comphelper/sequence.hxx> +#include <comphelper/types.hxx> +#include <comphelper/property.hxx> +#include <comphelper/mimeconfighelper.hxx> +#include <cppuhelper/supportsservice.hxx> + +#include <strings.hxx> +#include <reportformula.hxx> + +#include <i18nutil/searchopt.hxx> +#include <unotools/textsearch.hxx> +#include <unotools/localedatawrapper.hxx> + +#include <toolkit/helper/vclunohelper.hxx> +#include <unotools/syslocale.hxx> +#include <tools/diagnose_ex.h> +#include <tools/resary.hxx> +#include <com/sun/star/lang/NullPointerException.hpp> +#include <com/sun/star/form/inspection/FormComponentPropertyHandler.hpp> +#include <com/sun/star/inspection/StringRepresentation.hpp> +#include <com/sun/star/inspection/PropertyControlType.hpp> +#include <com/sun/star/inspection/XStringListControl.hpp> +#include <com/sun/star/report/Function.hpp> +#include <com/sun/star/report/XReportDefinition.hpp> +#include <com/sun/star/report/XShape.hpp> +#include <com/sun/star/report/XSection.hpp> +#include <com/sun/star/report/XFixedLine.hpp> +#include <com/sun/star/script/Converter.hpp> +#include <com/sun/star/sdb/XSingleSelectQueryComposer.hpp> +#include <com/sun/star/sdb/CommandType.hpp> +#include <com/sun/star/sdb/FilterDialog.hpp> +#include <com/sun/star/sdb/SQLContext.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/util/SearchAlgorithms2.hpp> +#include <com/sun/star/util/MeasureUnit.hpp> +#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/inspection/XNumericControl.hpp> +#include <com/sun/star/style/ParagraphAdjust.hpp> + +#include <tools/fldunit.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> + +#include <core_resource.hxx> +#include <stringarray.hrc> +#include <strings.hrc> +#include <RptDef.hxx> +#include <UITools.hxx> + +#include <connectivity/dbexception.hxx> +#include <connectivity/dbtools.hxx> + +#include <metadata.hxx> +#include <sfx2/docfilt.hxx> + +#include <helpids.h> +#include <toolkit/helper/convert.hxx> +#include <o3tl/functional.hxx> +#include <o3tl/safeint.hxx> + +#define DATA_OR_FORMULA 0 +#define FUNCTION 1 +#define COUNTER 2 +#define USER_DEF_FUNCTION 3 +#define UNDEF_DATA 4 + + +namespace rptui +{ + +using namespace ::com::sun::star; + +namespace{ + +OUString lcl_getQuotedFunctionName(std::u16string_view _sFunction) +{ + return OUString::Concat("[") + _sFunction + "]"; +} + +OUString lcl_getQuotedFunctionName(const uno::Reference< report::XFunction>& _xFunction) +{ + return lcl_getQuotedFunctionName(_xFunction->getName()); +} + +void lcl_collectFunctionNames(const uno::Reference< report::XFunctions>& _xFunctions,TFunctions& _rFunctionNames) +{ + uno::Reference< report::XFunctionsSupplier> xParent(_xFunctions->getParent(),uno::UNO_QUERY_THROW); + const sal_Int32 nCount = _xFunctions->getCount(); + for (sal_Int32 i = 0; i < nCount ; ++i) + { + uno::Reference< report::XFunction > xFunction(_xFunctions->getByIndex(i),uno::UNO_QUERY_THROW); + _rFunctionNames.emplace( lcl_getQuotedFunctionName(xFunction),TFunctionPair(xFunction,xParent) ); + } +} + +void lcl_collectFunctionNames(const uno::Reference< report::XSection>& _xSection,TFunctions& _rFunctionNames) +{ + const uno::Reference< report::XReportDefinition> xReportDefinition = _xSection->getReportDefinition(); + const uno::Reference< report::XGroups> xGroups = xReportDefinition->getGroups(); + sal_Int32 nPos = -1; + uno::Reference< report::XGroup> xGroup = _xSection->getGroup(); + if ( xGroup.is() ) + nPos = getPositionInIndexAccess(xGroups,xGroup); + else if ( _xSection == xReportDefinition->getDetail() ) + nPos = xGroups->getCount()-1; + + for (sal_Int32 i = 0 ; i <= nPos ; ++i) + { + xGroup.set(xGroups->getByIndex(i),uno::UNO_QUERY_THROW); + lcl_collectFunctionNames(xGroup->getFunctions(),_rFunctionNames); + } + lcl_collectFunctionNames(xReportDefinition->getFunctions(),_rFunctionNames); +} + +void lcl_convertFormulaTo(const uno::Any& _aPropertyValue,uno::Any& _rControlValue) +{ + OUString sName; + _aPropertyValue >>= sName; + const sal_Int32 nLen = sName.getLength(); + if ( nLen ) + { + ReportFormula aFormula( sName ); + _rControlValue <<= aFormula.getUndecoratedContent(); + } +} + +// return value rounded to the nearest multiple of base +// if equidistant of two multiples, round up (for positive numbers) +// T is assumed to be an integer type +template <typename T, T base> T lcl_round(T value) +{ + OSL_ENSURE(value >= 0, "lcl_round: positive numbers only please"); + const T threshold = (base % 2 == 0) ? (base/2) : (base/2 + 1); + const T rest = value % base; + if ( rest >= threshold ) + return value + (base - rest); + else + return value - rest; +} + +} // anonymous namespace + +bool GeometryHandler::impl_isDataField(const OUString& _sName) const +{ + bool bIsField = ( ::std::find( m_aFieldNames.begin(), m_aFieldNames.end(), _sName ) != m_aFieldNames.end() ); + + if ( !bIsField ) + { + bIsField = ( ::std::find( m_aParamNames.begin(), m_aParamNames.end(), _sName ) != m_aParamNames.end() ); + } + return bIsField; +} + +OUString GeometryHandler::impl_convertToFormula( const uno::Any& _rControlValue ) +{ + OUString sName; + _rControlValue >>= sName; + + if ( sName.isEmpty() ) + return sName; + + ReportFormula aParser( sName ); + if ( aParser.isValid() ) + return sName; + + return ReportFormula(impl_isDataField(sName) ? ReportFormula::Field : ReportFormula::Expression, sName).getCompleteFormula(); +} + +GeometryHandler::GeometryHandler(uno::Reference< uno::XComponentContext > const & context) + : GeometryHandler_Base(m_aMutex) + , m_aPropertyListeners(m_aMutex) + , m_xContext(context) + , m_nDataFieldType(0) + , m_bNewFunction(false) + , m_bIn(false) +{ + try + { + m_xFormComponentHandler = form::inspection::FormComponentPropertyHandler::create(m_xContext); + m_xTypeConverter = script::Converter::create(context); + loadDefaultFunctions(); + } + catch(const uno::Exception&) + { + } +} + +GeometryHandler::~GeometryHandler() +{ +} + +OUString SAL_CALL GeometryHandler::getImplementationName( ) +{ + return "com.sun.star.comp.report.GeometryHandler"; +} + +sal_Bool SAL_CALL GeometryHandler::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +uno::Sequence< OUString > SAL_CALL GeometryHandler::getSupportedServiceNames( ) +{ + return { "com.sun.star.report.inspection.GeometryHandler" }; +} + +// override WeakComponentImplHelperBase::disposing() +// This function is called upon disposing the component, +// if your component needs special work when it becomes +// disposed, do it here. +void SAL_CALL GeometryHandler::disposing() +{ + try + { + ::comphelper::disposeComponent(m_xFormComponentHandler); + ::comphelper::disposeComponent(m_xTypeConverter); + if ( m_xReportComponent.is() && m_xReportComponent->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATAFIELD) ) + m_xReportComponent->removePropertyChangeListener(PROPERTY_DATAFIELD,static_cast< beans::XPropertyChangeListener* >( this )); + + m_xReportComponent.clear(); + m_xRowSet.clear(); + m_aPropertyListeners.clear(); + } + catch(uno::Exception&) + {} +} +void SAL_CALL GeometryHandler::addEventListener(const uno::Reference< lang::XEventListener > & xListener) +{ + m_xFormComponentHandler->addEventListener(xListener); +} + +void SAL_CALL GeometryHandler::removeEventListener(const uno::Reference< lang::XEventListener > & aListener) +{ + m_xFormComponentHandler->removeEventListener(aListener); +} + +// inspection::XPropertyHandler: + +/********************************************************************************/ +void SAL_CALL GeometryHandler::inspect( const uno::Reference< uno::XInterface > & _rxInspectee ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + m_sScope.clear(); + m_sDefaultFunction.clear(); + m_bNewFunction = false; + m_nDataFieldType = 0; + m_xFunction.clear(); + m_aFunctionNames.clear(); + try + { + if ( m_xReportComponent.is() && m_xReportComponent->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATAFIELD) ) + m_xReportComponent->removePropertyChangeListener(PROPERTY_DATAFIELD,static_cast< beans::XPropertyChangeListener* >( this )); + + const uno::Reference< container::XNameContainer > xObjectAsContainer( _rxInspectee, uno::UNO_QUERY ); + m_xReportComponent.set( xObjectAsContainer->getByName("ReportComponent"), uno::UNO_QUERY ); + + static const OUStringLiteral sRowSet(u"RowSet"); + if ( xObjectAsContainer->hasByName( sRowSet ) ) + { + const uno::Any aRowSet( xObjectAsContainer->getByName(sRowSet) ); + aRowSet >>= m_xRowSet; + // forward the rowset to our delegator handler + uno::Reference< beans::XPropertySet > xProp( m_xFormComponentHandler,uno::UNO_QUERY ); + xProp->setPropertyValue( sRowSet, aRowSet ); + + m_aParamNames = getParameterNames( m_xRowSet ); + impl_initFieldList_nothrow(m_aFieldNames); + if ( m_xReportComponent->getPropertySetInfo()->hasPropertyByName(PROPERTY_DATAFIELD) ) + m_xReportComponent->addPropertyChangeListener(PROPERTY_DATAFIELD,static_cast< beans::XPropertyChangeListener* >( this )); + } + + const uno::Reference< report::XReportComponent> xReportComponent( m_xReportComponent, uno::UNO_QUERY); + uno::Reference< report::XSection> xSection( m_xReportComponent, uno::UNO_QUERY ); + if ( !xSection.is() && xReportComponent.is() ) + xSection = xReportComponent->getSection(); + if ( xSection.is() ) + lcl_collectFunctionNames( xSection, m_aFunctionNames ); + } + catch(const uno::Exception &) + { + throw lang::NullPointerException(); + } + m_xFormComponentHandler->inspect(m_xReportComponent); +} + +uno::Any SAL_CALL GeometryHandler::getPropertyValue(const OUString & PropertyName) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + uno::Any aPropertyValue; + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + switch(nId) + { + case PROPERTY_ID_CONDITIONALPRINTEXPRESSION: + case PROPERTY_ID_INITIALFORMULA: + case PROPERTY_ID_FORMULA: + case PROPERTY_ID_DATAFIELD: + aPropertyValue = m_xReportComponent->getPropertyValue( PropertyName ); + lcl_convertFormulaTo(aPropertyValue,aPropertyValue); + if ( PROPERTY_ID_DATAFIELD == nId ) + { + OUString sDataField; + aPropertyValue >>= sDataField; + switch(m_nDataFieldType) + { + case DATA_OR_FORMULA: + break; + case FUNCTION: + if ( isDefaultFunction(sDataField,sDataField) ) + aPropertyValue <<= sDataField; + else if ( sDataField.isEmpty() ) + aPropertyValue = uno::Any(); + break; + case COUNTER: + case USER_DEF_FUNCTION: + aPropertyValue = uno::Any(); + break; + } + + } + break; + case PROPERTY_ID_TYPE: + { + const sal_uInt32 nOldDataFieldType = m_nDataFieldType; + m_nDataFieldType = impl_getDataFieldType_throw(); + if ( UNDEF_DATA == m_nDataFieldType ) + m_nDataFieldType = nOldDataFieldType; + aPropertyValue <<= m_nDataFieldType; + } + break; + case PROPERTY_ID_FORMULALIST: + case PROPERTY_ID_SCOPE: + { + uno::Any aDataField = m_xReportComponent->getPropertyValue( PROPERTY_DATAFIELD ); + lcl_convertFormulaTo(aDataField,aDataField); + OUString sDataField; + aDataField >>= sDataField; + switch(m_nDataFieldType) + { + case DATA_OR_FORMULA: + break; + case FUNCTION: + if ( isDefaultFunction(sDataField,sDataField,uno::Reference< report::XFunctionsSupplier>(),true) ) + aPropertyValue <<= (PROPERTY_ID_FORMULALIST == nId ? m_sDefaultFunction : m_sScope); + break; + case USER_DEF_FUNCTION: + if ( !sDataField.isEmpty() && PROPERTY_ID_FORMULALIST == nId ) + aPropertyValue = aDataField; + break; + case COUNTER: + if ( PROPERTY_ID_SCOPE == nId && impl_isCounterFunction_throw(sDataField,m_sScope) ) + aPropertyValue <<= m_sScope; + break; + } + + } + break; + case PROPERTY_ID_BACKCOLOR: + case PROPERTY_ID_CONTROLBACKGROUND: + { + aPropertyValue = m_xReportComponent->getPropertyValue( PropertyName ); + Color nColor = COL_TRANSPARENT; + if ( (aPropertyValue >>= nColor) && COL_TRANSPARENT == nColor ) + aPropertyValue.clear(); + } + break; + case PROPERTY_ID_MIMETYPE: + { + OUString sValue; + m_xReportComponent->getPropertyValue( PropertyName ) >>= sValue; + aPropertyValue <<= impl_ConvertMimeTypeToUI_nothrow(sValue); + } + break; + default: + aPropertyValue = m_xReportComponent->getPropertyValue( PropertyName ); + break; + } + return aPropertyValue; +} + +void SAL_CALL GeometryHandler::setPropertyValue(const OUString & PropertyName, const uno::Any & Value) +{ + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + uno::Any aNewValue = Value; + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + bool bHandled = false; + switch(nId) + { + case PROPERTY_ID_INITIALFORMULA: + case PROPERTY_ID_FORMULA: + break; + case PROPERTY_ID_DATAFIELD: + { + OBlocker aBlocker(m_bIn); + m_xReportComponent->setPropertyValue(PropertyName, aNewValue); + bHandled = true; + const OUString sOldFunctionName = m_sDefaultFunction; + const OUString sOldScope = m_sScope; + + uno::Any aPropertyValue; + lcl_convertFormulaTo(Value,aPropertyValue); + OUString sDataField; + aPropertyValue >>= sDataField; + + m_sScope.clear(); + m_sDefaultFunction.clear(); + m_xFunction.clear(); + const sal_uInt32 nOldDataFieldType = m_nDataFieldType; + if ( !sDataField.isEmpty() ) + { + if ( isDefaultFunction(sDataField,sDataField,uno::Reference< report::XFunctionsSupplier>(),true) ) + m_nDataFieldType = FUNCTION; + else if ( m_aFunctionNames.find(sDataField) != m_aFunctionNames.end() ) + m_nDataFieldType = USER_DEF_FUNCTION; + } + + resetOwnProperties(aGuard,sOldFunctionName,sOldScope,nOldDataFieldType); + } + break; + case PROPERTY_ID_TYPE: + { + bHandled = true; + Value >>= m_nDataFieldType; + + const OUString sOldFunctionName = m_sDefaultFunction; + const OUString sOldScope = m_sScope; + m_sDefaultFunction.clear(); + m_sScope.clear(); + + if ( m_nDataFieldType == COUNTER ) + { + impl_setCounterFunction_throw(); + } + else + { + if ( m_bNewFunction ) + removeFunction(); + m_xFunction.clear(); + OBlocker aBlocker(m_bIn); + m_xReportComponent->setPropertyValue(PROPERTY_DATAFIELD,uno::Any(OUString())); + } + resetOwnProperties(aGuard,sOldFunctionName,sOldScope,m_nDataFieldType); + } + break; + case PROPERTY_ID_FORMULALIST: + { + bHandled = true; + OUString sFunction; + if ( !(Value >>= sFunction) || sFunction.isEmpty() ) + { + if ( m_nDataFieldType == FUNCTION ) + { + m_sDefaultFunction.clear(); + if ( m_bNewFunction ) + removeFunction(); + m_xFunction.clear(); + + beans::PropertyChangeEvent aEvent; + aEvent.PropertyName = PROPERTY_SCOPE; + aEvent.OldValue <<= m_sScope; + m_sScope.clear(); + aEvent.NewValue <<= m_sScope; + aGuard.clear(); + m_aPropertyListeners.notifyEach( &beans::XPropertyChangeListener::propertyChange, aEvent ); + } + else if ( m_nDataFieldType == USER_DEF_FUNCTION ) + { + OBlocker aBlocker(m_bIn); + m_xReportComponent->setPropertyValue(PROPERTY_DATAFIELD,uno::Any(OUString())); + } + } + else if ( m_nDataFieldType == USER_DEF_FUNCTION ) + { + OBlocker aBlocker(m_bIn); + const sal_uInt32 nNewDataType = impl_getDataFieldType_throw(sFunction); + if ( nNewDataType != UNDEF_DATA && nNewDataType != m_nDataFieldType ) + { + const OUString sOldFunctionName = m_sDefaultFunction; + const OUString sOldScope = m_sScope; + m_sScope.clear(); + m_sDefaultFunction.clear(); + m_xFunction.clear(); + if ( nNewDataType == COUNTER ) + impl_isCounterFunction_throw(sFunction,m_sScope); + else + { + OUString sNamePostfix; + OUString sDataField; + const uno::Reference< report::XFunctionsSupplier> xFunctionsSupplier = fillScope_throw(sNamePostfix); + isDefaultFunction(sFunction,sDataField,xFunctionsSupplier,true); + } + const sal_uInt32 nOldDataFieldType = m_nDataFieldType; + m_nDataFieldType = nNewDataType; + m_xReportComponent->setPropertyValue(PROPERTY_DATAFIELD,uno::Any(impl_convertToFormula( uno::Any(sFunction)))); + resetOwnProperties(aGuard,sOldFunctionName,sOldScope,nOldDataFieldType); + } + else + m_xReportComponent->setPropertyValue(PROPERTY_DATAFIELD,uno::Any(impl_convertToFormula( uno::Any(sFunction)))); + } + else if ( m_nDataFieldType == FUNCTION ) + { + uno::Any aPropertyValue = m_xReportComponent->getPropertyValue(PROPERTY_DATAFIELD); + lcl_convertFormulaTo(aPropertyValue,aPropertyValue); + OUString sDataField; + aPropertyValue >>= sDataField; + if ( m_nDataFieldType == FUNCTION && (!isDefaultFunction(sDataField,sDataField) || m_sDefaultFunction != sFunction) ) + { + if ( m_bNewFunction ) + removeFunction(); + // function currently does not exist + createDefaultFunction(aGuard,sFunction,sDataField); + m_sDefaultFunction = sFunction; + } + } + } + + break; + case PROPERTY_ID_SCOPE: + if ( !(Value >>= m_sScope) ) + m_sScope.clear(); + else + { + if ( m_bNewFunction ) + removeFunction(); + if ( m_nDataFieldType == COUNTER ) + impl_setCounterFunction_throw(); + else + { + OSL_ENSURE(m_xFunction.is(),"Where is my function gone!"); + + OUString sNamePostfix; + const uno::Reference< report::XFunctionsSupplier> xFunctionsSupplier = fillScope_throw(sNamePostfix); + + OUString sQuotedFunctionName(lcl_getQuotedFunctionName(m_xFunction)); + if ( isDefaultFunction(sQuotedFunctionName,sQuotedFunctionName,xFunctionsSupplier,true) ) + m_bNewFunction = false; + else + { + OUString sDefaultFunctionName; + OUString sDataField; + OSL_VERIFY( impl_isDefaultFunction_nothrow(m_xFunction,sDataField,sDefaultFunctionName) ); + m_sDefaultFunction = sDefaultFunctionName; + createDefaultFunction(aGuard,m_sDefaultFunction,sDataField); + } + } + } + bHandled = true; + break; + case PROPERTY_ID_POSITIONX: + case PROPERTY_ID_POSITIONY: + case PROPERTY_ID_HEIGHT: + case PROPERTY_ID_WIDTH: + { + const uno::Reference< report::XReportComponent> xSourceReportComponent(m_xReportComponent,uno::UNO_QUERY); + if ( xSourceReportComponent.is() ) // check only report components + { + sal_Int32 nNewValue = 0; + Value >>= nNewValue; + OSL_ENSURE(nNewValue >= 0, "A position/dimension should not be negative!"); + nNewValue = lcl_round<sal_Int32, 10>(nNewValue); + awt::Point aAwtPoint = xSourceReportComponent->getPosition(); + awt::Size aAwtSize = xSourceReportComponent->getSize(); + if ( nId == PROPERTY_ID_POSITIONX ) + aAwtPoint.X = nNewValue; + else if ( nId == PROPERTY_ID_POSITIONY ) + aAwtPoint.Y = nNewValue; + else if ( nId == PROPERTY_ID_HEIGHT ) + aAwtSize.Height = nNewValue; + else if ( nId == PROPERTY_ID_WIDTH ) + aAwtSize.Width = nNewValue; + + checkPosAndSize(aAwtPoint,aAwtSize); + } + } + break; + case PROPERTY_ID_FONT: + { + const uno::Reference< report::XReportControlFormat > xReportControlFormat( m_xReportComponent,uno::UNO_QUERY_THROW ); + uno::Sequence< beans::NamedValue > aFontSettings; + OSL_VERIFY( Value >>= aFontSettings ); + applyCharacterSettings( xReportControlFormat, aFontSettings ); + bHandled = true; + } + break; + case PROPERTY_ID_MIMETYPE: + { + OUString sValue; + Value >>= sValue; + aNewValue <<= impl_ConvertUIToMimeType_nothrow(sValue); + } + break; + default: + break; + } + + if ( !bHandled ) + m_xReportComponent->setPropertyValue(PropertyName, aNewValue); +} + + +beans::PropertyState SAL_CALL GeometryHandler::getPropertyState(const OUString & PropertyName) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + return m_xFormComponentHandler->getPropertyState(PropertyName); +} + +void GeometryHandler::implCreateListLikeControl( + const uno::Reference< inspection::XPropertyControlFactory >& _rxControlFactory + ,inspection::LineDescriptor & out_Descriptor + ,const TranslateId* pResId + ,bool _bReadOnlyControl + ,bool _bTrueIfListBoxFalseIfComboBox + ) +{ + std::vector<OUString> aList; + for (const TranslateId* pItem = pResId; *pItem; ++pItem) + aList.push_back(RptResId(*pItem)); + implCreateListLikeControl(_rxControlFactory, out_Descriptor, aList, _bReadOnlyControl, _bTrueIfListBoxFalseIfComboBox); +} + +void GeometryHandler::implCreateListLikeControl( + const uno::Reference< inspection::XPropertyControlFactory >& _rxControlFactory + ,inspection::LineDescriptor & out_Descriptor + ,const ::std::vector< OUString>& _aEntries + ,bool _bReadOnlyControl + ,bool _bTrueIfListBoxFalseIfComboBox + ) +{ + const uno::Reference< inspection::XStringListControl > xListControl( + _rxControlFactory->createPropertyControl( + _bTrueIfListBoxFalseIfComboBox ? inspection::PropertyControlType::ListBox : inspection::PropertyControlType::ComboBox, _bReadOnlyControl + ), + uno::UNO_QUERY_THROW + ); + + out_Descriptor.Control = xListControl.get(); + for (auto const& it : _aEntries) + { + xListControl->appendListEntry(it); + } +} + + +inspection::LineDescriptor SAL_CALL GeometryHandler::describePropertyLine(const OUString & PropertyName, const uno::Reference< inspection::XPropertyControlFactory > & _xControlFactory) +{ + inspection::LineDescriptor aOut; + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + switch(nId) + { + case PROPERTY_ID_FORCENEWPAGE: + case PROPERTY_ID_NEWROWORCOL: + implCreateListLikeControl(_xControlFactory,aOut,RID_STR_FORCENEWPAGE_CONST,false,true); + break; + case PROPERTY_ID_GROUPKEEPTOGETHER: + implCreateListLikeControl(_xControlFactory,aOut,RID_STR_GROUPKEEPTOGETHER_CONST,false,true); + break; + case PROPERTY_ID_PAGEHEADEROPTION: + case PROPERTY_ID_PAGEFOOTEROPTION: + implCreateListLikeControl(_xControlFactory,aOut,RID_STR_REPORTPRINTOPTION_CONST,false,true); + break; + case PROPERTY_ID_FORMULALIST: + { + ::std::vector< OUString > aList; + impl_fillFormulaList_nothrow(aList); + implCreateListLikeControl(_xControlFactory,aOut,aList,false,true); + } + break; + case PROPERTY_ID_SCOPE: + { + ::std::vector< OUString > aList; + impl_fillScopeList_nothrow(aList); + implCreateListLikeControl(_xControlFactory,aOut,aList,false,true); + } + break; + case PROPERTY_ID_MIMETYPE: + { + ::std::vector< OUString > aList; + impl_fillMimeTypes_nothrow(aList); + implCreateListLikeControl(_xControlFactory,aOut,aList,false,true); + } + break; + case PROPERTY_ID_TYPE: + implCreateListLikeControl(_xControlFactory,aOut,RID_STR_TYPE_CONST,false,true); + break; + case PROPERTY_ID_VISIBLE: + case PROPERTY_ID_CANGROW: + case PROPERTY_ID_CANSHRINK: + case PROPERTY_ID_REPEATSECTION: + case PROPERTY_ID_PRINTREPEATEDVALUES: + case PROPERTY_ID_STARTNEWCOLUMN: + case PROPERTY_ID_RESETPAGENUMBER: + case PROPERTY_ID_PRINTWHENGROUPCHANGE: + case PROPERTY_ID_KEEPTOGETHER: + case PROPERTY_ID_DEEPTRAVERSING: + case PROPERTY_ID_PREEVALUATED: + case PROPERTY_ID_PRESERVEIRI: + case PROPERTY_ID_BACKTRANSPARENT: + case PROPERTY_ID_CONTROLBACKGROUNDTRANSPARENT: + { + const TranslateId* pResId = RID_STR_BOOL; + if ( PROPERTY_ID_KEEPTOGETHER == nId && uno::Reference< report::XGroup>(m_xReportComponent,uno::UNO_QUERY).is()) + pResId = RID_STR_KEEPTOGETHER_CONST; + implCreateListLikeControl(_xControlFactory,aOut,pResId,false,true); + } + break; + case PROPERTY_ID_INITIALFORMULA: + case PROPERTY_ID_FORMULA: + aOut.PrimaryButtonId = UID_RPT_PROP_FORMULA; + aOut.HasPrimaryButton = true; + aOut.Control = _xControlFactory->createPropertyControl(inspection::PropertyControlType::MultiLineTextField , false); + break; + case PROPERTY_ID_CONDITIONALPRINTEXPRESSION: + aOut.PrimaryButtonId = UID_RPT_PROP_FORMULA; + aOut.HasPrimaryButton = true; + aOut.Control = _xControlFactory->createPropertyControl(inspection::PropertyControlType::MultiLineTextField , false); + break; + case PROPERTY_ID_DATAFIELD: + { + uno::Reference< inspection::XStringListControl > xListControl( + _xControlFactory->createPropertyControl( + m_nDataFieldType == DATA_OR_FORMULA ? inspection::PropertyControlType::ComboBox : inspection::PropertyControlType::ListBox, false + ), + uno::UNO_QUERY_THROW + ); + + if ( m_nDataFieldType == DATA_OR_FORMULA ) + { + aOut.PrimaryButtonId = UID_RPT_PROP_FORMULA; + aOut.HasPrimaryButton = true; + } + + aOut.Control = xListControl.get(); + if ( m_nDataFieldType == USER_DEF_FUNCTION ) + { + // add function names + ::std::for_each(m_aFunctionNames.begin(), m_aFunctionNames.end(), + [&xListControl] (const TFunctions::value_type& func) { + xListControl->appendListEntry(func.first); + }); + } + else + { + for (auto const& it : std::as_const(m_aFieldNames)) + { + xListControl->appendListEntry(it); + } + for (auto const& it : std::as_const(m_aParamNames)) + { + xListControl->appendListEntry(it); + } + } + } + break; + case PROPERTY_ID_BACKCOLOR: + case PROPERTY_ID_CONTROLBACKGROUND: + aOut.Control = _xControlFactory->createPropertyControl( inspection::PropertyControlType::ColorListBox, false ); + break; + case PROPERTY_ID_FONT: + aOut.PrimaryButtonId = UID_RPT_RPT_PROP_DLG_FONT_TYPE; + aOut.Control = _xControlFactory->createPropertyControl( inspection::PropertyControlType::TextField, true ); + aOut.HasPrimaryButton = true; + break; + case PROPERTY_ID_AREA: + aOut.PrimaryButtonId = UID_RPT_RPT_PROP_DLG_AREA; + aOut.Control = _xControlFactory->createPropertyControl( inspection::PropertyControlType::TextField, true ); + aOut.HasPrimaryButton = true; + break; + case PROPERTY_ID_VERTICALALIGN: + implCreateListLikeControl(_xControlFactory,aOut,RID_STR_VERTICAL_ALIGN_CONST,false,true); + break; + case PROPERTY_ID_PARAADJUST: + implCreateListLikeControl(_xControlFactory,aOut,RID_STR_PARAADJUST_CONST,false,true); + break; + default: + { + aOut = m_xFormComponentHandler->describePropertyLine(PropertyName, _xControlFactory); + } + } + + if ( nId != -1 ) + { + aOut.Category = (OPropertyInfoService::getPropertyUIFlags(nId ) & PropUIFlags::DataProperty) ? + std::u16string_view(u"Data") + : + std::u16string_view(u"General"); + aOut.HelpURL = HelpIdUrl::getHelpURL( OPropertyInfoService::getPropertyHelpId( nId ) ); + aOut.DisplayName = OPropertyInfoService::getPropertyTranslation(nId); + } + + if ( ( nId == PROPERTY_ID_POSITIONX ) + || ( nId == PROPERTY_ID_POSITIONY ) + || ( nId == PROPERTY_ID_WIDTH ) + || ( nId == PROPERTY_ID_HEIGHT ) + ) + { + const MeasurementSystem eSystem = SvtSysLocale().GetLocaleData().getMeasurementSystemEnum(); + const sal_Int16 nDisplayUnit = VCLUnoHelper::ConvertToMeasurementUnit( MeasurementSystem::Metric == eSystem ? FieldUnit::CM : FieldUnit::INCH, 1 ); + uno::Reference< inspection::XNumericControl > xNumericControl(aOut.Control,uno::UNO_QUERY); + xNumericControl->setDecimalDigits( 2 ); + xNumericControl->setValueUnit( util::MeasureUnit::MM_100TH ); + uno::Reference< drawing::XShapeDescriptor> xShapeDesc(m_xReportComponent,uno::UNO_QUERY); + bool bSetMin = !xShapeDesc.is() || xShapeDesc->getShapeType() != "com.sun.star.drawing.CustomShape"; + if ( bSetMin ) + xNumericControl->setMinValue(beans::Optional<double>(true,0.0)); + if ( nDisplayUnit != -1 ) + xNumericControl->setDisplayUnit( nDisplayUnit ); + uno::Reference< report::XReportComponent> xComp(m_xReportComponent,uno::UNO_QUERY); + if ( xComp.is() && xComp->getSection().is() ) + { + uno::Reference< report::XReportDefinition > xReport = xComp->getSection()->getReportDefinition(); + OSL_ENSURE(xReport.is(),"Why is the report definition NULL!"); + if ( xReport.is() ) + { + const awt::Size aSize = getStyleProperty<awt::Size>(xReport,PROPERTY_PAPERSIZE); + const sal_Int32 nLeftMargin = getStyleProperty<sal_Int32>(xReport,PROPERTY_LEFTMARGIN); + const sal_Int32 nRightMargin = getStyleProperty<sal_Int32>(xReport,PROPERTY_RIGHTMARGIN); + switch(nId) + { + case PROPERTY_ID_POSITIONX: + case PROPERTY_ID_WIDTH: + if ( bSetMin ) + xNumericControl->setMinValue(beans::Optional<double>(true,0.0)); + xNumericControl->setMaxValue(beans::Optional<double>(true,double(aSize.Width - nLeftMargin - nRightMargin))); + if ( PROPERTY_ID_WIDTH == nId ) + { + uno::Reference<report::XFixedLine> xFixedLine(m_xReportComponent,uno::UNO_QUERY); + if ( xFixedLine.is() && xFixedLine->getOrientation() == 1 ) // vertical + xNumericControl->setMinValue(beans::Optional<double>(true,0.08 )); + } + break; + default: + break; + } + } + } + else if ( PROPERTY_ID_HEIGHT == nId ) + { + const uno::Reference< report::XSection> xSection(m_xReportComponent,uno::UNO_QUERY); + if ( xSection.is() ) + { + sal_Int32 nHeight = 0; + const sal_Int32 nCount = xSection->getCount(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + uno::Reference<drawing::XShape> xShape(xSection->getByIndex(i),uno::UNO_QUERY); + nHeight = ::std::max<sal_Int32>(nHeight,xShape->getPosition().Y + xShape->getSize().Height); + } + xNumericControl->setMinValue(beans::Optional<double>(true,nHeight )); + } + } + } + return aOut; +} + +beans::Property GeometryHandler::getProperty(const OUString & PropertyName) +{ + uno::Sequence< beans::Property > aProps = getSupportedProperties(); + const beans::Property* pIter = aProps.getConstArray(); + const beans::Property* pEnd = pIter + aProps.getLength(); + const beans::Property* pFind = ::std::find_if(pIter, pEnd, + [&PropertyName] (const beans::Property& x) -> bool { + return x.Name == PropertyName; + }); + if ( pFind == pEnd ) + return beans::Property(); + return *pFind; +} +uno::Any GeometryHandler::getConstantValue(bool _bToControlValue,const TranslateId* pResId,const uno::Any& _aValue,const OUString& _sConstantName,const OUString & PropertyName ) +{ + std::vector<OUString> aList; + for (const TranslateId* pItem = pResId; *pItem; ++pItem) + aList.push_back(RptResId(*pItem)); + uno::Sequence< OUString > aSeq(aList.size()); + auto aSeqRange = asNonConstRange(aSeq); + for (size_t i = 0; i < aList.size(); ++i) + aSeqRange[i] = aList[i]; + + uno::Reference< inspection::XStringRepresentation > xConversionHelper = inspection::StringRepresentation::createConstant( m_xContext,m_xTypeConverter,_sConstantName,aSeq); + if ( _bToControlValue ) + { + return uno::Any( xConversionHelper->convertToControlValue( _aValue ) ); + } + else + { + OUString sControlValue; + _aValue >>= sControlValue; + const beans::Property aProp = getProperty(PropertyName); + return xConversionHelper->convertToPropertyValue( sControlValue, aProp.Type ); + } +} + +uno::Any SAL_CALL GeometryHandler::convertToPropertyValue(const OUString & PropertyName, const uno::Any & _rControlValue) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + uno::Any aPropertyValue( _rControlValue ); + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + switch(nId) + { + case PROPERTY_ID_FORCENEWPAGE: + case PROPERTY_ID_NEWROWORCOL: + aPropertyValue = getConstantValue(false,RID_STR_FORCENEWPAGE_CONST,_rControlValue,"com.sun.star.report.ForceNewPage",PropertyName); + break; + case PROPERTY_ID_GROUPKEEPTOGETHER: + aPropertyValue = getConstantValue(false,RID_STR_GROUPKEEPTOGETHER_CONST,_rControlValue,"com.sun.star.report.GroupKeepTogether",PropertyName); + break; + case PROPERTY_ID_PAGEHEADEROPTION: + case PROPERTY_ID_PAGEFOOTEROPTION: + aPropertyValue = getConstantValue(false,RID_STR_REPORTPRINTOPTION_CONST,_rControlValue,"com.sun.star.report.ReportPrintOption",PropertyName); + break; + case PROPERTY_ID_BACKCOLOR: + case PROPERTY_ID_CONTROLBACKGROUND: + if ( !_rControlValue.hasValue() ) + { + aPropertyValue <<= COL_TRANSPARENT; + break; + } + [[fallthrough]]; + + case PROPERTY_ID_KEEPTOGETHER: + if ( uno::Reference< report::XGroup>(m_xReportComponent,uno::UNO_QUERY).is()) + { + aPropertyValue = getConstantValue(false,RID_STR_KEEPTOGETHER_CONST,_rControlValue,"com.sun.star.report.KeepTogether",PropertyName); + break; + } + [[fallthrough]]; + + case PROPERTY_ID_VISIBLE: + case PROPERTY_ID_CANGROW: + case PROPERTY_ID_CANSHRINK: + case PROPERTY_ID_REPEATSECTION: + case PROPERTY_ID_PRINTREPEATEDVALUES: + case PROPERTY_ID_STARTNEWCOLUMN: + case PROPERTY_ID_RESETPAGENUMBER: + case PROPERTY_ID_PRINTWHENGROUPCHANGE: + case PROPERTY_ID_DEEPTRAVERSING: + case PROPERTY_ID_PREEVALUATED: + case PROPERTY_ID_PRESERVEIRI: + case PROPERTY_ID_BACKTRANSPARENT: + case PROPERTY_ID_CONTROLBACKGROUNDTRANSPARENT: + { + if ( aPropertyValue.hasValue() ) + { + const beans::Property aProp = getProperty(PropertyName); + if ( aPropertyValue.getValueType().equals( aProp.Type ) ) + // nothing to do, type is already as desired + return aPropertyValue; + + if ( _rControlValue.getValueType().getTypeClass() == uno::TypeClass_STRING ) + { + OUString sControlValue; + _rControlValue >>= sControlValue; + + const uno::Reference< inspection::XStringRepresentation > xConversionHelper = inspection::StringRepresentation::create( m_xContext,m_xTypeConverter ); + aPropertyValue = xConversionHelper->convertToPropertyValue( sControlValue, aProp.Type ); + } + else + { + try + { + aPropertyValue = m_xTypeConverter->convertTo( _rControlValue, aProp.Type ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "GeometryHandler::convertToPropertyValue: caught an exception while converting via TypeConverter!" ); + } + } + } + + break; + } + case PROPERTY_ID_CONDITIONALPRINTEXPRESSION: + case PROPERTY_ID_INITIALFORMULA: + case PROPERTY_ID_FORMULA: + return uno::Any( impl_convertToFormula( _rControlValue ) ); + case PROPERTY_ID_DATAFIELD: + { + OUString sDataField; + _rControlValue >>= sDataField; + if ( isDefaultFunction(sDataField,sDataField) ) + { + OSL_ENSURE(m_xFunction.is(),"No function set!"); + aPropertyValue <<= impl_convertToFormula( uno::Any(lcl_getQuotedFunctionName(m_xFunction)) ); + } + else + aPropertyValue <<= impl_convertToFormula( _rControlValue ); + } + break; + case PROPERTY_ID_POSITIONX: + { + aPropertyValue = m_xFormComponentHandler->convertToPropertyValue(PropertyName, _rControlValue); + sal_Int32 nPosX = 0; + aPropertyValue >>= nPosX; + const uno::Reference< report::XReportComponent> xSourceReportComponent(m_xReportComponent,uno::UNO_QUERY); + if ( xSourceReportComponent->getSection().is() ) + nPosX += getStyleProperty<sal_Int32>(xSourceReportComponent->getSection()->getReportDefinition(),PROPERTY_LEFTMARGIN); + aPropertyValue <<= nPosX; + } + break; + case PROPERTY_ID_FONT: + aPropertyValue = m_xFormComponentHandler->convertToPropertyValue(PROPERTY_FONT, _rControlValue); + break; + case PROPERTY_ID_SCOPE: + case PROPERTY_ID_FORMULALIST: + case PROPERTY_ID_AREA: + aPropertyValue = _rControlValue; + break; + case PROPERTY_ID_TYPE: + { + OUString sValue; + _rControlValue >>= sValue; + + sal_uInt32 nFound(RESARRAY_INDEX_NOTFOUND); + sal_uInt32 i = 0; + for (const TranslateId* pItem = RID_STR_TYPE_CONST; *pItem; ++pItem) + { + if (sValue == RptResId(*pItem)) + { + nFound = i; + break; + } + ++i; + } + if (nFound != RESARRAY_INDEX_NOTFOUND) + aPropertyValue <<= nFound; + } + break; + case PROPERTY_ID_MIMETYPE: + aPropertyValue = _rControlValue; + break; + case PROPERTY_ID_VERTICALALIGN: + { + OUString sValue; + _rControlValue >>= sValue; + + sal_uInt32 nFound(RESARRAY_INDEX_NOTFOUND); + sal_uInt32 i = 0; + for (const TranslateId* pItem = RID_STR_VERTICAL_ALIGN_CONST; *pItem; ++pItem) + { + if (sValue == RptResId(*pItem)) + { + nFound = i; + break; + } + ++i; + } + if (nFound != RESARRAY_INDEX_NOTFOUND) + aPropertyValue <<= static_cast<style::VerticalAlignment>(nFound); + } + break; + case PROPERTY_ID_PARAADJUST: + { + OUString sValue; + _rControlValue >>= sValue; + + sal_uInt32 nFound(RESARRAY_INDEX_NOTFOUND); + sal_uInt32 i = 0; + for (const TranslateId* pItem = RID_STR_PARAADJUST_CONST; *pItem; ++pItem) + { + if (sValue == RptResId(*pItem)) + { + nFound = i; + break; + } + ++i; + } + + if (nFound != RESARRAY_INDEX_NOTFOUND) + aPropertyValue <<= static_cast<sal_Int16>(nFound); + } + break; + default: + return m_xFormComponentHandler->convertToPropertyValue(PropertyName, _rControlValue); + } + return aPropertyValue; +} + +uno::Any SAL_CALL GeometryHandler::convertToControlValue(const OUString & PropertyName, const uno::Any & _rPropertyValue, const uno::Type & _rControlValueType) +{ + uno::Any aControlValue( _rPropertyValue ); + if ( !aControlValue.hasValue() ) + // NULL is converted to NULL + return aControlValue; + + uno::Any aPropertyValue(_rPropertyValue); + + ::osl::MutexGuard aGuard( m_aMutex ); + const sal_Int32 nId = OPropertyInfoService::getPropertyId(PropertyName); + switch(nId) + { + case PROPERTY_ID_AREA: + break; + case PROPERTY_ID_FORCENEWPAGE: + case PROPERTY_ID_NEWROWORCOL: + aControlValue = getConstantValue(true,RID_STR_FORCENEWPAGE_CONST,aPropertyValue,"com.sun.star.report.ForceNewPage",PropertyName); + break; + case PROPERTY_ID_GROUPKEEPTOGETHER: + aControlValue = getConstantValue(true,RID_STR_GROUPKEEPTOGETHER_CONST,aPropertyValue,"com.sun.star.report.GroupKeepTogether",PropertyName); + break; + case PROPERTY_ID_PAGEHEADEROPTION: + case PROPERTY_ID_PAGEFOOTEROPTION: + aControlValue = getConstantValue(true,RID_STR_REPORTPRINTOPTION_CONST,aPropertyValue,"com.sun.star.report.ReportPrintOption",PropertyName); + break; + case PROPERTY_ID_KEEPTOGETHER: + if ( uno::Reference< report::XGroup>(m_xReportComponent,uno::UNO_QUERY).is()) + { + aControlValue = getConstantValue(true,RID_STR_KEEPTOGETHER_CONST,aPropertyValue,"com.sun.star.report.KeepTogether",PropertyName); + break; + } + [[fallthrough]]; + case PROPERTY_ID_VISIBLE: + case PROPERTY_ID_CANGROW: + case PROPERTY_ID_CANSHRINK: + case PROPERTY_ID_REPEATSECTION: + case PROPERTY_ID_PRINTREPEATEDVALUES: + case PROPERTY_ID_STARTNEWCOLUMN: + case PROPERTY_ID_RESETPAGENUMBER: + case PROPERTY_ID_PRINTWHENGROUPCHANGE: + case PROPERTY_ID_DEEPTRAVERSING: + case PROPERTY_ID_PREEVALUATED: + case PROPERTY_ID_PRESERVEIRI: + case PROPERTY_ID_BACKTRANSPARENT: + case PROPERTY_ID_CONTROLBACKGROUNDTRANSPARENT: + { + if ( _rControlValueType.getTypeClass() == uno::TypeClass_STRING ) + { + const uno::Reference< inspection::XStringRepresentation > xConversionHelper = inspection::StringRepresentation::create( m_xContext,m_xTypeConverter ); + aControlValue <<= xConversionHelper->convertToControlValue( aPropertyValue ); + } + else + { + try + { + aControlValue = m_xTypeConverter->convertTo( aPropertyValue, _rControlValueType ); + } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "GeometryHandler::convertToControlValue: caught an exception while converting via TypeConverter!" ); + } + } + break; + } + case PROPERTY_ID_CONDITIONALPRINTEXPRESSION: + case PROPERTY_ID_INITIALFORMULA: + case PROPERTY_ID_FORMULA: + lcl_convertFormulaTo(aPropertyValue,aControlValue); + break; + case PROPERTY_ID_DATAFIELD: + { + OUString sValue; + aControlValue >>= sValue; + if ( isDefaultFunction(sValue,sValue) ) + aControlValue <<= sValue; + else + lcl_convertFormulaTo(aPropertyValue,aControlValue); + } + break; + case PROPERTY_ID_FONT: + aControlValue = m_xFormComponentHandler->convertToControlValue(PROPERTY_FONT, aPropertyValue, _rControlValueType); + break; + case PROPERTY_ID_POSITIONX: + { + sal_Int32 nPosX = 0; + aPropertyValue >>= nPosX; + const uno::Reference< report::XReportComponent> xSourceReportComponent(m_xReportComponent,uno::UNO_QUERY); + if ( xSourceReportComponent->getSection().is() ) + nPosX -= getStyleProperty<sal_Int32>(xSourceReportComponent->getSection()->getReportDefinition(),PROPERTY_LEFTMARGIN); + aPropertyValue <<= nPosX; + aControlValue = m_xFormComponentHandler->convertToControlValue(PropertyName, aPropertyValue, _rControlValueType); + } + break; + case PROPERTY_ID_FORMULALIST: + aControlValue <<= m_sDefaultFunction; + break; + case PROPERTY_ID_SCOPE: + aControlValue <<= m_sScope; + break; + case PROPERTY_ID_MIMETYPE: + aControlValue = aPropertyValue; + break; + case PROPERTY_ID_TYPE: + { + if (m_nDataFieldType < SAL_N_ELEMENTS(RID_STR_TYPE_CONST) - 1) + aControlValue <<= RptResId(RID_STR_TYPE_CONST[m_nDataFieldType]); + } + break; + case PROPERTY_ID_VERTICALALIGN: + { + style::VerticalAlignment nParagraphVertAlign = style::VerticalAlignment_TOP; + aPropertyValue >>= nParagraphVertAlign; + if (sal_uInt32(nParagraphVertAlign) < SAL_N_ELEMENTS(RID_STR_VERTICAL_ALIGN_CONST) - 1) + aControlValue <<= RptResId(RID_STR_VERTICAL_ALIGN_CONST[static_cast<sal_uInt32>(nParagraphVertAlign)]); + } + break; + case PROPERTY_ID_PARAADJUST: + { + sal_Int16 nParagraphAdjust = sal_Int16(style::ParagraphAdjust_LEFT); + aPropertyValue >>= nParagraphAdjust; + if (o3tl::make_unsigned(nParagraphAdjust) < SAL_N_ELEMENTS(RID_STR_PARAADJUST_CONST) - 1) + aControlValue <<= RptResId(RID_STR_PARAADJUST_CONST[nParagraphAdjust]); + } + break; + case PROPERTY_ID_BACKCOLOR: + case PROPERTY_ID_CONTROLBACKGROUND: + { + Color nColor = COL_TRANSPARENT; + if ( (aPropertyValue >>= nColor) && COL_TRANSPARENT == nColor ) + aPropertyValue.clear(); + } + [[fallthrough]]; + default: + aControlValue = m_xFormComponentHandler->convertToControlValue(PropertyName, aPropertyValue, _rControlValueType); + } + return aControlValue; +} +void SAL_CALL GeometryHandler::addPropertyChangeListener(const uno::Reference< beans::XPropertyChangeListener > & _rxListener) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + m_aPropertyListeners.addInterface( _rxListener ); + m_xFormComponentHandler->addPropertyChangeListener(_rxListener); +} + +void SAL_CALL GeometryHandler::removePropertyChangeListener(const uno::Reference< beans::XPropertyChangeListener > & _rxListener) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + m_aPropertyListeners.removeInterface( _rxListener ); + m_xFormComponentHandler->removePropertyChangeListener(_rxListener); +} + + +uno::Sequence< beans::Property > SAL_CALL GeometryHandler::getSupportedProperties() +{ + ::std::vector< beans::Property > aNewProps; + aNewProps.reserve(20); // only a guess + rptui::OPropertyInfoService::getExcludeProperties( aNewProps, m_xFormComponentHandler ); + + const OUString pIncludeProperties[] = + { + OUString(PROPERTY_FORCENEWPAGE) + ,OUString(PROPERTY_KEEPTOGETHER) + ,OUString(PROPERTY_CANGROW) + ,OUString(PROPERTY_CANSHRINK) + ,OUString(PROPERTY_REPEATSECTION) + ,OUString(PROPERTY_PRINTREPEATEDVALUES) + ,OUString(PROPERTY_CONDITIONALPRINTEXPRESSION) + ,OUString(PROPERTY_STARTNEWCOLUMN) + ,OUString(PROPERTY_RESETPAGENUMBER) + ,OUString(PROPERTY_PRINTWHENGROUPCHANGE) + ,OUString(PROPERTY_VISIBLE) + ,OUString(PROPERTY_PAGEHEADEROPTION) + ,OUString(PROPERTY_PAGEFOOTEROPTION) + ,OUString("ControlLabel") + ,OUString(PROPERTY_POSITIONX) + ,OUString(PROPERTY_POSITIONY) + ,OUString(PROPERTY_WIDTH) + ,OUString(PROPERTY_HEIGHT) + ,OUString(PROPERTY_AUTOGROW) + ,OUString(PROPERTY_PREEVALUATED) + ,OUString(PROPERTY_DEEPTRAVERSING) + ,OUString(PROPERTY_FORMULA) + ,OUString(PROPERTY_INITIALFORMULA) + ,OUString(PROPERTY_PRESERVEIRI) + ,OUString(PROPERTY_DATAFIELD) + ,OUString(PROPERTY_FONT) + ,OUString(PROPERTY_BACKCOLOR) + ,OUString(PROPERTY_BACKTRANSPARENT) + ,OUString(PROPERTY_CONTROLBACKGROUND) + ,OUString(PROPERTY_CONTROLBACKGROUNDTRANSPARENT) + ,OUString(PROPERTY_LABEL) + ,OUString(PROPERTY_MIMETYPE) + ,OUString(PROPERTY_VERTICALALIGN) + ,OUString(PROPERTY_PARAADJUST) + }; + const uno::Reference < beans::XPropertySetInfo > xInfo = m_xReportComponent->getPropertySetInfo(); + const uno::Sequence< beans::Property> aSeq = xInfo->getProperties(); + for (const auto & rIncludeProp : pIncludeProperties) + { + const beans::Property* pFind = ::std::find_if(aSeq.begin(), aSeq.end(), + [&rIncludeProp] (const beans::Property& x) -> bool { + return x.Name == rIncludeProp; + }); + if ( pFind != aSeq.end() ) + { + // special case for controls which contain a data field + if ( PROPERTY_DATAFIELD == rIncludeProp ) + { + beans::Property aValue; + aValue.Name = PROPERTY_FORMULALIST; + aNewProps.push_back(aValue); + aValue.Name = PROPERTY_SCOPE; + aNewProps.push_back(aValue); + aValue.Name = PROPERTY_TYPE; + aNewProps.push_back(aValue); + } + aNewProps.push_back(*pFind); + } + } + + // special property for shapes +// if ( uno::Reference< report::XShape>(m_xReportComponent,uno::UNO_QUERY).is() ) +// { +// beans::Property aValue; +// aValue.Name = PROPERTY_AREA; +// aNewProps.push_back(aValue); +// } + // re-enable when the remaining issues of #i88727# are fixed + + return uno::Sequence< beans::Property > (&(*aNewProps.begin()),aNewProps.size()); +} + +uno::Sequence< OUString > SAL_CALL GeometryHandler::getSupersededProperties() +{ + uno::Sequence< OUString > aRet; + const uno::Reference<report::XReportDefinition> xReport(m_xReportComponent,uno::UNO_QUERY); + if ( xReport.is() && !uno::Reference< report::XSection>(xReport->getParent(),uno::UNO_QUERY).is() ) + { + aRet.realloc(5); + OUString* pIter = aRet.getArray(); + *pIter++ = PROPERTY_POSITIONX; + *pIter++ = PROPERTY_POSITIONY; + *pIter++ = PROPERTY_WIDTH; + *pIter++ = PROPERTY_HEIGHT; + *pIter++ = PROPERTY_DATAFIELD; + } + return aRet; +} + +uno::Sequence< OUString > SAL_CALL GeometryHandler::getActuatingProperties() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + uno::Sequence< OUString > aSeq + { + PROPERTY_BACKTRANSPARENT, + PROPERTY_CONTROLBACKGROUNDTRANSPARENT, + PROPERTY_FORMULALIST, + PROPERTY_TYPE, + PROPERTY_DATAFIELD + }; + + return ::comphelper::concatSequences(m_xFormComponentHandler->getActuatingProperties(),aSeq); +} + +sal_Bool SAL_CALL GeometryHandler::isComposable(const OUString & _rPropertyName) +{ + return OPropertyInfoService::isComposable( _rPropertyName, m_xFormComponentHandler ); +} + +inspection::InteractiveSelectionResult SAL_CALL GeometryHandler::onInteractivePropertySelection(const OUString & PropertyName, sal_Bool Primary, uno::Any & _rData, const uno::Reference< inspection::XObjectInspectorUI > & _rxInspectorUI) +{ + if ( !_rxInspectorUI.is() ) + throw lang::NullPointerException(); + if (PropertyName == PROPERTY_FILTER) + { + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + inspection::InteractiveSelectionResult eResult = inspection::InteractiveSelectionResult_Cancelled; + OUString sClause; + if ( impl_dialogFilter_nothrow( sClause, aGuard ) ) + { + _rData <<= sClause; + eResult = inspection::InteractiveSelectionResult_ObtainedValue; + } + return eResult; + } + else if (PropertyName == PROPERTY_FONT) + { + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + inspection::InteractiveSelectionResult eResult = inspection::InteractiveSelectionResult_Cancelled; + const uno::Reference< awt::XWindow> xInspectorWindow(m_xContext->getValueByName("DialogParentWindow") ,uno::UNO_QUERY); + const uno::Reference< report::XReportControlFormat> xReportControlFormat(m_xReportComponent,uno::UNO_QUERY); + aGuard.clear(); + + uno::Sequence< beans::NamedValue > aFontSettings; + if ( rptui::openCharDialog( xReportControlFormat, xInspectorWindow, aFontSettings ) ) + { + _rData <<= aFontSettings; + eResult = inspection::InteractiveSelectionResult_ObtainedValue; + } + return eResult; + } + else if ( PropertyName == PROPERTY_FORMULA + || PropertyName == PROPERTY_INITIALFORMULA + || PropertyName == PROPERTY_DATAFIELD + || PropertyName == PROPERTY_CONDITIONALPRINTEXPRESSION) + { + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + + OUString sFormula; + m_xReportComponent->getPropertyValue(PropertyName) >>= sFormula; + const uno::Reference< awt::XWindow> xInspectorWindow(m_xContext->getValueByName("DialogParentWindow") ,uno::UNO_QUERY); + uno::Reference< uno::XComponentContext > xContext = m_xContext; + uno::Reference< beans::XPropertySet > xRowSet( m_xRowSet,uno::UNO_QUERY); + aGuard.clear(); + + inspection::InteractiveSelectionResult eResult = inspection::InteractiveSelectionResult_Cancelled; + if ( rptui::openDialogFormula_nothrow( sFormula, xContext,xInspectorWindow,xRowSet ) ) + { + _rData <<= sFormula; + eResult = inspection::InteractiveSelectionResult_ObtainedValue; + } + return eResult; + } + else if (PropertyName == PROPERTY_AREA) + { + ::osl::ClearableMutexGuard aGuard( m_aMutex ); + + inspection::InteractiveSelectionResult eResult = inspection::InteractiveSelectionResult_Cancelled; + const uno::Reference< awt::XWindow> xInspectorWindow(m_xContext->getValueByName("DialogParentWindow") ,uno::UNO_QUERY); + const uno::Reference< report::XShape> xShape(m_xReportComponent,uno::UNO_QUERY); + aGuard.clear(); + + if ( rptui::openAreaDialog( xShape, xInspectorWindow) ) + { + eResult = inspection::InteractiveSelectionResult_ObtainedValue; + beans::PropertyChangeEvent aScopeEvent; + aScopeEvent.PropertyName = PROPERTY_FILLCOLOR; + aScopeEvent.NewValue = xShape->getPropertyValue(PROPERTY_FILLCOLOR); + m_aPropertyListeners.notifyEach( &beans::XPropertyChangeListener::propertyChange, aScopeEvent ); + } + return eResult; + } + + + return m_xFormComponentHandler->onInteractivePropertySelection(PropertyName, Primary, _rData, _rxInspectorUI); +} + +void SAL_CALL GeometryHandler::actuatingPropertyChanged(const OUString & ActuatingPropertyName, const uno::Any & NewValue, const uno::Any & OldValue, const uno::Reference< inspection::XObjectInspectorUI > & _rxInspectorUI, sal_Bool _bFirstTimeInit) +{ + if ( !_rxInspectorUI.is() ) + throw lang::NullPointerException(); + + ::osl::MutexGuard aGuard( m_aMutex ); + const sal_Int32 nId = OPropertyInfoService::getPropertyId(ActuatingPropertyName); + switch(nId) + { + case PROPERTY_ID_TYPE: + { + sal_uInt32 nNewVal = 0; + NewValue >>= nNewVal; + switch(nNewVal) + { + case DATA_OR_FORMULA: + _rxInspectorUI->rebuildPropertyUI(PROPERTY_DATAFIELD); + _rxInspectorUI->enablePropertyUI(PROPERTY_DATAFIELD,true); + _rxInspectorUI->enablePropertyUI(PROPERTY_FORMULALIST,false); + _rxInspectorUI->enablePropertyUI(PROPERTY_SCOPE,false); + OSL_ENSURE(m_sDefaultFunction.isEmpty(),"Why is the m_sDefaultFunction set?"); + OSL_ENSURE(m_sScope.isEmpty(),"Why is the m_sScope set?"); + break; + case FUNCTION: + _rxInspectorUI->rebuildPropertyUI(PROPERTY_DATAFIELD); + _rxInspectorUI->rebuildPropertyUI(PROPERTY_FORMULALIST); + _rxInspectorUI->enablePropertyUI(PROPERTY_DATAFIELD,true); + _rxInspectorUI->enablePropertyUI(PROPERTY_FORMULALIST,!m_sDefaultFunction.isEmpty()); + _rxInspectorUI->enablePropertyUI(PROPERTY_SCOPE,!m_sScope.isEmpty()); + break; + case USER_DEF_FUNCTION: + _rxInspectorUI->enablePropertyUI(PROPERTY_DATAFIELD,false); + _rxInspectorUI->enablePropertyUI(PROPERTY_FORMULALIST,true); + _rxInspectorUI->rebuildPropertyUI(PROPERTY_FORMULALIST); + _rxInspectorUI->enablePropertyUI(PROPERTY_SCOPE,false); + break; + case COUNTER: + _rxInspectorUI->enablePropertyUI(PROPERTY_DATAFIELD,false); + _rxInspectorUI->enablePropertyUI(PROPERTY_FORMULALIST,false); + _rxInspectorUI->enablePropertyUI(PROPERTY_SCOPE,true); + break; + } + } + break; + case PROPERTY_ID_DATAFIELD: + { + bool bEnable = (m_nDataFieldType != DATA_OR_FORMULA && m_nDataFieldType != COUNTER ); + if ( bEnable ) + { + OUString sValue; + m_xReportComponent->getPropertyValue( PROPERTY_DATAFIELD ) >>= sValue; + bEnable = !sValue.isEmpty(); + } + _rxInspectorUI->enablePropertyUI(PROPERTY_FORMULALIST,bEnable); + if ( bEnable ) + { + _rxInspectorUI->rebuildPropertyUI(PROPERTY_DATAFIELD); + _rxInspectorUI->rebuildPropertyUI(PROPERTY_FORMULALIST); + } + m_xFormComponentHandler->actuatingPropertyChanged(ActuatingPropertyName, NewValue, OldValue, _rxInspectorUI, _bFirstTimeInit); + } + break; + case PROPERTY_ID_FORMULALIST: + { + _rxInspectorUI->enablePropertyUI(PROPERTY_SCOPE,m_nDataFieldType == FUNCTION || m_nDataFieldType == COUNTER); + } + break; + case PROPERTY_ID_BACKTRANSPARENT: + case PROPERTY_ID_CONTROLBACKGROUNDTRANSPARENT: + { + bool bValue = false; + NewValue >>= bValue; + bValue = !bValue; + _rxInspectorUI->enablePropertyUI(PROPERTY_BACKCOLOR,bValue); + _rxInspectorUI->enablePropertyUI(PROPERTY_CONTROLBACKGROUND,bValue); + } + break; + default: + m_xFormComponentHandler->actuatingPropertyChanged(ActuatingPropertyName, NewValue, OldValue, _rxInspectorUI, _bFirstTimeInit); + break; + } +} + +sal_Bool SAL_CALL GeometryHandler::suspend(sal_Bool Suspend) +{ + return m_xFormComponentHandler->suspend(Suspend); +} + +bool GeometryHandler::impl_dialogFilter_nothrow( OUString& _out_rSelectedClause, ::osl::ClearableMutexGuard& _rClearBeforeDialog ) const +{ + _out_rSelectedClause.clear(); + bool bSuccess = false; + ::dbtools::SQLExceptionInfo aErrorInfo; + uno::Reference< awt::XWindow > xInspectorWindow; + uno::Reference< lang::XMultiComponentFactory > xFactory; + try + { + xFactory = m_xContext->getServiceManager(); + xInspectorWindow.set(m_xContext->getValueByName("DialogParentWindow") ,uno::UNO_QUERY); + uno::Reference<sdbc::XConnection> xCon(m_xContext->getValueByName("ActiveConnection") ,uno::UNO_QUERY); + if ( !xCon.is() ) + return false; + + uno::Reference< beans::XPropertySet> xRowSetProp(m_xRowSet,uno::UNO_QUERY); + if ( !m_xRowSet.is() ) + { + m_xRowSet.set(xFactory->createInstanceWithContext("com.sun.star.sdb.RowSet",m_xContext),uno::UNO_QUERY); + xRowSetProp.set(m_xRowSet,uno::UNO_QUERY); + xRowSetProp->setPropertyValue(PROPERTY_ACTIVECONNECTION,uno::Any(xCon)); + ::comphelper::copyProperties(m_xReportComponent,xRowSetProp); + } + + // get a composer for the statement which the form is currently based on + uno::Reference< sdb::XSingleSelectQueryComposer > xComposer( ::dbtools::getCurrentSettingsComposer( xRowSetProp, m_xContext, nullptr ) ); + OSL_ENSURE( xComposer.is(), "GeometryHandler::impl_dialogFilter_nothrow: could not obtain a composer!" ); + if ( !xComposer.is() ) + return false; + + // create the dialog + uno::Reference< ui::dialogs::XExecutableDialog > xDialog = sdb::FilterDialog::createWithQuery(m_xContext, xComposer, m_xRowSet, xInspectorWindow); + + const OUString sPropertyUIName(RptResId(RID_STR_FILTER)); + // initialize the dialog + xDialog->setTitle( sPropertyUIName ); + + _rClearBeforeDialog.clear(); + bSuccess = ( xDialog->execute() != 0 ); + if ( bSuccess ) + _out_rSelectedClause = xComposer->getFilter(); + } + catch (const sdb::SQLContext& e) { aErrorInfo = e; } + catch (const sdbc::SQLWarning& e) { aErrorInfo = e; } + catch (const sdbc::SQLException& e) { aErrorInfo = e; } + catch( const uno::Exception& ) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "GeometryHandler::impl_dialogFilter_nothrow" ); + } + + if ( aErrorInfo.isValid() ) + ::dbtools::showError( aErrorInfo, xInspectorWindow, m_xContext ); + + return bSuccess; +} + +void GeometryHandler::checkPosAndSize( const awt::Point& _aNewPos, + const awt::Size& _aSize) +{ + const uno::Reference< report::XReportComponent> xSourceReportComponent(m_xReportComponent,uno::UNO_QUERY); + const uno::Reference< report::XSection> xSection(xSourceReportComponent->getParent(),uno::UNO_QUERY); + if ( !xSection.is() || uno::Reference< report::XShape>(xSourceReportComponent,uno::UNO_QUERY).is() ) // shapes can overlap. + return; + + ::Point aPos(VCLPoint(_aNewPos)); + if ( aPos.X() < 0 || aPos.Y() < 0 ) // TODO: have to check size with pos aka || (aPos.X() + aAwtSize.Width) > m_xSection->getReportDefinition()-> + throw beans::PropertyVetoException(RptResId(RID_STR_ILLEGAL_POSITION),xSourceReportComponent); + + ::tools::Rectangle aSourceRect(aPos,VCLSize(_aSize)); + + const sal_Int32 nCount = xSection->getCount(); + for (sal_Int32 i = 0; i < nCount ; ++i) + { + const uno::Reference< report::XReportComponent> xReportComponent(xSection->getByIndex(i),uno::UNO_QUERY); + if ( xReportComponent.is() && xReportComponent != xSourceReportComponent ) + { + const ::tools::Rectangle aBoundRect(VCLPoint(xReportComponent->getPosition()),VCLSize(xReportComponent->getSize())); + const ::tools::Rectangle aRect = aSourceRect.GetIntersection(aBoundRect); + if ( !aRect.IsEmpty() && (aRect.Left() != aRect.Right() && aRect.Top() != aRect.Bottom() ) ) + throw beans::PropertyVetoException(RptResId( RID_STR_OVERLAP_OTHER_CONTROL),xSourceReportComponent); + } + } +} + +void GeometryHandler::impl_fillFormulaList_nothrow(::std::vector< OUString >& out_rList) const +{ + if ( m_nDataFieldType == FUNCTION ) + { + for (auto const& it : m_aDefaultFunctions) + { + out_rList.push_back(it.getName()); + } + } + else if ( m_nDataFieldType == USER_DEF_FUNCTION ) + ::std::transform( m_aFunctionNames.begin(), + m_aFunctionNames.end(), + ::std::back_inserter(out_rList), + ::o3tl::select1st< TFunctions::value_type >() ); +} + +OUString GeometryHandler::impl_ConvertUIToMimeType_nothrow(const OUString& _sUIName) const +{ + ::std::vector< OUString > aList; + impl_fillMimeTypes_nothrow(aList); + OUString sRet; + ::std::vector< OUString >::const_iterator aFind = ::std::find(aList.begin(),aList.end(),_sUIName); + if ( aFind != aList.end() ) + { + const std::size_t nPos = aFind - aList.begin(); + const uno::Reference< report::XReportDefinition> xReportDefinition(m_xReportComponent,uno::UNO_QUERY); + if ( xReportDefinition.is() ) + { + const uno::Sequence< OUString > aMimeTypes( xReportDefinition->getAvailableMimeTypes() ); + sRet = aMimeTypes[nPos]; + } + } + return sRet; +} + +OUString GeometryHandler::impl_ConvertMimeTypeToUI_nothrow(const OUString& _sMimetype) const +{ + ::comphelper::MimeConfigurationHelper aMimeHelper(m_xContext); + OUString sRet; + std::shared_ptr<const SfxFilter> pFilter = SfxFilter::GetDefaultFilter( aMimeHelper.GetDocServiceNameFromMediaType(_sMimetype) ); + if ( pFilter ) + sRet = pFilter->GetUIName(); + if ( sRet.isEmpty() ) + sRet = _sMimetype; + return sRet; +} + +void GeometryHandler::impl_fillMimeTypes_nothrow(::std::vector< OUString >& _out_rList) const +{ + try + { + const uno::Reference< report::XReportDefinition> xReportDefinition(m_xReportComponent,uno::UNO_QUERY); + if ( xReportDefinition.is() ) + { + const uno::Sequence< OUString > aMimeTypes( xReportDefinition->getAvailableMimeTypes() ); + for(const OUString& rMimeType : aMimeTypes) + { + const OUString sDocName( impl_ConvertMimeTypeToUI_nothrow(rMimeType) ); + if ( !sDocName.isEmpty() ) + _out_rList.push_back(sDocName); + } + } + } + catch(uno::Exception&) + { + TOOLS_WARN_EXCEPTION( "reportdesign", ""); + } +} + +void GeometryHandler::impl_fillScopeList_nothrow(::std::vector< OUString >& _out_rList) const +{ + try + { + const uno::Reference< report::XReportComponent> xSourceReportComponent(m_xReportComponent,uno::UNO_QUERY_THROW); + const uno::Reference< report::XSection> xSection(xSourceReportComponent->getParent(),uno::UNO_QUERY_THROW); + + const uno::Reference< report::XReportDefinition> xReportDefinition = xSection->getReportDefinition(); + const uno::Reference< report::XGroups> xGroups = xReportDefinition->getGroups(); + sal_Int32 nPos = -1; + uno::Reference< report::XGroup> xGroup = xSection->getGroup(); + if ( xGroup.is() ) + nPos = getPositionInIndexAccess(xGroups,xGroup); + else if ( xSection == xReportDefinition->getDetail() ) + nPos = xGroups->getCount()-1; + + const OUString sGroup = RptResId(RID_STR_SCOPE_GROUP); + for (sal_Int32 i = 0 ; i <= nPos ; ++i) + { + xGroup.set(xGroups->getByIndex(i),uno::UNO_QUERY_THROW); + OUString sGroupName = sGroup.replaceFirst("%1",xGroup->getExpression()); + _out_rList.push_back(sGroupName); + } + _out_rList.push_back(xReportDefinition->getName()); + } + catch(uno::Exception&) + { + TOOLS_WARN_EXCEPTION( "reportdesign", ""); + } +} + +uno::Reference< report::XFunctionsSupplier> GeometryHandler::fillScope_throw(OUString& _rsNamePostfix) +{ + uno::Reference< report::XFunctionsSupplier> xReturn; + + const uno::Reference< report::XReportComponent> xSourceReportComponent(m_xReportComponent,uno::UNO_QUERY_THROW); + const uno::Reference< report::XSection> xSection(xSourceReportComponent->getParent(),uno::UNO_QUERY_THROW); + const uno::Reference< report::XReportDefinition> xReportDefinition = xSection->getReportDefinition(); + if ( m_sScope.isEmpty() ) + { + const uno::Reference< report::XGroup> xGroup = xSection->getGroup(); + if ( xGroup.is() ) + { + OUString sGroupName = RptResId(RID_STR_SCOPE_GROUP); + _rsNamePostfix = xGroup->getExpression(); + m_sScope = sGroupName.replaceFirst("%1",_rsNamePostfix); + xReturn = xGroup.get(); + } + else if ( xSection == xReportDefinition->getDetail() ) + { + const uno::Reference< report::XGroups> xGroups = xReportDefinition->getGroups(); + const sal_Int32 nCount = xGroups->getCount(); + if ( nCount ) + { + const uno::Reference< report::XGroup> xGroup2(xGroups->getByIndex(nCount - 1),uno::UNO_QUERY_THROW); + OUString sGroupName = RptResId(RID_STR_SCOPE_GROUP); + _rsNamePostfix = xGroup2->getExpression(); + m_sScope = sGroupName.replaceFirst("%1",_rsNamePostfix); + xReturn = xGroup2.get(); + } + } + if ( m_sScope.isEmpty() ) + { + xReturn = xReportDefinition.get(); + _rsNamePostfix = m_sScope = xReportDefinition->getName(); + } + } + else if ( m_sScope == xReportDefinition->getName() ) + { + xReturn = xReportDefinition.get(); + _rsNamePostfix = m_sScope; + } + else + { + uno::Reference< report::XGroups> xGroups = xReportDefinition->getGroups(); + const sal_Int32 nCount = xGroups->getCount(); + + for (sal_Int32 i = 0 ; i < nCount; ++i) + { + const uno::Reference< report::XGroup> xGroup(xGroups->getByIndex(i),uno::UNO_QUERY_THROW); + OUString sGroupName = RptResId(RID_STR_SCOPE_GROUP); + if ( m_sScope == sGroupName.replaceFirst("%1",xGroup->getExpression()) ) + { + _rsNamePostfix = xGroup->getExpression(); + xReturn = xGroup.get(); + break; + } + } + + } + OSL_ENSURE(xReturn.is(),"Why don't we have a functionssupplier here!"); + + return xReturn; +} + +bool GeometryHandler::isDefaultFunction( const OUString& _sQuotedFunction + ,OUString& _rDataField + ,const uno::Reference< report::XFunctionsSupplier>& _xFunctionsSupplier + ,bool _bSet) const +{ + bool bDefaultFunction = false; + try + { + const uno::Reference< report::XReportComponent> xSourceReportComponent(m_xReportComponent,uno::UNO_QUERY_THROW); + const uno::Reference< report::XSection> xSection(xSourceReportComponent->getParent(),uno::UNO_QUERY_THROW); + const uno::Reference< report::XReportDefinition> xReportDefinition = xSection->getReportDefinition(); + + ::std::pair<TFunctions::const_iterator,TFunctions::const_iterator> aFind = m_aFunctionNames.equal_range(_sQuotedFunction); + while ( aFind.first != aFind.second ) + { + if ( !_xFunctionsSupplier.is() || _xFunctionsSupplier == aFind.first->second.second ) + { + const beans::Optional< OUString> aInitialFormula = aFind.first->second.first->getInitialFormula(); + if ( aInitialFormula.IsPresent ) + { + OUString sDefaultFunctionName; + bDefaultFunction = impl_isDefaultFunction_nothrow(aFind.first->second.first,_rDataField,sDefaultFunctionName); + if ( bDefaultFunction ) + { + m_xFunction = aFind.first->second.first; + if ( _bSet ) + { + m_sDefaultFunction = sDefaultFunctionName; + uno::Reference< report::XGroup> xGroup(aFind.first->second.second,uno::UNO_QUERY); + if ( xGroup.is() ) + { + OUString sGroupName = RptResId(RID_STR_SCOPE_GROUP); + m_sScope = sGroupName.replaceFirst("%1",xGroup->getExpression()); + } + else + m_sScope = xReportDefinition->getName(); + } + } + break; + } + } + ++(aFind.first); + } + } + catch(uno::Exception&) + { + TOOLS_WARN_EXCEPTION( "reportdesign", ""); + } + return bDefaultFunction; +} + +bool GeometryHandler::impl_isDefaultFunction_nothrow( const uno::Reference< report::XFunction>& _xFunction + ,OUString& _rDataField + ,OUString& _rsDefaultFunctionName) const +{ + bool bDefaultFunction = false; + try + { + const OUString sFormula( _xFunction->getFormula() ); + i18nutil::SearchOptions2 aSearchOptions; + aSearchOptions.AlgorithmType2 = util::SearchAlgorithms2::REGEXP; + aSearchOptions.searchFlag = 0x00000100; + auto aIter = std::find_if(m_aDefaultFunctions.begin(), m_aDefaultFunctions.end(), + [&aSearchOptions, &sFormula](const DefaultFunction& rDefaultFunction) { + aSearchOptions.searchString = rDefaultFunction.m_sSearchString; + utl::TextSearch aTextSearch( aSearchOptions); + sal_Int32 start = 0; + sal_Int32 end = sFormula.getLength(); + return aTextSearch.SearchForward(sFormula, &start, &end) && start == 0 && end == sFormula.getLength(); + }); + if (aIter != m_aDefaultFunctions.end()) // default function found + { + sal_Int32 start = 0; + sal_Int32 end = sFormula.getLength(); + aSearchOptions.searchString = "\\[[:alpha:]+([:space:]*[:alnum:]*)*\\]"; + utl::TextSearch aDataSearch( aSearchOptions); + (void)aDataSearch.SearchForward(sFormula, &start, &end); + ++start; + _rDataField = sFormula.copy(start,end-start-1); + _rsDefaultFunctionName = aIter->m_sName; + bDefaultFunction = true; + } + } + catch(uno::Exception&) + { + TOOLS_WARN_EXCEPTION( "reportdesign", ""); + } + return bDefaultFunction; +} + +void GeometryHandler::loadDefaultFunctions() +{ + if ( !m_aDefaultFunctions.empty() ) + return; + + m_aCounterFunction.m_bPreEvaluated = false; + m_aCounterFunction.m_sName = RptResId(RID_STR_F_COUNTER); + m_aCounterFunction.m_sFormula = "rpt:[%FunctionName] + 1"; + m_aCounterFunction.m_sSearchString = "rpt:\\[[:alpha:]+([:space:]*[:alnum:]*)*\\][:space:]*\\+[:space:]*[:digit:]*"; + m_aCounterFunction.m_sInitialFormula.IsPresent = true; + m_aCounterFunction.m_sInitialFormula.Value = "rpt:1"; + + DefaultFunction aDefault; + + aDefault.m_bPreEvaluated = true; + + aDefault.m_sName = RptResId(RID_STR_F_ACCUMULATION); + aDefault.m_sFormula = "rpt:[%Column] + [%FunctionName]"; + aDefault.m_sSearchString = "rpt:\\[[:alpha:]+([:space:]*[:alnum:]*)*\\][:space:]*\\+[:space:]*\\[[:alpha:]+([:space:]*[:alnum:]*)*\\]"; + aDefault.m_sInitialFormula.IsPresent = true; + aDefault.m_sInitialFormula.Value = "rpt:[%Column]"; + m_aDefaultFunctions.push_back(aDefault); + + aDefault.m_sName = RptResId(RID_STR_F_MINIMUM); + aDefault.m_sFormula = "rpt:IF([%Column] < [%FunctionName];[%Column];[%FunctionName])"; + aDefault.m_sSearchString = "rpt:IF\\((\\[[:alpha:]+([:space:]*[:alnum:]*)*\\])[:space:]*<[:space:]*(\\[[:alpha:]+([:space:]*[:alnum:]*)*\\]);[:space:]*\\1[:space:]*;[:space:]*\\3[:space:]*\\)"; + aDefault.m_sInitialFormula.IsPresent = true; + aDefault.m_sInitialFormula.Value = "rpt:[%Column]"; + m_aDefaultFunctions.push_back(aDefault); + + aDefault.m_sName = RptResId(RID_STR_F_MAXIMUM); + aDefault.m_sFormula = "rpt:IF([%Column] > [%FunctionName];[%Column];[%FunctionName])"; + aDefault.m_sSearchString = "rpt:IF\\((\\[[:alpha:]+([:space:]*[:alnum:]*)*\\])[:space:]*>[:space:]*(\\[[:alpha:]+([:space:]*[:alnum:]*)*\\]);[:space:]*\\1[:space:]*;[:space:]*\\3[:space:]*\\)"; + aDefault.m_sInitialFormula.IsPresent = true; + aDefault.m_sInitialFormula.Value = "rpt:[%Column]"; + m_aDefaultFunctions.push_back(aDefault); +} + +void GeometryHandler::createDefaultFunction(::osl::ResettableMutexGuard& _aGuard ,const OUString& _sFunction,std::u16string_view _sDataField) +{ + try + { + OUString sNamePostfix; + const uno::Reference< report::XFunctionsSupplier> xFunctionsSupplier = fillScope_throw(sNamePostfix); + + auto aIter = std::find_if(m_aDefaultFunctions.begin(), m_aDefaultFunctions.end(), + [&_sFunction](const DefaultFunction& rDefaultFunction) { return rDefaultFunction.m_sName == _sFunction; }); + if (aIter != m_aDefaultFunctions.end()) + { + const OUString sFunctionName( _sFunction + _sDataField + sNamePostfix); + const OUString sQuotedFunctionName(lcl_getQuotedFunctionName(sFunctionName)); + + beans::PropertyChangeEvent aEvent; + aEvent.PropertyName = PROPERTY_SCOPE; + aEvent.OldValue <<= m_sScope; + + ::std::pair<TFunctions::const_iterator,TFunctions::const_iterator> aFind = m_aFunctionNames.equal_range(sQuotedFunctionName); + while ( aFind.first != aFind.second ) + { + if ( xFunctionsSupplier == aFind.first->second.second ) + { + m_xFunction = aFind.first->second.first; + OUString sTemp; + isDefaultFunction(sQuotedFunctionName,sTemp,uno::Reference< report::XFunctionsSupplier>(),true); // implicitly sets the m_sScope + break; + } + ++(aFind.first); + } + if ( aFind.first == aFind.second ) + impl_createFunction(sFunctionName,_sDataField,*aIter); + + OBlocker aBlocker(m_bIn); + m_xReportComponent->setPropertyValue(PROPERTY_DATAFIELD,uno::Any( impl_convertToFormula( uno::Any(sQuotedFunctionName) ))); + aEvent.NewValue <<= m_sScope; + _aGuard.clear(); + m_aPropertyListeners.notifyEach( &beans::XPropertyChangeListener::propertyChange, aEvent ); + } + } + catch(uno::Exception&) + { + TOOLS_WARN_EXCEPTION( "reportdesign", ""); + } +} + +void GeometryHandler::removeFunction() +{ + if ( !m_xFunction.is() ) + return; + + const OUString sQuotedFunctionName(lcl_getQuotedFunctionName(m_xFunction)); + ::std::pair<TFunctions::iterator,TFunctions::iterator> aFind = m_aFunctionNames.equal_range(sQuotedFunctionName); + while ( aFind.first != aFind.second ) + { + if ( aFind.first->second.first == m_xFunction ) + { + uno::Reference< report::XFunctions> xFunctions = aFind.first->second.second->getFunctions(); + xFunctions->removeByIndex(xFunctions->getCount() - 1 ); /// TODO: insert new method in XFunctions: removeFunction(xfunction) + m_aFunctionNames.erase(aFind.first); + m_bNewFunction = false; + break; + } + ++(aFind.first); + } +} + +void GeometryHandler::resetOwnProperties(::osl::ResettableMutexGuard& _aGuard,const OUString& _sOldFunctionName,const OUString& _sOldScope,const sal_uInt32 _nOldDataFieldType) +{ + const OUString sNewFunction = m_sDefaultFunction; + const OUString sNewScope = m_sScope; + const sal_uInt32 nNewDataFieldType = m_nDataFieldType; + _aGuard.clear(); + if ( _nOldDataFieldType != nNewDataFieldType ) + { + beans::PropertyChangeEvent aScopeEvent; + aScopeEvent.PropertyName = PROPERTY_TYPE; + aScopeEvent.OldValue <<= _nOldDataFieldType; + aScopeEvent.NewValue <<= nNewDataFieldType; + m_aPropertyListeners.notifyEach( &beans::XPropertyChangeListener::propertyChange, aScopeEvent ); + } + if ( _sOldFunctionName != sNewFunction ) + { + beans::PropertyChangeEvent aFormulaEvent; + aFormulaEvent.PropertyName = PROPERTY_FORMULALIST; + aFormulaEvent.OldValue <<= _sOldFunctionName; + aFormulaEvent.NewValue <<= sNewFunction; + + m_aPropertyListeners.notifyEach( &beans::XPropertyChangeListener::propertyChange, aFormulaEvent ); + } + if ( _sOldScope != sNewScope ) + { + beans::PropertyChangeEvent aScopeEvent; + aScopeEvent.PropertyName = PROPERTY_SCOPE; + aScopeEvent.OldValue <<= _sOldScope; + aScopeEvent.NewValue <<= sNewScope; + m_aPropertyListeners.notifyEach( &beans::XPropertyChangeListener::propertyChange, aScopeEvent ); + } + + _aGuard.reset(); +} + +void GeometryHandler::impl_initFieldList_nothrow( uno::Sequence< OUString >& _rFieldNames ) const +{ + _rFieldNames.realloc(0); + try + { + uno::Reference< awt::XWindow> xInspectorWindow(m_xContext->getValueByName("DialogParentWindow") ,uno::UNO_QUERY); + weld::WaitObject aWaitCursor(Application::GetFrameWeld(xInspectorWindow)); + + // get the form of the control we're inspecting + uno::Reference< beans::XPropertySet > xFormSet( m_xRowSet, uno::UNO_QUERY ); + if ( !xFormSet.is() ) + return; + + OUString sObjectName; + OSL_VERIFY( xFormSet->getPropertyValue( PROPERTY_COMMAND ) >>= sObjectName ); + // when there is no command we don't need to ask for columns + uno::Reference<sdbc::XConnection> xCon(m_xContext->getValueByName("ActiveConnection") ,uno::UNO_QUERY); + if ( !sObjectName.isEmpty() && xCon.is() ) + { + sal_Int32 nObjectType = sdb::CommandType::COMMAND; + OSL_VERIFY( xFormSet->getPropertyValue( PROPERTY_COMMANDTYPE ) >>= nObjectType ); + + _rFieldNames = ::dbtools::getFieldNamesByCommandDescriptor( xCon, nObjectType, sObjectName ); + } + } + catch (uno::Exception&) + { + TOOLS_WARN_EXCEPTION( "reportdesign", "GeometryHandler::impl_initFieldList_nothrow" ); + } +} + +bool GeometryHandler::impl_isCounterFunction_throw(const OUString& _sQuotedFunctionName,OUString& Out_sScope) const +{ + ::std::pair<TFunctions::const_iterator,TFunctions::const_iterator> aFind = m_aFunctionNames.equal_range(_sQuotedFunctionName); + while ( aFind.first != aFind.second ) + { + const beans::Optional< OUString> aInitialFormula = aFind.first->second.first->getInitialFormula(); + if ( aInitialFormula.IsPresent ) + { + const OUString sFormula( aFind.first->second.first->getFormula() ); + i18nutil::SearchOptions2 aSearchOptions; + aSearchOptions.AlgorithmType2 = util::SearchAlgorithms2::REGEXP; + aSearchOptions.searchFlag = 0x00000100; + aSearchOptions.searchString = m_aCounterFunction.m_sSearchString; + utl::TextSearch aTextSearch( aSearchOptions); + sal_Int32 start = 0; + sal_Int32 end = sFormula.getLength(); + if ( aTextSearch.SearchForward(sFormula,&start,&end) && start == 0 && end == sFormula.getLength()) // counter function found + { + const uno::Reference< report::XGroup > xGroup(aFind.first->second.second,uno::UNO_QUERY); + if ( xGroup.is() ) + { + OUString sGroupName = RptResId(RID_STR_SCOPE_GROUP); + Out_sScope = sGroupName.replaceFirst("%1",xGroup->getExpression()); + } + else + Out_sScope = uno::Reference< report::XReportDefinition >(aFind.first->second.second,uno::UNO_QUERY_THROW)->getName(); + break; + } + } + ++(aFind.first); + } + return aFind.first != aFind.second; +} + +void GeometryHandler::impl_createFunction(const OUString& _sFunctionName,std::u16string_view _sDataField,const DefaultFunction& _aFunction) +{ + if ( m_bNewFunction ) + removeFunction(); + + const OUString sQuotedFunctionName(lcl_getQuotedFunctionName(_sFunctionName)); + m_xFunction.set(report::Function::create(m_xContext)); + m_xFunction->setName( _sFunctionName ); + + static const OUStringLiteral sPlaceHolder1(u"%Column"); + static const OUStringLiteral sPlaceHolder2(u"%FunctionName"); + OUString sFormula(_aFunction.m_sFormula); + sFormula = sFormula.replaceAll(sPlaceHolder1,_sDataField); + sFormula = sFormula.replaceAll(sPlaceHolder2,_sFunctionName); + + m_xFunction->setFormula(sFormula); + m_xFunction->setPreEvaluated(_aFunction.m_bPreEvaluated); + m_xFunction->setDeepTraversing(false); + if ( _aFunction.m_sInitialFormula.IsPresent ) + { + beans::Optional< OUString> aInitialFormula = _aFunction.m_sInitialFormula; + OUString sInitialFormula = aInitialFormula.Value; + sInitialFormula = sInitialFormula.replaceAll(sPlaceHolder1,_sDataField); + sInitialFormula = sInitialFormula.replaceAll(sPlaceHolder2,_sFunctionName); + aInitialFormula.Value = sInitialFormula; + m_xFunction->setInitialFormula( aInitialFormula ); + } + OUString sNamePostfix; + const uno::Reference< report::XFunctionsSupplier> xFunctionsSupplier = fillScope_throw(sNamePostfix); + const uno::Reference< container::XIndexContainer> xFunctions(xFunctionsSupplier->getFunctions(),uno::UNO_QUERY_THROW); + xFunctions->insertByIndex(xFunctions->getCount(),uno::Any(m_xFunction)); + m_aFunctionNames.emplace(sQuotedFunctionName,TFunctionPair(m_xFunction,xFunctionsSupplier)); + m_bNewFunction = true; +} + +void GeometryHandler::impl_setCounterFunction_throw() +{ + OUString sNamePostfix; + fillScope_throw(sNamePostfix); + OUString sFunctionName = m_aCounterFunction.m_sName + sNamePostfix; + const OUString sQuotedFunctionName = lcl_getQuotedFunctionName(sFunctionName); + OUString sScope; + if ( !(!sFunctionName.isEmpty() && m_aFunctionNames.find(sQuotedFunctionName) != m_aFunctionNames.end() && impl_isCounterFunction_throw(sQuotedFunctionName,sScope)) ) + impl_createFunction(sFunctionName,{},m_aCounterFunction); + + OBlocker aBlocker(m_bIn); + m_xReportComponent->setPropertyValue(PROPERTY_DATAFIELD,uno::Any(impl_convertToFormula( uno::Any(sQuotedFunctionName)))); +} + +sal_uInt32 GeometryHandler::impl_getDataFieldType_throw(const OUString& _sDataField) const +{ + sal_uInt32 nDataFieldType = UNDEF_DATA; + OUString sDataField; + if ( !_sDataField.isEmpty() ) + sDataField = _sDataField; + else + { + uno::Any aDataField( m_xReportComponent->getPropertyValue( PROPERTY_DATAFIELD ) ); + lcl_convertFormulaTo(aDataField,aDataField); + aDataField >>= sDataField; + } + + if ( !sDataField.isEmpty() ) + { + if ( impl_isDataField(sDataField) ) + nDataFieldType = DATA_OR_FORMULA; + else if ( isDefaultFunction(sDataField,sDataField) ) + nDataFieldType = FUNCTION; + else if ( m_aFunctionNames.find(sDataField) != m_aFunctionNames.end() ) + { + nDataFieldType = USER_DEF_FUNCTION; + OUString sScope; + if ( impl_isCounterFunction_throw(sDataField,sScope) ) + nDataFieldType = COUNTER; + } + else + nDataFieldType = DATA_OR_FORMULA; + } + return nDataFieldType; +} + +// XEventListener +void SAL_CALL GeometryHandler::disposing(const lang::EventObject& ) +{ +} +// XPropertyChangeListener +void SAL_CALL GeometryHandler::propertyChange(const beans::PropertyChangeEvent& /*evt*/) +{ + ::osl::ResettableMutexGuard aGuard( m_aMutex ); + if ( m_bIn ) + return; + + const sal_uInt32 nOldDataFieldType = m_nDataFieldType; + const OUString sOldFunctionName = m_sDefaultFunction; + const OUString sOldScope = m_sScope; + m_sDefaultFunction.clear(); + m_sScope.clear(); + m_nDataFieldType = impl_getDataFieldType_throw(); + if ( UNDEF_DATA == m_nDataFieldType ) + m_nDataFieldType = nOldDataFieldType; + uno::Any aDataField = m_xReportComponent->getPropertyValue( PROPERTY_DATAFIELD ); + lcl_convertFormulaTo(aDataField,aDataField); + OUString sDataField; + aDataField >>= sDataField; + switch(m_nDataFieldType) + { + case FUNCTION: + isDefaultFunction(sDataField,sDataField,uno::Reference< report::XFunctionsSupplier>(),true); + break; + case COUNTER: + impl_isCounterFunction_throw(sDataField,m_sScope); + break; + default: + ; + } + + resetOwnProperties(aGuard,sOldFunctionName,sOldScope,nOldDataFieldType); +} + +} // namespace rptui + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +reportdesign_GeometryHandler_get_implementation( + css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new rptui::GeometryHandler(context)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inspection/ReportComponentHandler.cxx b/reportdesign/source/ui/inspection/ReportComponentHandler.cxx new file mode 100644 index 000000000..28b33acc4 --- /dev/null +++ b/reportdesign/source/ui/inspection/ReportComponentHandler.cxx @@ -0,0 +1,199 @@ +/* -*- 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 <ReportComponentHandler.hxx> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/lang/NullPointerException.hpp> +#include <comphelper/types.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <com/sun/star/form/inspection/FormComponentPropertyHandler.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <metadata.hxx> + + +namespace rptui +{ + +using namespace ::com::sun::star; + +ReportComponentHandler::ReportComponentHandler(uno::Reference< uno::XComponentContext > const & context) + :ReportComponentHandler_Base(m_aMutex) + ,m_xContext(context) +{ + try + { + m_xFormComponentHandler = form::inspection::FormComponentPropertyHandler::create(m_xContext); + + }catch(const uno::Exception &) + { + } +} + +OUString SAL_CALL ReportComponentHandler::getImplementationName( ) +{ + return "com.sun.star.comp.report.ReportComponentHandler"; +} + +sal_Bool SAL_CALL ReportComponentHandler::supportsService( const OUString& ServiceName ) +{ + return cppu::supportsService(this, ServiceName); +} + +uno::Sequence< OUString > SAL_CALL ReportComponentHandler::getSupportedServiceNames( ) +{ + return { "com.sun.star.report.inspection.ReportComponentHandler" }; +} + +// override WeakComponentImplHelperBase::disposing() +// This function is called upon disposing the component, +// if your component needs special work when it becomes +// disposed, do it here. +void SAL_CALL ReportComponentHandler::disposing() +{ + ::comphelper::disposeComponent(m_xFormComponentHandler); +} +void SAL_CALL ReportComponentHandler::addEventListener(const uno::Reference< lang::XEventListener > & xListener) +{ + m_xFormComponentHandler->addEventListener(xListener); +} + +void SAL_CALL ReportComponentHandler::removeEventListener(const uno::Reference< lang::XEventListener > & aListener) +{ + m_xFormComponentHandler->removeEventListener(aListener); +} + +// inspection::XPropertyHandler: + +/********************************************************************************/ +void SAL_CALL ReportComponentHandler::inspect(const uno::Reference< uno::XInterface > & Component) +{ + try + { + uno::Reference< container::XNameContainer > xNameCont(Component,uno::UNO_QUERY); + static const OUStringLiteral sFormComponent(u"FormComponent"); + if ( xNameCont->hasByName(sFormComponent) ) + xNameCont->getByName(sFormComponent) >>= m_xFormComponent; + static const OUStringLiteral sRowSet(u"RowSet"); + if ( xNameCont->hasByName(sRowSet) ) + { + uno::Reference<beans::XPropertySet> xProp(m_xFormComponentHandler,uno::UNO_QUERY); + xProp->setPropertyValue(sRowSet,xNameCont->getByName(sRowSet)); + } + } + catch(const uno::Exception &) + { + throw lang::NullPointerException(); + } + if ( m_xFormComponent.is() ) + { + m_xFormComponentHandler->inspect(m_xFormComponent); + } +} + +uno::Any SAL_CALL ReportComponentHandler::getPropertyValue(const OUString & PropertyName) +{ + return m_xFormComponentHandler->getPropertyValue(PropertyName); +} + +void SAL_CALL ReportComponentHandler::setPropertyValue(const OUString & PropertyName, const uno::Any & Value) +{ + m_xFormComponentHandler->setPropertyValue(PropertyName, Value); +} + +beans::PropertyState SAL_CALL ReportComponentHandler::getPropertyState(const OUString & PropertyName) +{ + return m_xFormComponentHandler->getPropertyState(PropertyName); +} + +inspection::LineDescriptor SAL_CALL ReportComponentHandler::describePropertyLine(const OUString & PropertyName, const uno::Reference< inspection::XPropertyControlFactory > & ControlFactory) +{ + return m_xFormComponentHandler->describePropertyLine(PropertyName, ControlFactory); +} + +uno::Any SAL_CALL ReportComponentHandler::convertToPropertyValue(const OUString & PropertyName, const uno::Any & ControlValue) +{ + return m_xFormComponentHandler->convertToPropertyValue(PropertyName, ControlValue); +} + +uno::Any SAL_CALL ReportComponentHandler::convertToControlValue(const OUString & PropertyName, const uno::Any & PropertyValue, const uno::Type & ControlValueType) +{ + return m_xFormComponentHandler->convertToControlValue(PropertyName, PropertyValue, ControlValueType); +} + +void SAL_CALL ReportComponentHandler::addPropertyChangeListener(const uno::Reference< beans::XPropertyChangeListener > & Listener) +{ + m_xFormComponentHandler->addPropertyChangeListener(Listener); +} + +void SAL_CALL ReportComponentHandler::removePropertyChangeListener(const uno::Reference< beans::XPropertyChangeListener > & _rxListener) +{ + m_xFormComponentHandler->removePropertyChangeListener(_rxListener); +} + +uno::Sequence< beans::Property > SAL_CALL ReportComponentHandler::getSupportedProperties() +{ + ::std::vector< beans::Property > aNewProps; + rptui::OPropertyInfoService::getExcludeProperties( aNewProps, m_xFormComponentHandler ); + + return uno::Sequence< beans::Property >(aNewProps.data(), aNewProps.size()); +} + +uno::Sequence< OUString > SAL_CALL ReportComponentHandler::getSupersededProperties() +{ + uno::Sequence< OUString > aRet; + return aRet; +} + +uno::Sequence< OUString > SAL_CALL ReportComponentHandler::getActuatingProperties() +{ + return m_xFormComponentHandler->getActuatingProperties(); +} + +sal_Bool SAL_CALL ReportComponentHandler::isComposable( const OUString& _rPropertyName ) +{ + return OPropertyInfoService::isComposable( _rPropertyName, m_xFormComponentHandler ); +} + +inspection::InteractiveSelectionResult SAL_CALL ReportComponentHandler::onInteractivePropertySelection(const OUString & PropertyName, sal_Bool Primary, uno::Any & out_Data, const uno::Reference< inspection::XObjectInspectorUI > & InspectorUI) +{ + return m_xFormComponentHandler->onInteractivePropertySelection(PropertyName, Primary, out_Data, InspectorUI); +} + +void SAL_CALL ReportComponentHandler::actuatingPropertyChanged(const OUString & ActuatingPropertyName, const uno::Any & NewValue, const uno::Any & OldValue, const uno::Reference< inspection::XObjectInspectorUI > & InspectorUI, sal_Bool FirstTimeInit) +{ + m_xFormComponentHandler->actuatingPropertyChanged(ActuatingPropertyName, NewValue, OldValue, InspectorUI, FirstTimeInit); +} + +sal_Bool SAL_CALL ReportComponentHandler::suspend(sal_Bool Suspend) +{ + return m_xFormComponentHandler->suspend(Suspend); +} + + +} // namespace rptui + + +extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* +reportdesign_ReportComponentHandler_get_implementation( + css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&) +{ + return cppu::acquire(new rptui::ReportComponentHandler(context)); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/reportdesign/source/ui/inspection/metadata.cxx b/reportdesign/source/ui/inspection/metadata.cxx new file mode 100644 index 000000000..59bbdb21d --- /dev/null +++ b/reportdesign/source/ui/inspection/metadata.cxx @@ -0,0 +1,293 @@ +/* -*- 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 <metadata.hxx> +#include <com/sun/star/inspection/XPropertyHandler.hpp> +#include <core_resource.hxx> +#include <helpids.h> +#include <strings.hrc> +#include <strings.hxx> + +#include <algorithm> +#include <string_view> + +namespace rptui +{ + + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star; + + + //= OPropertyInfoImpl + + struct OPropertyInfoImpl + { + OUString sName; + OUString sTranslation; + OString sHelpId; + sal_Int32 nId; + PropUIFlags nUIFlags; + + OPropertyInfoImpl( + const OUString& rName, + sal_Int32 _nId, + const OUString& aTranslation, + const OString& _sHelpId, + PropUIFlags _nUIFlags); + }; + + + OPropertyInfoImpl::OPropertyInfoImpl(const OUString& _rName, sal_Int32 _nId, + const OUString& aString, const OString& sHid, PropUIFlags _nUIFlags) + :sName(_rName) + ,sTranslation(aString) + ,sHelpId(sHid) + ,nId(_nId) + ,nUIFlags(_nUIFlags) + { + } + + namespace { + + // compare PropertyInfo + struct PropertyInfoLessByName + { + bool operator()( const OPropertyInfoImpl& _lhs, const OPropertyInfoImpl& _rhs ) + { + return _lhs.sName < _rhs.sName; + } + }; + + } + + //= OPropertyInfoService + + sal_uInt16 OPropertyInfoService::s_nCount = 0; + OPropertyInfoImpl* OPropertyInfoService::s_pPropertyInfos = nullptr; + + const OPropertyInfoImpl* OPropertyInfoService::getPropertyInfo() + { + if ( s_pPropertyInfos ) + return s_pPropertyInfos; + + static OPropertyInfoImpl aPropertyInfos[] = + { + OPropertyInfoImpl(PROPERTY_FORCENEWPAGE, PROPERTY_ID_FORCENEWPAGE, RptResId(RID_STR_FORCENEWPAGE), HID_RPT_PROP_FORCENEWPAGE, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_NEWROWORCOL, PROPERTY_ID_NEWROWORCOL, RptResId(RID_STR_NEWROWORCOL), HID_RPT_PROP_NEWROWORCOL, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_KEEPTOGETHER, PROPERTY_ID_KEEPTOGETHER, RptResId(RID_STR_KEEPTOGETHER), HID_RPT_PROP_KEEPTOGETHER, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_CANGROW, PROPERTY_ID_CANGROW, RptResId(RID_STR_CANGROW), HID_RPT_PROP_CANGROW, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_CANSHRINK, PROPERTY_ID_CANSHRINK, RptResId(RID_STR_CANSHRINK), HID_RPT_PROP_CANSHRINK, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_REPEATSECTION, PROPERTY_ID_REPEATSECTION, RptResId(RID_STR_REPEATSECTION), HID_RPT_PROP_REPEATSECTION, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_PRINTREPEATEDVALUES, PROPERTY_ID_PRINTREPEATEDVALUES, RptResId(RID_STR_PRINTREPEATEDVALUES), HID_RPT_PROP_PRINTREPEATEDVALUES, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_CONDITIONALPRINTEXPRESSION, PROPERTY_ID_CONDITIONALPRINTEXPRESSION, RptResId(RID_STR_CONDITIONALPRINTEXPRESSION), HID_RPT_PROP_CONDITIONALPRINTEXPRESSION, + PropUIFlags::Composeable ), + OPropertyInfoImpl(PROPERTY_STARTNEWCOLUMN, PROPERTY_ID_STARTNEWCOLUMN, RptResId(RID_STR_STARTNEWCOLUMN), HID_RPT_PROP_STARTNEWCOLUMN, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_RESETPAGENUMBER, PROPERTY_ID_RESETPAGENUMBER, RptResId(RID_STR_RESETPAGENUMBER), HID_RPT_PROP_RESETPAGENUMBER, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_PRINTWHENGROUPCHANGE, PROPERTY_ID_PRINTWHENGROUPCHANGE, RptResId(RID_STR_PRINTWHENGROUPCHANGE), HID_RPT_PROP_PRINTWHENGROUPCHANGE, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_VISIBLE, PROPERTY_ID_VISIBLE, RptResId(RID_STR_VISIBLE), HID_RPT_PROP_VISIBLE, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_GROUPKEEPTOGETHER, PROPERTY_ID_GROUPKEEPTOGETHER, RptResId(RID_STR_GROUPKEEPTOGETHER), HID_RPT_PROP_GROUPKEEPTOGETHER, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_PAGEHEADEROPTION, PROPERTY_ID_PAGEHEADEROPTION, RptResId(RID_STR_PAGEHEADEROPTION), HID_RPT_PROP_PAGEHEADEROPTION, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_PAGEFOOTEROPTION, PROPERTY_ID_PAGEFOOTEROPTION, RptResId(RID_STR_PAGEFOOTEROPTION), HID_RPT_PROP_PAGEFOOTEROPTION, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_POSITIONX, PROPERTY_ID_POSITIONX, RptResId(RID_STR_POSITIONX), HID_RPT_PROP_RPT_POSITIONX, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_POSITIONY, PROPERTY_ID_POSITIONY, RptResId(RID_STR_POSITIONY), HID_RPT_PROP_RPT_POSITIONY, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_WIDTH, PROPERTY_ID_WIDTH, RptResId(RID_STR_WIDTH), HID_RPT_PROP_RPT_WIDTH, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_HEIGHT, PROPERTY_ID_HEIGHT, RptResId(RID_STR_HEIGHT), HID_RPT_PROP_RPT_HEIGHT, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_AUTOGROW, PROPERTY_ID_AUTOGROW, RptResId(RID_STR_AUTOGROW), HID_RPT_PROP_RPT_AUTOGROW, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_FONT, PROPERTY_ID_FONT, RptResId(RID_STR_FONT), HID_RPT_PROP_RPT_FONT, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_PREEVALUATED, PROPERTY_ID_PREEVALUATED, RptResId(RID_STR_PREEVALUATED), HID_RPT_PROP_PREEVALUATED, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_DEEPTRAVERSING, PROPERTY_ID_DEEPTRAVERSING, RptResId(RID_STR_DEEPTRAVERSING), HID_RPT_PROP_DEEPTRAVERSING, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_FORMULA, PROPERTY_ID_FORMULA, RptResId(RID_STR_FORMULA), HID_RPT_PROP_FORMULA, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_INITIALFORMULA, PROPERTY_ID_INITIALFORMULA, RptResId(RID_STR_INITIALFORMULA), HID_RPT_PROP_INITIALFORMULA, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_TYPE, PROPERTY_ID_TYPE, RptResId(RID_STR_TYPE), HID_RPT_PROP_TYPE, PropUIFlags::Composeable | PropUIFlags::DataProperty), + OPropertyInfoImpl(PROPERTY_DATAFIELD,PROPERTY_ID_DATAFIELD, RptResId(RID_STR_DATAFIELD), HID_RPT_PROP_DATAFIELD, PropUIFlags::Composeable | PropUIFlags::DataProperty), + OPropertyInfoImpl(PROPERTY_FORMULALIST, PROPERTY_ID_FORMULALIST, RptResId(RID_STR_FORMULALIST), HID_RPT_PROP_FORMULALIST, PropUIFlags::Composeable | PropUIFlags::DataProperty), + OPropertyInfoImpl(PROPERTY_SCOPE, PROPERTY_ID_SCOPE, RptResId(RID_STR_SCOPE), HID_RPT_PROP_SCOPE, PropUIFlags::Composeable | PropUIFlags::DataProperty), + OPropertyInfoImpl(PROPERTY_PRESERVEIRI, PROPERTY_ID_PRESERVEIRI, RptResId(RID_STR_PRESERVEIRI), HID_RPT_PROP_PRESERVEIRI, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_BACKCOLOR, PROPERTY_ID_BACKCOLOR, RptResId(RID_STR_BACKCOLOR), HID_RPT_PROP_BACKCOLOR, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_CONTROLBACKGROUND, PROPERTY_ID_CONTROLBACKGROUND, RptResId(RID_STR_BACKCOLOR), HID_RPT_PROP_BACKCOLOR, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_BACKTRANSPARENT, PROPERTY_ID_BACKTRANSPARENT, RptResId(RID_STR_BACKTRANSPARENT), HID_RPT_PROP_BACKTRANSPARENT, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_CONTROLBACKGROUNDTRANSPARENT, PROPERTY_ID_CONTROLBACKGROUNDTRANSPARENT, RptResId(RID_STR_CONTROLBACKGROUNDTRANSPARENT), HID_RPT_PROP_CONTROLBACKGROUNDTRANSPARENT, + PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_CHARTTYPE, PROPERTY_ID_CHARTTYPE, RptResId(RID_STR_CHARTTYPE), HID_RPT_PROP_CHARTTYPE, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_PREVIEW_COUNT, PROPERTY_ID_PREVIEW_COUNT, RptResId(RID_STR_PREVIEW_COUNT), HID_RPT_PROP_PREVIEW_COUNT, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_MASTERFIELDS, PROPERTY_ID_MASTERFIELDS, RptResId(RID_STR_MASTERFIELDS), HID_RPT_PROP_MASTERFIELDS, PropUIFlags::Composeable | PropUIFlags::DataProperty), + OPropertyInfoImpl(PROPERTY_DETAILFIELDS, PROPERTY_ID_DETAILFIELDS, RptResId(RID_STR_DETAILFIELDS), HID_RPT_PROP_DETAILFIELDS, PropUIFlags::Composeable | PropUIFlags::DataProperty), + OPropertyInfoImpl(PROPERTY_AREA, PROPERTY_ID_AREA, RptResId(RID_STR_AREA), HID_RPT_PROP_AREA, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_MIMETYPE, PROPERTY_ID_MIMETYPE, RptResId(RID_STR_MIMETYPE), HID_RPT_PROP_MIMETYPE, PropUIFlags::Composeable | PropUIFlags::DataProperty), + OPropertyInfoImpl(PROPERTY_PARAADJUST, PROPERTY_ID_PARAADJUST, RptResId(RID_STR_PARAADJUST), HID_RPT_PROP_PARAADJUST, PropUIFlags::Composeable), + OPropertyInfoImpl(PROPERTY_VERTICALALIGN, PROPERTY_ID_VERTICALALIGN, RptResId(RID_STR_VERTICALALIGN), HID_RPT_PROP_VERTICALALIGN, PropUIFlags::Composeable) + }; + + s_pPropertyInfos = aPropertyInfos; + s_nCount = SAL_N_ELEMENTS(aPropertyInfos); + ::std::sort( aPropertyInfos, aPropertyInfos + SAL_N_ELEMENTS(aPropertyInfos), PropertyInfoLessByName() ); + + return s_pPropertyInfos; + } + + + sal_Int32 OPropertyInfoService::getPropertyId(const OUString& _rName) + { + const OPropertyInfoImpl* pInfo = getPropertyInfo(_rName); + return pInfo ? pInfo->nId : -1; + } + + + OUString OPropertyInfoService::getPropertyTranslation(sal_Int32 _nId) + { + const OPropertyInfoImpl* pInfo = getPropertyInfo(_nId); + return pInfo ? pInfo->sTranslation : OUString(); + } + + + OString OPropertyInfoService::getPropertyHelpId(sal_Int32 _nId) + { + const OPropertyInfoImpl* pInfo = getPropertyInfo(_nId); + return pInfo ? pInfo->sHelpId : OString(); + } + + + PropUIFlags OPropertyInfoService::getPropertyUIFlags(sal_Int32 _nId) + { + const OPropertyInfoImpl* pInfo = getPropertyInfo(_nId); + return pInfo ? pInfo->nUIFlags : PropUIFlags::NONE; + } + + + const OPropertyInfoImpl* OPropertyInfoService::getPropertyInfo(const OUString& _rName) + { + // initialization + if(!s_pPropertyInfos) + getPropertyInfo(); + OPropertyInfoImpl aSearch(_rName, 0, OUString(), "", PropUIFlags::NONE); + + const OPropertyInfoImpl* pPropInfo = ::std::lower_bound( + s_pPropertyInfos, s_pPropertyInfos + s_nCount, aSearch, PropertyInfoLessByName() ); + + if ( ( pPropInfo < s_pPropertyInfos + s_nCount ) && pPropInfo->sName == _rName ) + return pPropInfo; + + return nullptr; + } + + + const OPropertyInfoImpl* OPropertyInfoService::getPropertyInfo(sal_Int32 _nId) + { + // initialization + if(!s_pPropertyInfos) + getPropertyInfo(); + + // TODO: a real structure which allows quick access by name as well as by id + for (sal_uInt16 i = 0; i < s_nCount; i++) + if (s_pPropertyInfos[i].nId == _nId) + return &s_pPropertyInfos[i]; + + return nullptr; + } + + + bool OPropertyInfoService::isComposable( const OUString& _rPropertyName, const css::uno::Reference< css::inspection::XPropertyHandler >& _rxFormComponentHandler ) + { + sal_Int32 nId = getPropertyId( _rPropertyName ); + if ( nId != -1 ) + { + PropUIFlags nFlags = getPropertyUIFlags( nId ); + return bool( nFlags & PropUIFlags::Composeable ); + } + + return _rxFormComponentHandler->isComposable( _rPropertyName ); + } + + + void OPropertyInfoService::getExcludeProperties(::std::vector< beans::Property >& _rExcludeProperties,const css::uno::Reference< css::inspection::XPropertyHandler >& _xFormComponentHandler) + { + const uno::Sequence< beans::Property > aProps = _xFormComponentHandler->getSupportedProperties(); + static const std::u16string_view pExcludeProperties[] = + { + u"Enabled", + u"Printable", + u"WordBreak", + u"MultiLine", + u"Tag", + u"HelpText", + u"HelpURL", + u"MaxTextLen", + u"ReadOnly", + u"Tabstop", + u"TabIndex", + u"ValueMin", + u"ValueMax", + u"Spin", + u"SpinValue", + u"SpinValueMin", + u"SpinValueMax", + u"DefaultSpinValue", + u"SpinIncrement", + u"Repeat", + u"RepeatDelay", + u"ControlLabel", /// TODO: has to be checked + u"LabelControl", + u"Title", // comment this out if you want to have title feature for charts + u"" PROPERTY_MAXTEXTLEN, + u"" PROPERTY_EFFECTIVEDEFAULT, + u"" PROPERTY_EFFECTIVEMAX, + u"" PROPERTY_EFFECTIVEMIN, + u"HideInactiveSelection", + u"SubmitAction", + u"InputRequired", + u"VerticalAlign", + u"" PROPERTY_ALIGN, + u"" PROPERTY_EMPTY_IS_NULL, + u"" PROPERTY_FILTERPROPOSAL + ,u"" PROPERTY_POSITIONX + ,u"" PROPERTY_POSITIONY + ,u"" PROPERTY_WIDTH + ,u"" PROPERTY_HEIGHT + ,u"" PROPERTY_AUTOGROW + ,u"" PROPERTY_FONT + ,u"" PROPERTY_LABEL + ,u"" PROPERTY_LINECOLOR + ,u"" PROPERTY_BORDER + ,u"" PROPERTY_BORDERCOLOR + ,u"" PROPERTY_BACKTRANSPARENT + ,u"" PROPERTY_CONTROLBACKGROUND + ,u"" PROPERTY_BACKGROUNDCOLOR + ,u"" PROPERTY_CONTROLBACKGROUNDTRANSPARENT + ,u"" PROPERTY_FORMULALIST + ,u"" PROPERTY_SCOPE + ,u"" PROPERTY_TYPE + ,u"" PROPERTY_DATASOURCENAME + ,u"" PROPERTY_VERTICALALIGN + }; + + for (beans::Property const & prop : aProps) + { + size_t nPos = 0; + for (; nPos < SAL_N_ELEMENTS(pExcludeProperties) && pExcludeProperties[nPos] != prop.Name; ++nPos ) + ; + if ( nPos == SAL_N_ELEMENTS(pExcludeProperties) ) + _rExcludeProperties.push_back(prop); + } + } + + +} // namespace pcr + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |