1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include "elementimport.hxx" 21 #include <xmloff/xmlimp.hxx> 22 #include <xmloff/nmspmap.hxx> 23 #include "strings.hxx" 24 #include "callbacks.hxx" 25 #include "attriblistmerge.hxx" 26 #include <xmloff/xmlnmspe.hxx> 27 #include "eventimport.hxx" 28 #include <xmloff/txtstyli.hxx> 29 #include "formenums.hxx" 30 #include <xmloff/xmltoken.hxx> 31 #include "gridcolumnproptranslator.hxx" 32 #include "property_description.hxx" 33 #include "property_meta_data.hxx" 34 35 #include <com/sun/star/uno/XComponentContext.hpp> 36 #include <com/sun/star/text/XText.hpp> 37 #include <com/sun/star/util/XCloneable.hpp> 38 #include <com/sun/star/util/Duration.hpp> 39 #include <com/sun/star/form/FormComponentType.hpp> 40 #include <com/sun/star/awt/ImagePosition.hpp> 41 #include <com/sun/star/beans/XMultiPropertySet.hpp> 42 #include <com/sun/star/beans/XPropertyContainer.hpp> 43 #include <com/sun/star/beans/PropertyAttribute.hpp> 44 45 #include <sax/tools/converter.hxx> 46 #include <tools/urlobj.hxx> 47 #include <tools/diagnose_ex.h> 48 #include <rtl/strbuf.hxx> 49 #include <sal/log.hxx> 50 #include <comphelper/extract.hxx> 51 #include <comphelper/types.hxx> 52 #include <comphelper/sequence.hxx> 53 54 #include <algorithm> 55 56 namespace xmloff 57 { 58 59 using namespace ::xmloff::token; 60 using namespace ::com::sun::star; 61 using namespace ::com::sun::star::uno; 62 using namespace ::com::sun::star::awt; 63 using namespace ::com::sun::star::container; 64 using namespace ::com::sun::star::beans; 65 using namespace ::com::sun::star::script; 66 using namespace ::com::sun::star::lang; 67 using namespace ::com::sun::star::form; 68 using namespace ::com::sun::star::xml; 69 using namespace ::com::sun::star::util; 70 using namespace ::com::sun::star::text; 71 using namespace ::comphelper; 72 using ::com::sun::star::xml::sax::XAttributeList; 73 74 #define PROPID_VALUE 1 75 #define PROPID_CURRENT_VALUE 2 76 #define PROPID_MIN_VALUE 3 77 #define PROPID_MAX_VALUE 4 78 79 struct PropertyValueLess 80 { operator ()xmloff::PropertyValueLess81 bool operator()(const PropertyValue& _rLeft, const PropertyValue& _rRight) 82 { 83 return _rLeft.Name < _rRight.Name; 84 } 85 }; 86 87 //= OElementNameMap 88 OElementNameMap::MapString2Element OElementNameMap::s_sElementTranslations; 89 operator ++(OControlElement::ElementType & _e)90 const OControlElement::ElementType& operator ++(OControlElement::ElementType& _e) 91 { 92 OControlElement::ElementType e = _e; 93 sal_Int32 nAsInt = static_cast<sal_Int32>(e); 94 _e = static_cast<OControlElement::ElementType>( ++nAsInt ); 95 return _e; 96 } 97 getElementType(const OUString & _rName)98 OControlElement::ElementType OElementNameMap::getElementType(const OUString& _rName) 99 { 100 if ( s_sElementTranslations.empty() ) 101 { // initialize 102 for (ElementType eType=ElementType(0); eType<UNKNOWN; ++eType) 103 s_sElementTranslations[OUString::createFromAscii(getElementName(eType))] = eType; 104 } 105 MapString2Element::const_iterator aPos = s_sElementTranslations.find(_rName); 106 if (s_sElementTranslations.end() != aPos) 107 return aPos->second; 108 109 return UNKNOWN; 110 } 111 112 //= OElementImport OElementImport(OFormLayerXMLImport_Impl & _rImport,IEventAttacherManager & _rEventManager,sal_uInt16 _nPrefix,const OUString & _rName,const Reference<XNameContainer> & _rxParentContainer)113 OElementImport::OElementImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const OUString& _rName, 114 const Reference< XNameContainer >& _rxParentContainer) 115 :OPropertyImport(_rImport, _nPrefix, _rName) 116 ,m_rFormImport(_rImport) 117 ,m_rEventManager(_rEventManager) 118 ,m_pStyleElement( nullptr ) 119 ,m_xParentContainer(_rxParentContainer) 120 ,m_bImplicitGenericAttributeHandling( true ) 121 { 122 OSL_ENSURE(m_xParentContainer.is(), "OElementImport::OElementImport: invalid parent container!"); 123 } 124 ~OElementImport()125 OElementImport::~OElementImport() 126 { 127 } 128 determineDefaultServiceName() const129 OUString OElementImport::determineDefaultServiceName() const 130 { 131 return OUString(); 132 } 133 StartElement(const Reference<XAttributeList> & _rxAttrList)134 void OElementImport::StartElement(const Reference< XAttributeList >& _rxAttrList) 135 { 136 ENTER_LOG_CONTEXT( "xmloff::OElementImport - importing one element" ); 137 138 const SvXMLNamespaceMap& rMap = m_rContext.getGlobalContext().GetNamespaceMap(); 139 const OUString sImplNameAttribute = rMap.GetQNameByKey( XML_NAMESPACE_FORM, GetXMLToken( XML_CONTROL_IMPLEMENTATION ) ); 140 const OUString sControlImplementation = _rxAttrList->getValueByName( sImplNameAttribute ); 141 142 // retrieve the service name 143 if ( !sControlImplementation.isEmpty() ) 144 { 145 OUString sOOoImplementationName; 146 const sal_uInt16 nImplPrefix = GetImport().GetNamespaceMap().GetKeyByAttrName( sControlImplementation, &sOOoImplementationName ); 147 m_sServiceName = ( nImplPrefix == XML_NAMESPACE_OOO ) ? sOOoImplementationName : sControlImplementation; 148 } 149 150 if ( m_sServiceName.isEmpty() ) 151 m_sServiceName = determineDefaultServiceName(); 152 153 // create the object *now*. This allows setting properties in the various handleAttribute methods. 154 // (Though currently not all code is migrated to this pattern, most attributes are still handled 155 // by remembering the value (via implPushBackPropertyValue), and setting the correct property value 156 // later (in OControlImport::StartElement).) 157 m_xElement = createElement(); 158 if ( m_xElement.is() ) 159 m_xInfo = m_xElement->getPropertySetInfo(); 160 161 // call the base class 162 OPropertyImport::StartElement( _rxAttrList ); 163 } 164 CreateChildContext(sal_uInt16 _nPrefix,const OUString & _rLocalName,const Reference<XAttributeList> & _rxAttrList)165 SvXMLImportContextRef OElementImport::CreateChildContext(sal_uInt16 _nPrefix, const OUString& _rLocalName, 166 const Reference< XAttributeList >& _rxAttrList) 167 { 168 if( token::IsXMLToken(_rLocalName, token::XML_EVENT_LISTENERS) && (XML_NAMESPACE_OFFICE == _nPrefix)) 169 return new OFormEventsImportContext(m_rFormImport.getGlobalContext(), _nPrefix, _rLocalName, *this); 170 171 return OPropertyImport::CreateChildContext(_nPrefix, _rLocalName, _rxAttrList); 172 } 173 EndElement()174 void OElementImport::EndElement() 175 { 176 OSL_ENSURE(m_xElement.is(), "OElementImport::EndElement: invalid element created!"); 177 if (!m_xElement.is()) 178 return; 179 180 // apply the non-generic properties 181 implApplySpecificProperties(); 182 183 // set the generic properties 184 implApplyGenericProperties(); 185 186 // set the style properties 187 if ( m_pStyleElement && m_xElement.is() ) 188 { 189 Reference< XPropertySet > xPropTranslation = 190 new OGridColumnPropertyTranslator( Reference< XMultiPropertySet >( m_xElement, UNO_QUERY ) ); 191 const_cast< XMLTextStyleContext* >( m_pStyleElement )->FillPropertySet( xPropTranslation ); 192 193 const OUString sNumberStyleName = m_pStyleElement->GetDataStyleName( ); 194 if ( !sNumberStyleName.isEmpty() ) 195 // the style also has a number (sub) style 196 m_rContext.applyControlNumberStyle( m_xElement, sNumberStyleName ); 197 } 198 199 // insert the element into the parent container 200 if (m_sName.isEmpty()) 201 { 202 OSL_FAIL("OElementImport::EndElement: did not find a name attribute!"); 203 m_sName = implGetDefaultName(); 204 } 205 206 if (m_xParentContainer.is()) 207 m_xParentContainer->insertByName(m_sName, makeAny(m_xElement)); 208 209 LEAVE_LOG_CONTEXT( ); 210 } 211 implApplySpecificProperties()212 void OElementImport::implApplySpecificProperties() 213 { 214 if ( m_aValues.empty() ) 215 return; 216 217 // set all the properties we collected 218 #if OSL_DEBUG_LEVEL > 0 219 // check if the object has all the properties 220 // (We do this in the non-pro version only. Doing it all the time would be too much expensive) 221 if ( m_xInfo.is() ) 222 { 223 for ( const auto& rCheck : m_aValues ) 224 { 225 OSL_ENSURE(m_xInfo->hasPropertyByName(rCheck.Name), 226 OStringBuffer("OElementImport::implApplySpecificProperties: read a property ("). 227 append(OUStringToOString(rCheck.Name, RTL_TEXTENCODING_ASCII_US)). 228 append(") which does not exist on the element!").getStr()); 229 } 230 } 231 #endif 232 233 // set the properties 234 const Reference< XMultiPropertySet > xMultiProps(m_xElement, UNO_QUERY); 235 bool bSuccess = false; 236 if (xMultiProps.is()) 237 { 238 // translate our properties so that the XMultiPropertySet can handle them 239 240 // sort our property value array so that we can use it in a setPropertyValues 241 ::std::sort( m_aValues.begin(), m_aValues.end(), PropertyValueLess()); 242 243 // the names 244 Sequence< OUString > aNames(m_aValues.size()); 245 OUString* pNames = aNames.getArray(); 246 // the values 247 Sequence< Any > aValues(m_aValues.size()); 248 Any* pValues = aValues.getArray(); 249 // copy 250 251 for ( const auto& rPropValues : m_aValues ) 252 { 253 *pNames = rPropValues.Name; 254 *pValues = rPropValues.Value; 255 ++pNames; 256 ++pValues; 257 } 258 259 try 260 { 261 xMultiProps->setPropertyValues(aNames, aValues); 262 bSuccess = true; 263 } 264 catch(const Exception&) 265 { 266 DBG_UNHANDLED_EXCEPTION("xmloff.forms"); 267 OSL_FAIL("OElementImport::implApplySpecificProperties: could not set the properties (using the XMultiPropertySet)!"); 268 } 269 } 270 271 if (!bSuccess) 272 { // no XMultiPropertySet or setting all properties at once failed 273 for ( const auto& rPropValues : m_aValues ) 274 { 275 // this try/catch here is expensive, but because this is just a fallback which should normally not be 276 // used it's acceptable this way ... 277 try 278 { 279 m_xElement->setPropertyValue(rPropValues.Name, rPropValues.Value); 280 } 281 catch(const Exception&) 282 { 283 DBG_UNHANDLED_EXCEPTION("xmloff.forms"); 284 OSL_FAIL(OStringBuffer("OElementImport::implApplySpecificProperties: could not set the property \""). 285 append(OUStringToOString(rPropValues.Name, RTL_TEXTENCODING_ASCII_US)). 286 append("\"!").getStr()); 287 } 288 } 289 } 290 } 291 implApplyGenericProperties()292 void OElementImport::implApplyGenericProperties() 293 { 294 if ( m_aGenericValues.empty() ) 295 return; 296 297 Reference< XPropertyContainer > xDynamicProperties( m_xElement, UNO_QUERY ); 298 299 // PropertyValueArray::iterator aEnd = m_aGenericValues.end(); 300 for ( auto& rPropValues : m_aGenericValues ) 301 { 302 // check property type for numeric types before setting 303 // the property 304 try 305 { 306 // if such a property does not yet exist at the element, create it if necessary 307 const bool bExistentProperty = m_xInfo->hasPropertyByName( rPropValues.Name ); 308 if ( !bExistentProperty ) 309 { 310 if ( !xDynamicProperties.is() ) 311 { 312 SAL_WARN( "xmloff", "OElementImport::implApplyGenericProperties: encountered an unknown property (" 313 << rPropValues.Name << "), but component is no PropertyBag!"); 314 continue; 315 } 316 317 xDynamicProperties->addProperty( 318 rPropValues.Name, 319 PropertyAttribute::BOUND | PropertyAttribute::REMOVABLE, 320 rPropValues.Value 321 ); 322 323 // re-fetch the PropertySetInfo 324 m_xInfo = m_xElement->getPropertySetInfo(); 325 } 326 327 // determine the type of the value (source for the following conversion) 328 TypeClass eValueTypeClass = rPropValues.Value.getValueTypeClass(); 329 const bool bValueIsSequence = TypeClass_SEQUENCE == eValueTypeClass; 330 if ( bValueIsSequence ) 331 { 332 uno::Type aSimpleType( getSequenceElementType( rPropValues.Value.getValueType() ) ); 333 eValueTypeClass = aSimpleType.getTypeClass(); 334 } 335 336 // determine the type of the property (target for the following conversion) 337 const Property aProperty( m_xInfo->getPropertyByName( rPropValues.Name ) ); 338 TypeClass ePropTypeClass = aProperty.Type.getTypeClass(); 339 const bool bPropIsSequence = TypeClass_SEQUENCE == ePropTypeClass; 340 if( bPropIsSequence ) 341 { 342 uno::Type aSimpleType( ::comphelper::getSequenceElementType( aProperty.Type ) ); 343 ePropTypeClass = aSimpleType.getTypeClass(); 344 } 345 346 if ( bPropIsSequence != bValueIsSequence ) 347 { 348 OSL_FAIL( "OElementImport::implImportGenericProperties: either both value and property should be a sequence, or none of them!" ); 349 continue; 350 } 351 352 if ( bValueIsSequence ) 353 { 354 OSL_ENSURE( eValueTypeClass == TypeClass_ANY, 355 "OElementImport::implApplyGenericProperties: only ANYs should have been imported as generic list property!" ); 356 // (OPropertyImport should produce only Sequencer< Any >, since it cannot know the real type 357 358 OSL_ENSURE( ePropTypeClass == TypeClass_SHORT, 359 "OElementImport::implApplyGenericProperties: conversion to sequences other than 'sequence< short >' not implemented, yet!" ); 360 361 Sequence< Any > aXMLValueList; 362 rPropValues.Value >>= aXMLValueList; 363 Sequence< sal_Int16 > aPropertyValueList( aXMLValueList.getLength() ); 364 365 std::transform(aXMLValueList.begin(), aXMLValueList.end(), aPropertyValueList.begin(), 366 [](const Any& rXMLValue) -> sal_Int16 { 367 // only value sequences of numeric types implemented so far. 368 double nVal( 0 ); 369 OSL_VERIFY( rXMLValue >>= nVal ); 370 return static_cast< sal_Int16 >( nVal ); 371 }); 372 373 rPropValues.Value <<= aPropertyValueList; 374 } 375 else if ( ePropTypeClass != eValueTypeClass ) 376 { 377 switch ( eValueTypeClass ) 378 { 379 case TypeClass_DOUBLE: 380 { 381 double nVal = 0; 382 rPropValues.Value >>= nVal; 383 switch( ePropTypeClass ) 384 { 385 case TypeClass_BYTE: 386 rPropValues.Value <<= static_cast< sal_Int8 >( nVal ); 387 break; 388 case TypeClass_SHORT: 389 rPropValues.Value <<= static_cast< sal_Int16 >( nVal ); 390 break; 391 case TypeClass_UNSIGNED_SHORT: 392 rPropValues.Value <<= static_cast< sal_uInt16 >( nVal ); 393 break; 394 case TypeClass_LONG: 395 case TypeClass_ENUM: 396 rPropValues.Value <<= static_cast< sal_Int32 >( nVal ); 397 break; 398 case TypeClass_UNSIGNED_LONG: 399 rPropValues.Value <<= static_cast< sal_uInt32 >( nVal ); 400 break; 401 case TypeClass_UNSIGNED_HYPER: 402 rPropValues.Value <<= static_cast< sal_uInt64 >( nVal ); 403 break; 404 case TypeClass_HYPER: 405 rPropValues.Value <<= static_cast< sal_Int64 >( nVal ); 406 break; 407 default: 408 OSL_FAIL( "OElementImport::implImportGenericProperties: unsupported value type!" ); 409 break; 410 } 411 } 412 break; 413 default: 414 OSL_FAIL( "OElementImport::implImportGenericProperties: non-double values not supported!" ); 415 break; 416 } 417 } 418 419 m_xElement->setPropertyValue( rPropValues.Name, rPropValues.Value ); 420 } 421 catch(const Exception&) 422 { 423 DBG_UNHANDLED_EXCEPTION("xmloff.forms"); 424 OSL_FAIL(OStringBuffer("OElementImport::EndElement: could not set the property \""). 425 append(OUStringToOString(rPropValues.Name, RTL_TEXTENCODING_ASCII_US)). 426 append("\"!").getStr()); 427 } 428 } 429 } 430 implGetDefaultName() const431 OUString OElementImport::implGetDefaultName() const 432 { 433 // no optimization here. If this method gets called, the XML stream did not contain a name for the 434 // element, which is a heavy error. So in this case we don't care for performance 435 static const char sUnnamedName[] = "unnamed"; 436 OSL_ENSURE(m_xParentContainer.is(), "OElementImport::implGetDefaultName: no parent container!"); 437 if (!m_xParentContainer.is()) 438 return sUnnamedName; 439 Sequence< OUString > aNames = m_xParentContainer->getElementNames(); 440 441 for (sal_Int32 i=0; i<32768; ++i) // the limit is nearly arbitrary... 442 { 443 // assemble the new name (suggestion) 444 OUString sReturn = sUnnamedName + OUString::number(i); 445 // check the existence (this is the bad performance part...) 446 if (comphelper::findValue(aNames, sReturn) == -1) 447 // not found the name 448 return sReturn; 449 } 450 OSL_FAIL("OElementImport::implGetDefaultName: did not find a free name!"); 451 return sUnnamedName; 452 } 453 impl_matchPropertyGroup(const PropertyGroups & i_propertyGroups) const454 PropertyGroups::const_iterator OElementImport::impl_matchPropertyGroup( const PropertyGroups& i_propertyGroups ) const 455 { 456 ENSURE_OR_RETURN( m_xInfo.is(), "OElementImport::impl_matchPropertyGroup: no property set info!", i_propertyGroups.end() ); 457 458 return std::find_if(i_propertyGroups.cbegin(), i_propertyGroups.cend(), [&](const PropertyDescriptionList& rGroup) { 459 return std::all_of(rGroup.cbegin(), rGroup.cend(), [&](const PropertyDescription* prop) { 460 return m_xInfo->hasPropertyByName( prop->propertyName ); 461 }); 462 }); 463 } 464 tryGenericAttribute(sal_uInt16 _nNamespaceKey,const OUString & _rLocalName,const OUString & _rValue)465 bool OElementImport::tryGenericAttribute( sal_uInt16 _nNamespaceKey, const OUString& _rLocalName, const OUString& _rValue ) 466 { 467 // the generic approach (which I hope all props will be migrated to, on the medium term): property handlers 468 const AttributeDescription attribute( metadata::getAttributeDescription( _nNamespaceKey, _rLocalName ) ); 469 if ( attribute.attributeToken != XML_TOKEN_INVALID ) 470 { 471 PropertyGroups propertyGroups; 472 metadata::getPropertyGroupList( attribute, propertyGroups ); 473 const PropertyGroups::const_iterator pos = impl_matchPropertyGroup( propertyGroups ); 474 if ( pos == propertyGroups.end() ) 475 return false; 476 477 do 478 { 479 const PropertyDescriptionList& rProperties( *pos ); 480 const PropertyDescription* first = *rProperties.begin(); 481 if ( !first ) 482 { 483 SAL_WARN( "xmloff.forms", "OElementImport::handleAttribute: invalid property description!" ); 484 break; 485 } 486 487 const PPropertyHandler handler = (*first->factory)( first->propertyId ); 488 if ( !handler.get() ) 489 { 490 SAL_WARN( "xmloff.forms", "OElementImport::handleAttribute: invalid property handler!" ); 491 break; 492 } 493 494 PropertyValues aValues; 495 for ( const auto& propDesc : rProperties ) 496 { 497 aValues[ propDesc->propertyId ] = Any(); 498 } 499 if ( handler->getPropertyValues( _rValue, aValues ) ) 500 { 501 for ( const auto& propDesc : rProperties ) 502 { 503 implPushBackPropertyValue( propDesc->propertyName, aValues[ propDesc->propertyId ] ); 504 } 505 } 506 } 507 while ( false ); 508 509 // handled 510 return true; 511 } 512 return false; 513 } 514 handleAttribute(sal_uInt16 _nNamespaceKey,const OUString & _rLocalName,const OUString & _rValue)515 bool OElementImport::handleAttribute(sal_uInt16 _nNamespaceKey, const OUString& _rLocalName, const OUString& _rValue) 516 { 517 if ( token::IsXMLToken( _rLocalName, token::XML_CONTROL_IMPLEMENTATION ) ) 518 // ignore this, it has already been handled in OElementImport::StartElement 519 return true; 520 521 if ( token::IsXMLToken( _rLocalName, token::XML_NAME ) ) 522 { 523 if ( m_sName.isEmpty() ) 524 // remember the name for later use in EndElement 525 m_sName = _rValue; 526 return true; 527 } 528 529 // maybe it's the style attribute? 530 if ( token::IsXMLToken( _rLocalName, token::XML_TEXT_STYLE_NAME ) ) 531 { 532 const SvXMLStyleContext* pStyleContext = m_rContext.getStyleElement( _rValue ); 533 OSL_ENSURE( pStyleContext, "OElementImport::handleAttribute: do not know the style!" ); 534 // remember the element for later usage. 535 m_pStyleElement = dynamic_cast<const XMLTextStyleContext*>( pStyleContext ); 536 return true; 537 } 538 539 if ( m_bImplicitGenericAttributeHandling ) 540 if ( tryGenericAttribute( _nNamespaceKey, _rLocalName, _rValue ) ) 541 return true; 542 543 // let the base class handle it 544 return OPropertyImport::handleAttribute(_nNamespaceKey, _rLocalName, _rValue); 545 } 546 createElement()547 Reference< XPropertySet > OElementImport::createElement() 548 { 549 Reference< XPropertySet > xReturn; 550 if (!m_sServiceName.isEmpty()) 551 { 552 Reference< XComponentContext > xContext = m_rFormImport.getGlobalContext().GetComponentContext(); 553 Reference< XInterface > xPure = xContext->getServiceManager()->createInstanceWithContext(m_sServiceName, xContext); 554 OSL_ENSURE(xPure.is(), 555 OStringBuffer("OElementImport::createElement: service factory gave me no object (service name: ").append(OUStringToOString(m_sServiceName, RTL_TEXTENCODING_ASCII_US)).append(")!").getStr()); 556 xReturn.set(xPure, UNO_QUERY); 557 } 558 else 559 OSL_FAIL("OElementImport::createElement: no service name to create an element!"); 560 561 return xReturn; 562 } 563 registerEvents(const Sequence<ScriptEventDescriptor> & _rEvents)564 void OElementImport::registerEvents(const Sequence< ScriptEventDescriptor >& _rEvents) 565 { 566 OSL_ENSURE(m_xElement.is(), "OElementImport::registerEvents: no element to register events for!"); 567 m_rEventManager.registerEvents(m_xElement, _rEvents); 568 } 569 simulateDefaultedAttribute(const sal_Char * _pAttributeName,const OUString & _rPropertyName,const sal_Char * _pAttributeDefault)570 void OElementImport::simulateDefaultedAttribute(const sal_Char* _pAttributeName, const OUString& _rPropertyName, const sal_Char* _pAttributeDefault) 571 { 572 OSL_ENSURE( m_xInfo.is(), "OPropertyImport::simulateDefaultedAttribute: the component should be more gossipy about it's properties!" ); 573 574 if ( !m_xInfo.is() || m_xInfo->hasPropertyByName( _rPropertyName ) ) 575 { 576 OUString sLocalAttrName = OUString::createFromAscii(_pAttributeName); 577 if ( !encounteredAttribute( sLocalAttrName ) ) 578 OSL_VERIFY( handleAttribute( XML_NAMESPACE_FORM, sLocalAttrName, OUString::createFromAscii( _pAttributeDefault ) ) ); 579 } 580 } 581 582 //= OControlImport OControlImport(OFormLayerXMLImport_Impl & _rImport,IEventAttacherManager & _rEventManager,sal_uInt16 _nPrefix,const OUString & _rName,const Reference<XNameContainer> & _rxParentContainer)583 OControlImport::OControlImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const OUString& _rName, 584 const Reference< XNameContainer >& _rxParentContainer) 585 :OElementImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer) 586 ,m_eElementType(OControlElement::UNKNOWN) 587 { 588 disableImplicitGenericAttributeHandling(); 589 } 590 OControlImport(OFormLayerXMLImport_Impl & _rImport,IEventAttacherManager & _rEventManager,sal_uInt16 _nPrefix,const OUString & _rName,const Reference<XNameContainer> & _rxParentContainer,OControlElement::ElementType _eType)591 OControlImport::OControlImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const OUString& _rName, 592 const Reference< XNameContainer >& _rxParentContainer, OControlElement::ElementType _eType) 593 :OElementImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer) 594 ,m_eElementType(_eType) 595 { 596 disableImplicitGenericAttributeHandling(); 597 } 598 determineDefaultServiceName() const599 OUString OControlImport::determineDefaultServiceName() const 600 { 601 const sal_Char* pServiceName = nullptr; 602 switch ( m_eElementType ) 603 { 604 case OControlElement::TEXT: 605 case OControlElement::TEXT_AREA: 606 case OControlElement::PASSWORD: pServiceName = "com.sun.star.form.component.TextField"; break; 607 case OControlElement::FILE: pServiceName = "com.sun.star.form.component.FileControl"; break; 608 case OControlElement::FORMATTED_TEXT: pServiceName = "com.sun.star.form.component.FormattedField"; break; 609 case OControlElement::FIXED_TEXT: pServiceName = "com.sun.star.form.component.FixedText"; break; 610 case OControlElement::COMBOBOX: pServiceName = "com.sun.star.form.component.ComboBox"; break; 611 case OControlElement::LISTBOX: pServiceName = "com.sun.star.form.component.ListBox"; break; 612 case OControlElement::BUTTON: pServiceName = "com.sun.star.form.component.CommandButton"; break; 613 case OControlElement::IMAGE: pServiceName = "com.sun.star.form.component.ImageButton"; break; 614 case OControlElement::CHECKBOX: pServiceName = "com.sun.star.form.component.CheckBox"; break; 615 case OControlElement::RADIO: pServiceName = "com.sun.star.form.component.RadioButton"; break; 616 case OControlElement::FRAME: pServiceName = "com.sun.star.form.component.GroupBox"; break; 617 case OControlElement::IMAGE_FRAME: pServiceName = "com.sun.star.form.component.DatabaseImageControl"; break; 618 case OControlElement::HIDDEN: pServiceName = "com.sun.star.form.component.HiddenControl"; break; 619 case OControlElement::GRID: pServiceName = "com.sun.star.form.component.GridControl"; break; 620 case OControlElement::VALUERANGE: pServiceName = "com.sun.star.form.component.ScrollBar"; break; 621 case OControlElement::TIME: pServiceName = "com.sun.star.form.component.TimeField"; break; 622 case OControlElement::DATE: pServiceName = "com.sun.star.form.component.DateField"; break; 623 default: break; 624 } 625 if ( pServiceName != nullptr ) 626 return OUString::createFromAscii( pServiceName ); 627 return OUString(); 628 } 629 addOuterAttributes(const Reference<XAttributeList> & _rxOuterAttribs)630 void OControlImport::addOuterAttributes(const Reference< XAttributeList >& _rxOuterAttribs) 631 { 632 OSL_ENSURE(!m_xOuterAttributes.is(), "OControlImport::addOuterAttributes: already have these attributes!"); 633 m_xOuterAttributes = _rxOuterAttribs; 634 } 635 handleAttribute(sal_uInt16 _nNamespaceKey,const OUString & _rLocalName,const OUString & _rValue)636 bool OControlImport::handleAttribute(sal_uInt16 _nNamespaceKey, const OUString& _rLocalName, const OUString& _rValue) 637 { 638 static const sal_Char* pLinkedCellAttributeName = OAttributeMetaData::getBindingAttributeName(BAFlags::LinkedCell); 639 640 if (IsXMLToken(_rLocalName, XML_ID)) 641 { // it's the control id 642 if (XML_NAMESPACE_XML == _nNamespaceKey) 643 { 644 m_sControlId = _rValue; 645 } 646 else if (XML_NAMESPACE_FORM == _nNamespaceKey) 647 { 648 if (m_sControlId.isEmpty()) 649 { 650 m_sControlId = _rValue; 651 } 652 } 653 return true; 654 } 655 656 if ( _rLocalName.equalsAscii( pLinkedCellAttributeName ) ) 657 { // it's the address of a spreadsheet cell 658 m_sBoundCellAddress = _rValue; 659 return true; 660 } 661 662 if ( _nNamespaceKey == XML_NAMESPACE_XFORMS && IsXMLToken( _rLocalName, XML_BIND ) ) 663 { 664 m_sBindingID = _rValue; 665 return true; 666 } 667 668 if ( _nNamespaceKey == XML_NAMESPACE_FORM && IsXMLToken( _rLocalName, XML_XFORMS_LIST_SOURCE ) ) 669 { 670 m_sListBindingID = _rValue; 671 return true; 672 } 673 674 if ( ( ( _nNamespaceKey == XML_NAMESPACE_FORM ) 675 && IsXMLToken( _rLocalName, XML_XFORMS_SUBMISSION ) 676 ) 677 || ( ( _nNamespaceKey == XML_NAMESPACE_XFORMS ) 678 && IsXMLToken( _rLocalName, XML_SUBMISSION ) 679 ) 680 ) 681 { 682 m_sSubmissionID = _rValue; 683 return true; 684 } 685 686 if ( OElementImport::tryGenericAttribute( _nNamespaceKey, _rLocalName, _rValue ) ) 687 return true; 688 689 static const sal_Char* pValueAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCAFlags::Value); 690 static const sal_Char* pCurrentValueAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCAFlags::CurrentValue); 691 static const sal_Char* pMinValueAttributeName = OAttributeMetaData::getSpecialAttributeName(SCAFlags::MinValue); 692 static const sal_Char* pMaxValueAttributeName = OAttributeMetaData::getSpecialAttributeName(SCAFlags::MaxValue); 693 static const sal_Char* pRepeatDelayAttributeName = OAttributeMetaData::getSpecialAttributeName( SCAFlags::RepeatDelay ); 694 695 sal_Int32 nHandle = -1; 696 if ( _rLocalName.equalsAscii( pValueAttributeName ) ) 697 nHandle = PROPID_VALUE; 698 else if ( _rLocalName.equalsAscii( pCurrentValueAttributeName ) ) 699 nHandle = PROPID_CURRENT_VALUE; 700 else if ( _rLocalName.equalsAscii( pMinValueAttributeName ) ) 701 nHandle = PROPID_MIN_VALUE; 702 else if ( _rLocalName.equalsAscii( pMaxValueAttributeName ) ) 703 nHandle = PROPID_MAX_VALUE; 704 if ( nHandle != -1 ) 705 { 706 // for the moment, simply remember the name and the value 707 PropertyValue aProp; 708 aProp.Name = _rLocalName; 709 aProp.Handle = nHandle; 710 aProp.Value <<= _rValue; 711 m_aValueProperties.push_back(aProp); 712 return true; 713 } 714 715 if ( _rLocalName.equalsAscii( pRepeatDelayAttributeName ) ) 716 { 717 util::Duration aDuration; 718 if (::sax::Converter::convertDuration(aDuration, _rValue)) 719 { 720 PropertyValue aProp; 721 aProp.Name = PROPERTY_REPEAT_DELAY; 722 sal_Int32 const nMS = 723 ((aDuration.Hours * 60 + aDuration.Minutes) * 60 724 + aDuration.Seconds) * 1000 + aDuration.NanoSeconds/1000000; 725 aProp.Value <<= nMS; 726 727 implPushBackPropertyValue(aProp); 728 } 729 return true; 730 } 731 732 return OElementImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue ); 733 } 734 StartElement(const Reference<XAttributeList> & _rxAttrList)735 void OControlImport::StartElement(const Reference< XAttributeList >& _rxAttrList) 736 { 737 css::uno::Reference< css::xml::sax::XAttributeList > xAttributes; 738 if( m_xOuterAttributes.is() ) 739 { 740 // merge the attribute lists 741 OAttribListMerger* pMerger = new OAttribListMerger; 742 // our own one 743 pMerger->addList(_rxAttrList); 744 // and the ones of our enclosing element 745 pMerger->addList(m_xOuterAttributes); 746 xAttributes = pMerger; 747 } 748 else 749 { 750 xAttributes = _rxAttrList; 751 } 752 753 // let the base class handle all the attributes 754 OElementImport::StartElement(xAttributes); 755 756 if ( m_aValueProperties.empty() || !m_xElement.is()) 757 return; 758 759 // get the property set info 760 if (!m_xInfo.is()) 761 { 762 OSL_FAIL("OControlImport::StartElement: no PropertySetInfo!"); 763 return; 764 } 765 766 const sal_Char* pValueProperty = nullptr; 767 const sal_Char* pCurrentValueProperty = nullptr; 768 const sal_Char* pMinValueProperty = nullptr; 769 const sal_Char* pMaxValueProperty = nullptr; 770 771 bool bRetrievedValues = false; 772 bool bRetrievedValueLimits = false; 773 774 // get the class id of our element 775 sal_Int16 nClassId = FormComponentType::CONTROL; 776 m_xElement->getPropertyValue(PROPERTY_CLASSID) >>= nClassId; 777 778 // translate the value properties we collected in handleAttributes 779 for ( auto& rValueProps : m_aValueProperties ) 780 { 781 bool bSuccess = false; 782 switch (rValueProps.Handle) 783 { 784 case PROPID_VALUE: 785 case PROPID_CURRENT_VALUE: 786 { 787 // get the property names 788 if (!bRetrievedValues) 789 { 790 getValuePropertyNames(m_eElementType, nClassId, pCurrentValueProperty, pValueProperty); 791 if ( !pCurrentValueProperty && !pValueProperty ) 792 { 793 SAL_WARN( "xmloff.forms", "OControlImport::StartElement: illegal value property names!" ); 794 break; 795 } 796 797 bRetrievedValues = true; 798 } 799 if ( PROPID_VALUE == rValueProps.Handle && !pValueProperty ) 800 { 801 SAL_WARN( "xmloff.forms", "OControlImport::StartElement: the control does not have a value property!"); 802 break; 803 } 804 805 if ( PROPID_CURRENT_VALUE == rValueProps.Handle && !pCurrentValueProperty ) 806 { 807 SAL_WARN( "xmloff.forms", "OControlImport::StartElement: the control does not have a current-value property!"); 808 break; 809 } 810 811 // transfer the name 812 if (PROPID_VALUE == rValueProps.Handle) 813 rValueProps.Name = OUString::createFromAscii(pValueProperty); 814 else 815 rValueProps.Name = OUString::createFromAscii(pCurrentValueProperty); 816 bSuccess = true; 817 } 818 break; 819 case PROPID_MIN_VALUE: 820 case PROPID_MAX_VALUE: 821 { 822 // get the property names 823 if (!bRetrievedValueLimits) 824 { 825 getValueLimitPropertyNames(nClassId, pMinValueProperty, pMaxValueProperty); 826 if ( !pMinValueProperty || !pMaxValueProperty ) 827 { 828 SAL_WARN( "xmloff.forms", "OControlImport::StartElement: illegal value limit property names!" ); 829 break; 830 } 831 832 bRetrievedValueLimits = true; 833 } 834 OSL_ENSURE((PROPID_MIN_VALUE != rValueProps.Handle) || pMinValueProperty, 835 "OControlImport::StartElement: the control does not have a value property!"); 836 OSL_ENSURE((PROPID_MAX_VALUE != rValueProps.Handle) || pMaxValueProperty, 837 "OControlImport::StartElement: the control does not have a current-value property!"); 838 839 // transfer the name 840 if (PROPID_MIN_VALUE == rValueProps.Handle) 841 rValueProps.Name = OUString::createFromAscii(pMinValueProperty); 842 else 843 rValueProps.Name = OUString::createFromAscii(pMaxValueProperty); 844 bSuccess = true; 845 } 846 break; 847 } 848 849 if ( !bSuccess ) 850 continue; 851 852 // translate the value 853 implTranslateValueProperty(m_xInfo, rValueProps); 854 // add the property to the base class' array 855 implPushBackPropertyValue(rValueProps); 856 } 857 858 } 859 implTranslateValueProperty(const Reference<XPropertySetInfo> & _rxPropInfo,PropertyValue & _rPropValue)860 void OControlImport::implTranslateValueProperty(const Reference< XPropertySetInfo >& _rxPropInfo, 861 PropertyValue& _rPropValue) 862 { 863 OSL_ENSURE(_rxPropInfo->hasPropertyByName(_rPropValue.Name), 864 "OControlImport::implTranslateValueProperty: invalid property name!"); 865 866 // retrieve the type of the property 867 Property aProp = _rxPropInfo->getPropertyByName(_rPropValue.Name); 868 // the untranslated string value as read in handleAttribute 869 OUString sValue; 870 bool bSuccess = _rPropValue.Value >>= sValue; 871 OSL_ENSURE(bSuccess, "OControlImport::implTranslateValueProperty: supposed to be called with non-translated string values!"); 872 873 if (TypeClass_ANY == aProp.Type.getTypeClass()) 874 { 875 // we have exactly 2 properties where this type class is allowed: 876 SAL_WARN_IF( 877 _rPropValue.Name == PROPERTY_EFFECTIVE_VALUE 878 || _rPropValue.Name == PROPERTY_EFFECTIVE_DEFAULT, "xmloff", 879 "OControlImport::implTranslateValueProperty: invalid property type/name combination, Any and " << _rPropValue.Name); 880 881 // Both properties are allowed to have a double or a string value, 882 // so first try to convert the string into a number 883 double nValue; 884 if (::sax::Converter::convertDouble(nValue, sValue)) 885 _rPropValue.Value <<= nValue; 886 else 887 _rPropValue.Value <<= sValue; 888 } 889 else 890 _rPropValue.Value = PropertyConversion::convertString(aProp.Type, sValue); 891 } 892 EndElement()893 void OControlImport::EndElement() 894 { 895 OSL_ENSURE(m_xElement.is(), "OControlImport::EndElement: invalid control!"); 896 if ( !m_xElement.is() ) 897 return; 898 899 // register our control with its id 900 if (!m_sControlId.isEmpty()) 901 m_rFormImport.registerControlId(m_xElement, m_sControlId); 902 // it's allowed to have no control id. In this case we're importing a column 903 904 // one more pre-work to do: 905 // when we set default values, then by definition the respective value is set 906 // to this default value, too. This means if the sequence contains for example 907 // a DefaultText value, then the Text will be affected by this, too. 908 // In case the Text is not part of the property sequence (or occurs _before_ 909 // the DefaultText, which can happen for other value/default-value property names), 910 // this means that the Text (the value property) is incorrectly imported. 911 912 bool bRestoreValuePropertyValue = false; 913 Any aValuePropertyValue; 914 915 sal_Int16 nClassId = FormComponentType::CONTROL; 916 try 917 { 918 // get the class id of our element 919 m_xElement->getPropertyValue(PROPERTY_CLASSID) >>= nClassId; 920 } 921 catch( const Exception& ) 922 { 923 DBG_UNHANDLED_EXCEPTION("xmloff.forms"); 924 OSL_FAIL( "OControlImport::EndElement: caught an exception while retrieving the class id!" ); 925 } 926 927 const sal_Char* pValueProperty = nullptr; 928 const sal_Char* pDefaultValueProperty = nullptr; 929 getRuntimeValuePropertyNames(m_eElementType, nClassId, pValueProperty, pDefaultValueProperty); 930 if ( pDefaultValueProperty && pValueProperty ) 931 { 932 bool bNonDefaultValuePropertyValue = false; 933 // is the "value property" part of the sequence? 934 935 // look up this property in our sequence 936 for ( const auto& rCheck : m_aValues ) 937 { 938 if ( rCheck.Name.equalsAscii( pDefaultValueProperty ) ) 939 bRestoreValuePropertyValue = true; 940 else if ( rCheck.Name.equalsAscii( pValueProperty ) ) 941 { 942 bNonDefaultValuePropertyValue = true; 943 // we need to restore the value property we found here, nothing else 944 aValuePropertyValue = rCheck.Value; 945 } 946 } 947 948 if ( bRestoreValuePropertyValue && !bNonDefaultValuePropertyValue ) 949 { 950 // found it -> need to remember (and restore) the "value property value", which is not set explicitly 951 try 952 { 953 aValuePropertyValue = m_xElement->getPropertyValue( OUString::createFromAscii( pValueProperty ) ); 954 } 955 catch( const Exception& ) 956 { 957 DBG_UNHANDLED_EXCEPTION("xmloff.forms"); 958 OSL_FAIL( "OControlImport::EndElement: caught an exception while retrieving the current value property!" ); 959 } 960 } 961 } 962 963 // let the base class set all the values 964 OElementImport::EndElement(); 965 966 // restore the "value property value", if necessary 967 if ( bRestoreValuePropertyValue && pValueProperty ) 968 { 969 try 970 { 971 m_xElement->setPropertyValue( OUString::createFromAscii( pValueProperty ), aValuePropertyValue ); 972 } 973 catch( const Exception& ) 974 { 975 DBG_UNHANDLED_EXCEPTION("xmloff.forms"); 976 OSL_FAIL( "OControlImport::EndElement: caught an exception while restoring the value property!" ); 977 } 978 } 979 980 // the external cell binding, if applicable 981 if ( m_xElement.is() && !m_sBoundCellAddress.isEmpty() ) 982 doRegisterCellValueBinding( m_sBoundCellAddress ); 983 984 // XForms binding, if applicable 985 if ( m_xElement.is() && !m_sBindingID.isEmpty() ) 986 doRegisterXFormsValueBinding( m_sBindingID ); 987 988 // XForms list binding, if applicable 989 if ( m_xElement.is() && !m_sListBindingID.isEmpty() ) 990 doRegisterXFormsListBinding( m_sListBindingID ); 991 992 // XForms submission, if applicable 993 if ( m_xElement.is() && !m_sSubmissionID.isEmpty() ) 994 doRegisterXFormsSubmission( m_sSubmissionID ); 995 } 996 doRegisterCellValueBinding(const OUString & _rBoundCellAddress)997 void OControlImport::doRegisterCellValueBinding( const OUString& _rBoundCellAddress ) 998 { 999 OSL_PRECOND( m_xElement.is(), "OControlImport::doRegisterCellValueBinding: invalid element!" ); 1000 OSL_PRECOND( !_rBoundCellAddress.isEmpty(), 1001 "OControlImport::doRegisterCellValueBinding: invalid address!" ); 1002 1003 m_rContext.registerCellValueBinding( m_xElement, _rBoundCellAddress ); 1004 } 1005 doRegisterXFormsValueBinding(const OUString & _rBindingID)1006 void OControlImport::doRegisterXFormsValueBinding( const OUString& _rBindingID ) 1007 { 1008 OSL_PRECOND( m_xElement.is(), "need element" ); 1009 OSL_PRECOND( !_rBindingID.isEmpty(), "binding ID is not valid" ); 1010 1011 m_rContext.registerXFormsValueBinding( m_xElement, _rBindingID ); 1012 } 1013 doRegisterXFormsListBinding(const OUString & _rBindingID)1014 void OControlImport::doRegisterXFormsListBinding( const OUString& _rBindingID ) 1015 { 1016 OSL_PRECOND( m_xElement.is(), "need element" ); 1017 OSL_PRECOND( !_rBindingID.isEmpty(), "binding ID is not valid" ); 1018 1019 m_rContext.registerXFormsListBinding( m_xElement, _rBindingID ); 1020 } 1021 doRegisterXFormsSubmission(const OUString & _rSubmissionID)1022 void OControlImport::doRegisterXFormsSubmission( const OUString& _rSubmissionID ) 1023 { 1024 OSL_PRECOND( m_xElement.is(), "need element" ); 1025 OSL_PRECOND( !_rSubmissionID.isEmpty(), "binding ID is not valid" ); 1026 1027 m_rContext.registerXFormsSubmission( m_xElement, _rSubmissionID ); 1028 } 1029 createElement()1030 Reference< XPropertySet > OControlImport::createElement() 1031 { 1032 const Reference<XPropertySet> xPropSet = OElementImport::createElement(); 1033 if ( xPropSet.is() ) 1034 { 1035 m_xInfo = xPropSet->getPropertySetInfo(); 1036 if ( m_xInfo.is() && m_xInfo->hasPropertyByName(PROPERTY_ALIGN) ) 1037 { 1038 Any aValue; 1039 xPropSet->setPropertyValue(PROPERTY_ALIGN,aValue); 1040 } 1041 } 1042 return xPropSet; 1043 } 1044 1045 //= OImagePositionImport OImagePositionImport(OFormLayerXMLImport_Impl & _rImport,IEventAttacherManager & _rEventManager,sal_uInt16 _nPrefix,const OUString & _rName,const Reference<XNameContainer> & _rxParentContainer,OControlElement::ElementType _eType)1046 OImagePositionImport::OImagePositionImport( OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, 1047 sal_uInt16 _nPrefix, const OUString& _rName, const Reference< XNameContainer >& _rxParentContainer, 1048 OControlElement::ElementType _eType ) 1049 :OControlImport( _rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType ) 1050 ,m_nImagePosition( -1 ) 1051 ,m_nImageAlign( 0 ) 1052 ,m_bHaveImagePosition( false ) 1053 { 1054 } 1055 handleAttribute(sal_uInt16 _nNamespaceKey,const OUString & _rLocalName,const OUString & _rValue)1056 bool OImagePositionImport::handleAttribute( sal_uInt16 _nNamespaceKey, const OUString& _rLocalName, 1057 const OUString& _rValue ) 1058 { 1059 static const sal_Char* s_pImageDataAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCAFlags::ImageData); 1060 1061 if (_rLocalName.equalsAscii(s_pImageDataAttributeName)) 1062 { 1063 m_xGraphic = m_rContext.getGlobalContext().loadGraphicByURL(_rValue); 1064 return true; 1065 } 1066 else if ( _rLocalName == GetXMLToken( XML_IMAGE_POSITION ) ) 1067 { 1068 OSL_VERIFY( PropertyConversion::convertString( 1069 cppu::UnoType<decltype(m_nImagePosition)>::get(), 1070 _rValue, aImagePositionMap 1071 ) >>= m_nImagePosition ); 1072 m_bHaveImagePosition = true; 1073 return true; 1074 } 1075 else if ( _rLocalName == GetXMLToken( XML_IMAGE_ALIGN ) ) 1076 { 1077 OSL_VERIFY( PropertyConversion::convertString( 1078 cppu::UnoType<decltype(m_nImageAlign)>::get(), 1079 _rValue, aImageAlignMap 1080 ) >>= m_nImageAlign ); 1081 return true; 1082 } 1083 1084 return OControlImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue ); 1085 } 1086 StartElement(const Reference<XAttributeList> & _rxAttrList)1087 void OImagePositionImport::StartElement(const Reference< XAttributeList >& _rxAttrList) 1088 { 1089 OControlImport::StartElement( _rxAttrList ); 1090 1091 if (m_xGraphic.is()) 1092 { 1093 PropertyValue aGraphicProperty; 1094 aGraphicProperty.Name = PROPERTY_GRAPHIC; 1095 aGraphicProperty.Value <<= m_xGraphic; 1096 implPushBackPropertyValue(aGraphicProperty); 1097 } 1098 if ( m_bHaveImagePosition ) 1099 { 1100 sal_Int16 nUnoImagePosition = ImagePosition::Centered; 1101 if ( m_nImagePosition >= 0 ) 1102 { 1103 OSL_ENSURE( ( m_nImagePosition <= 3 ) && ( m_nImageAlign >= 0 ) && ( m_nImageAlign < 3 ), 1104 "OImagePositionImport::StartElement: unknown image align and/or position!" ); 1105 nUnoImagePosition = m_nImagePosition * 3 + m_nImageAlign; 1106 } 1107 1108 PropertyValue aImagePosition; 1109 aImagePosition.Name = PROPERTY_IMAGE_POSITION; 1110 aImagePosition.Value <<= nUnoImagePosition; 1111 implPushBackPropertyValue( aImagePosition ); 1112 } 1113 } 1114 1115 //= OReferredControlImport OReferredControlImport(OFormLayerXMLImport_Impl & _rImport,IEventAttacherManager & _rEventManager,sal_uInt16 _nPrefix,const OUString & _rName,const Reference<XNameContainer> & _rxParentContainer)1116 OReferredControlImport::OReferredControlImport( 1117 OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const OUString& _rName, 1118 const Reference< XNameContainer >& _rxParentContainer ) 1119 :OControlImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer) 1120 { 1121 } 1122 StartElement(const Reference<XAttributeList> & _rxAttrList)1123 void OReferredControlImport::StartElement(const Reference< XAttributeList >& _rxAttrList) 1124 { 1125 OControlImport::StartElement(_rxAttrList); 1126 1127 // the base class should have created the control, so we can register it 1128 if ( !m_sReferringControls.isEmpty() ) 1129 m_rFormImport.registerControlReferences(m_xElement, m_sReferringControls); 1130 } 1131 handleAttribute(sal_uInt16 _nNamespaceKey,const OUString & _rLocalName,const OUString & _rValue)1132 bool OReferredControlImport::handleAttribute(sal_uInt16 _nNamespaceKey, const OUString& _rLocalName, 1133 const OUString& _rValue) 1134 { 1135 static const char * s_sReferenceAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCAFlags::For); 1136 if (_rLocalName.equalsAscii(s_sReferenceAttributeName)) 1137 { 1138 m_sReferringControls = _rValue; 1139 return true; 1140 } 1141 return OControlImport::handleAttribute(_nNamespaceKey, _rLocalName, _rValue); 1142 } 1143 1144 //= OPasswordImport OPasswordImport(OFormLayerXMLImport_Impl & _rImport,IEventAttacherManager & _rEventManager,sal_uInt16 _nPrefix,const OUString & _rName,const Reference<XNameContainer> & _rxParentContainer,OControlElement::ElementType _eType)1145 OPasswordImport::OPasswordImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const OUString& _rName, 1146 const Reference< XNameContainer >& _rxParentContainer, OControlElement::ElementType _eType) 1147 :OControlImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType) 1148 { 1149 } 1150 handleAttribute(sal_uInt16 _nNamespaceKey,const OUString & _rLocalName,const OUString & _rValue)1151 bool OPasswordImport::handleAttribute(sal_uInt16 _nNamespaceKey, const OUString& _rLocalName, const OUString& _rValue) 1152 { 1153 static const char * s_sEchoCharAttributeName = OAttributeMetaData::getSpecialAttributeName(SCAFlags::EchoChar); 1154 if (_rLocalName.equalsAscii(s_sEchoCharAttributeName)) 1155 { 1156 // need a special handling for the EchoChar property 1157 PropertyValue aEchoChar; 1158 aEchoChar.Name = PROPERTY_ECHOCHAR; 1159 OSL_ENSURE(_rValue.getLength() == 1, "OPasswordImport::handleAttribute: invalid echo char attribute!"); 1160 // we ourself should not have written values other than of length 1 1161 if (_rValue.getLength() >= 1) 1162 aEchoChar.Value <<= static_cast<sal_Int16>(_rValue[0]); 1163 else 1164 aEchoChar.Value <<= sal_Int16(0); 1165 implPushBackPropertyValue(aEchoChar); 1166 return true; 1167 } 1168 return OControlImport::handleAttribute(_nNamespaceKey, _rLocalName, _rValue); 1169 } 1170 1171 //= ORadioImport ORadioImport(OFormLayerXMLImport_Impl & _rImport,IEventAttacherManager & _rEventManager,sal_uInt16 _nPrefix,const OUString & _rName,const Reference<XNameContainer> & _rxParentContainer,OControlElement::ElementType _eType)1172 ORadioImport::ORadioImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const OUString& _rName, 1173 const Reference< XNameContainer >& _rxParentContainer, OControlElement::ElementType _eType) 1174 :OImagePositionImport( _rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType ) 1175 { 1176 } 1177 handleAttribute(sal_uInt16 _nNamespaceKey,const OUString & _rLocalName,const OUString & _rValue)1178 bool ORadioImport::handleAttribute(sal_uInt16 _nNamespaceKey, const OUString& _rLocalName, const OUString& _rValue) 1179 { 1180 // need special handling for the State & CurrentState properties: 1181 // they're stored as booleans, but expected to be int16 properties 1182 static const sal_Char* pCurrentSelectedAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCAFlags::CurrentSelected); 1183 static const sal_Char* pSelectedAttributeName = OAttributeMetaData::getCommonControlAttributeName(CCAFlags::Selected); 1184 if ( _rLocalName.equalsAscii( pCurrentSelectedAttributeName ) 1185 || _rLocalName.equalsAscii( pSelectedAttributeName ) 1186 ) 1187 { 1188 const OAttribute2Property::AttributeAssignment* pProperty = m_rContext.getAttributeMap().getAttributeTranslation(_rLocalName); 1189 OSL_ENSURE(pProperty, "ORadioImport::handleAttribute: invalid property map!"); 1190 if (pProperty) 1191 { 1192 const Any aBooleanValue( PropertyConversion::convertString(pProperty->aPropertyType, _rValue, pProperty->pEnumMap) ); 1193 1194 // create and store a new PropertyValue 1195 PropertyValue aNewValue; 1196 aNewValue.Name = pProperty->sPropertyName; 1197 aNewValue.Value <<= static_cast<sal_Int16>(::cppu::any2bool(aBooleanValue)); 1198 1199 implPushBackPropertyValue(aNewValue); 1200 } 1201 return true; 1202 } 1203 return OImagePositionImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue ); 1204 } 1205 1206 //= OURLReferenceImport OURLReferenceImport(OFormLayerXMLImport_Impl & _rImport,IEventAttacherManager & _rEventManager,sal_uInt16 _nPrefix,const OUString & _rName,const Reference<XNameContainer> & _rxParentContainer,OControlElement::ElementType _eType)1207 OURLReferenceImport::OURLReferenceImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const OUString& _rName, 1208 const Reference< XNameContainer >& _rxParentContainer, 1209 OControlElement::ElementType _eType) 1210 :OImagePositionImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType) 1211 { 1212 } 1213 handleAttribute(sal_uInt16 _nNamespaceKey,const OUString & _rLocalName,const OUString & _rValue)1214 bool OURLReferenceImport::handleAttribute(sal_uInt16 _nNamespaceKey, const OUString& _rLocalName, const OUString& _rValue) 1215 { 1216 static const sal_Char* s_pTargetLocationAttributeName = OAttributeMetaData::getCommonControlAttributeName( CCAFlags::TargetLocation ); 1217 static const sal_Char* s_pImageDataAttributeName = OAttributeMetaData::getCommonControlAttributeName( CCAFlags::ImageData ); 1218 1219 // need to make the URL absolute if 1220 // * it's the image-data attribute 1221 // * it's the target-location attribute, and we're dealing with an object which has the respective property 1222 bool bMakeAbsolute = 1223 _rLocalName.equalsAscii( s_pImageDataAttributeName ) 1224 || ( _rLocalName.equalsAscii( s_pTargetLocationAttributeName ) 1225 && ( ( OControlElement::BUTTON == m_eElementType ) 1226 || ( OControlElement::IMAGE == m_eElementType ) 1227 ) 1228 ); 1229 1230 if (bMakeAbsolute && !_rValue.isEmpty()) 1231 { 1232 OUString sAdjustedValue = _rValue; 1233 if (!_rLocalName.equalsAscii(s_pImageDataAttributeName)) 1234 sAdjustedValue = m_rContext.getGlobalContext().GetAbsoluteReference( _rValue ); 1235 return OImagePositionImport::handleAttribute( _nNamespaceKey, _rLocalName, sAdjustedValue ); 1236 } 1237 1238 return OImagePositionImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue ); 1239 } 1240 1241 //= OButtonImport OButtonImport(OFormLayerXMLImport_Impl & _rImport,IEventAttacherManager & _rEventManager,sal_uInt16 _nPrefix,const OUString & _rName,const Reference<XNameContainer> & _rxParentContainer,OControlElement::ElementType _eType)1242 OButtonImport::OButtonImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const OUString& _rName, 1243 const Reference< XNameContainer >& _rxParentContainer, 1244 OControlElement::ElementType _eType) 1245 :OURLReferenceImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType) 1246 { 1247 enableTrackAttributes(); 1248 } 1249 StartElement(const Reference<XAttributeList> & _rxAttrList)1250 void OButtonImport::StartElement(const Reference< XAttributeList >& _rxAttrList) 1251 { 1252 OURLReferenceImport::StartElement(_rxAttrList); 1253 1254 // handle the target-frame attribute 1255 simulateDefaultedAttribute(OAttributeMetaData::getCommonControlAttributeName(CCAFlags::TargetFrame), PROPERTY_TARGETFRAME, "_blank"); 1256 } 1257 1258 //= OValueRangeImport OValueRangeImport(OFormLayerXMLImport_Impl & _rImport,IEventAttacherManager & _rEventManager,sal_uInt16 _nPrefix,const OUString & _rName,const Reference<XNameContainer> & _rxParentContainer,OControlElement::ElementType _eType)1259 OValueRangeImport::OValueRangeImport( OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const OUString& _rName, 1260 const Reference< XNameContainer >& _rxParentContainer, OControlElement::ElementType _eType ) 1261 :OControlImport( _rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType ) 1262 ,m_nStepSizeValue( 1 ) 1263 { 1264 1265 } 1266 handleAttribute(sal_uInt16 _nNamespaceKey,const OUString & _rLocalName,const OUString & _rValue)1267 bool OValueRangeImport::handleAttribute( sal_uInt16 _nNamespaceKey, const OUString& _rLocalName, const OUString& _rValue ) 1268 { 1269 if ( _rLocalName.equalsAscii( OAttributeMetaData::getSpecialAttributeName( SCAFlags::StepSize ) ) ) 1270 { 1271 ::sax::Converter::convertNumber( m_nStepSizeValue, _rValue ); 1272 return true; 1273 } 1274 return OControlImport::handleAttribute( _nNamespaceKey, _rLocalName, _rValue ); 1275 } 1276 StartElement(const Reference<XAttributeList> & _rxAttrList)1277 void OValueRangeImport::StartElement( const Reference< XAttributeList >& _rxAttrList ) 1278 { 1279 OControlImport::StartElement( _rxAttrList ); 1280 1281 if ( m_xInfo.is() ) 1282 { 1283 if ( m_xInfo->hasPropertyByName( PROPERTY_SPIN_INCREMENT ) ) 1284 m_xElement->setPropertyValue( PROPERTY_SPIN_INCREMENT, makeAny( m_nStepSizeValue ) ); 1285 else if ( m_xInfo->hasPropertyByName( PROPERTY_LINE_INCREMENT ) ) 1286 m_xElement->setPropertyValue( PROPERTY_LINE_INCREMENT, makeAny( m_nStepSizeValue ) ); 1287 } 1288 } 1289 1290 //= OTextLikeImport OTextLikeImport(OFormLayerXMLImport_Impl & _rImport,IEventAttacherManager & _rEventManager,sal_uInt16 _nPrefix,const OUString & _rName,const Reference<XNameContainer> & _rxParentContainer,OControlElement::ElementType _eType)1291 OTextLikeImport::OTextLikeImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const OUString& _rName, 1292 const Reference< XNameContainer >& _rxParentContainer, 1293 OControlElement::ElementType _eType) 1294 :OControlImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType) 1295 ,m_bEncounteredTextPara( false ) 1296 { 1297 enableTrackAttributes(); 1298 } 1299 CreateChildContext(sal_uInt16 _nPrefix,const OUString & _rLocalName,const Reference<XAttributeList> & _rxAttrList)1300 SvXMLImportContextRef OTextLikeImport::CreateChildContext( sal_uInt16 _nPrefix, const OUString& _rLocalName, 1301 const Reference< XAttributeList >& _rxAttrList ) 1302 { 1303 if ( ( XML_NAMESPACE_TEXT == _nPrefix ) && _rLocalName.equalsIgnoreAsciiCase("p") ) 1304 { 1305 OSL_ENSURE( m_eElementType == OControlElement::TEXT_AREA, 1306 "OTextLikeImport::CreateChildContext: text paragraphs in a non-text-area?" ); 1307 1308 if ( m_eElementType == OControlElement::TEXT_AREA ) 1309 { 1310 Reference< XText > xTextElement( m_xElement, UNO_QUERY ); 1311 if ( xTextElement.is() ) 1312 { 1313 rtl::Reference < XMLTextImportHelper > xTextImportHelper( m_rContext.getGlobalContext().GetTextImport() ); 1314 1315 if ( !m_xCursor.is() ) 1316 { 1317 m_xOldCursor = xTextImportHelper->GetCursor(); 1318 m_xCursor = xTextElement->createTextCursor(); 1319 1320 if ( m_xCursor.is() ) 1321 xTextImportHelper->SetCursor( m_xCursor ); 1322 } 1323 if ( m_xCursor.is() ) 1324 { 1325 m_bEncounteredTextPara = true; 1326 return xTextImportHelper->CreateTextChildContext( m_rContext.getGlobalContext(), _nPrefix, _rLocalName, _rxAttrList ); 1327 } 1328 } 1329 else 1330 { 1331 // in theory, we could accumulate all the text portions (without formatting), 1332 // and set it as Text property at the model ... 1333 } 1334 } 1335 } 1336 1337 return OControlImport::CreateChildContext( _nPrefix, _rLocalName, _rxAttrList ); 1338 } 1339 StartElement(const Reference<XAttributeList> & _rxAttrList)1340 void OTextLikeImport::StartElement(const Reference< XAttributeList >& _rxAttrList) 1341 { 1342 OControlImport::StartElement(_rxAttrList); 1343 1344 // handle the convert-empty-to-null attribute, whose default is different from the property default 1345 // unfortunately, different classes are imported by this class ('cause they're represented by the 1346 // same XML element), though not all of them know this property. 1347 // So we have to do a check ... 1348 if (m_xElement.is() && m_xInfo.is() && m_xInfo->hasPropertyByName(PROPERTY_EMPTY_IS_NULL) ) 1349 simulateDefaultedAttribute(OAttributeMetaData::getDatabaseAttributeName(DAFlags::ConvertEmpty), PROPERTY_EMPTY_IS_NULL, "false"); 1350 } 1351 1352 struct EqualHandle 1353 { 1354 const sal_Int32 m_nHandle; EqualHandlexmloff::EqualHandle1355 explicit EqualHandle( sal_Int32 _nHandle ) : m_nHandle( _nHandle ) { } 1356 operator ()xmloff::EqualHandle1357 bool operator()( const PropertyValue& _rProp ) 1358 { 1359 return _rProp.Handle == m_nHandle; 1360 } 1361 }; 1362 removeRedundantCurrentValue()1363 void OTextLikeImport::removeRedundantCurrentValue() 1364 { 1365 if ( m_bEncounteredTextPara ) 1366 { 1367 // In case the text is written in the text:p elements, we need to ignore what we read as 1368 // current-value attribute, since it's redundant. 1369 // fortunately, OElementImport tagged the value property with the PROPID_CURRENT_VALUE 1370 // handle, so we do not need to determine the name of our value property here 1371 // (normally, it should be "Text", since no other controls than the edit field should 1372 // have the text:p elements) 1373 PropertyValueArray::iterator aValuePropertyPos = ::std::find_if( 1374 m_aValues.begin(), 1375 m_aValues.end(), 1376 EqualHandle( PROPID_CURRENT_VALUE ) 1377 ); 1378 if ( aValuePropertyPos != m_aValues.end() ) 1379 { 1380 OSL_ENSURE( aValuePropertyPos->Name == PROPERTY_TEXT, "OTextLikeImport::EndElement: text:p was present, but our value property is *not* 'Text'!" ); 1381 if ( aValuePropertyPos->Name == PROPERTY_TEXT ) 1382 { 1383 ::std::copy( 1384 aValuePropertyPos + 1, 1385 m_aValues.end(), 1386 aValuePropertyPos 1387 ); 1388 m_aValues.resize( m_aValues.size() - 1 ); 1389 } 1390 } 1391 1392 // additionally, we need to set the "RichText" property of our element to sal_True 1393 // (the presence of the text:p is used as indicator for the value of the RichText property) 1394 bool bHasRichTextProperty = false; 1395 if ( m_xInfo.is() ) 1396 bHasRichTextProperty = m_xInfo->hasPropertyByName( PROPERTY_RICH_TEXT ); 1397 OSL_ENSURE( bHasRichTextProperty, "OTextLikeImport::EndElement: text:p, but no rich text control?" ); 1398 if ( bHasRichTextProperty ) 1399 m_xElement->setPropertyValue( PROPERTY_RICH_TEXT, makeAny( true ) ); 1400 } 1401 // Note that we do *not* set the RichText property (in case our element has one) to sal_False here 1402 // since this is the default of this property, anyway. 1403 } 1404 1405 struct EqualName 1406 { 1407 const OUString & m_sName; EqualNamexmloff::EqualName1408 explicit EqualName( const OUString& _rName ) : m_sName( _rName ) { } 1409 operator ()xmloff::EqualName1410 bool operator()( const PropertyValue& _rProp ) 1411 { 1412 return _rProp.Name == m_sName; 1413 } 1414 }; 1415 adjustDefaultControlProperty()1416 void OTextLikeImport::adjustDefaultControlProperty() 1417 { 1418 // In OpenOffice.org 2.0, we changed the implementation of the css.form.component.TextField (the model of a text field control), 1419 // so that it now uses another default control. So if we encounter a text field where the *old* default 1420 // control property is writing, we are not allowed to use it 1421 PropertyValueArray::iterator aDefaultControlPropertyPos = ::std::find_if( 1422 m_aValues.begin(), 1423 m_aValues.end(), 1424 EqualName( "DefaultControl" ) 1425 ); 1426 if ( aDefaultControlPropertyPos != m_aValues.end() ) 1427 { 1428 OUString sDefaultControl; 1429 OSL_VERIFY( aDefaultControlPropertyPos->Value >>= sDefaultControl ); 1430 if ( sDefaultControl == "stardiv.one.form.control.Edit" ) 1431 { 1432 // complete remove this property value from the array. Today's "default value" of the "DefaultControl" 1433 // property is sufficient 1434 ::std::copy( 1435 aDefaultControlPropertyPos + 1, 1436 m_aValues.end(), 1437 aDefaultControlPropertyPos 1438 ); 1439 m_aValues.resize( m_aValues.size() - 1 ); 1440 } 1441 } 1442 } 1443 EndElement()1444 void OTextLikeImport::EndElement() 1445 { 1446 removeRedundantCurrentValue(); 1447 adjustDefaultControlProperty(); 1448 1449 // let the base class do the stuff 1450 OControlImport::EndElement(); 1451 1452 // some cleanups 1453 rtl::Reference < XMLTextImportHelper > xTextImportHelper( m_rContext.getGlobalContext().GetTextImport() ); 1454 if ( m_xCursor.is() ) 1455 { 1456 // delete the newline which has been imported erroneously 1457 // TODO (fs): stole this code somewhere - why don't we fix the text import?? 1458 m_xCursor->gotoEnd( false ); 1459 m_xCursor->goLeft( 1, true ); 1460 m_xCursor->setString( OUString() ); 1461 1462 // reset cursor 1463 xTextImportHelper->ResetCursor(); 1464 } 1465 1466 if ( m_xOldCursor.is() ) 1467 xTextImportHelper->SetCursor( m_xOldCursor ); 1468 1469 } 1470 1471 //= OListAndComboImport OListAndComboImport(OFormLayerXMLImport_Impl & _rImport,IEventAttacherManager & _rEventManager,sal_uInt16 _nPrefix,const OUString & _rName,const Reference<XNameContainer> & _rxParentContainer,OControlElement::ElementType _eType)1472 OListAndComboImport::OListAndComboImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const OUString& _rName, 1473 const Reference< XNameContainer >& _rxParentContainer, 1474 OControlElement::ElementType _eType) 1475 :OControlImport(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, _eType) 1476 ,m_nEmptyListItems( 0 ) 1477 ,m_nEmptyValueItems( 0 ) 1478 ,m_bEncounteredLSAttrib( false ) 1479 ,m_bLinkWithIndexes( false ) 1480 { 1481 if (OControlElement::COMBOBOX == m_eElementType) 1482 enableTrackAttributes(); 1483 } 1484 CreateChildContext(sal_uInt16 _nPrefix,const OUString & _rLocalName,const Reference<XAttributeList> & _rxAttrList)1485 SvXMLImportContextRef OListAndComboImport::CreateChildContext(sal_uInt16 _nPrefix, const OUString& _rLocalName, 1486 const Reference< XAttributeList >& _rxAttrList) 1487 { 1488 // is it the "option" sub tag of a listbox ? 1489 if (_rLocalName == "option") 1490 return new OListOptionImport(GetImport(), _nPrefix, _rLocalName, this); 1491 1492 // is it the "item" sub tag of a combobox ? 1493 if (_rLocalName == "item") 1494 return new OComboItemImport(GetImport(), _nPrefix, _rLocalName, this); 1495 1496 // everything else 1497 return OControlImport::CreateChildContext(_nPrefix, _rLocalName, _rxAttrList); 1498 } 1499 StartElement(const Reference<XAttributeList> & _rxAttrList)1500 void OListAndComboImport::StartElement(const Reference< XAttributeList >& _rxAttrList) 1501 { 1502 m_bLinkWithIndexes = false; 1503 1504 OControlImport::StartElement(_rxAttrList); 1505 1506 if (OControlElement::COMBOBOX == m_eElementType) 1507 { 1508 // for the auto-completion 1509 // the attribute default does not equal the property default, so in case we did not read this attribute, 1510 // we have to simulate it 1511 simulateDefaultedAttribute( OAttributeMetaData::getSpecialAttributeName( SCAFlags::AutoCompletion ), PROPERTY_AUTOCOMPLETE, "false"); 1512 1513 // same for the convert-empty-to-null attribute, which's default is different from the property default 1514 simulateDefaultedAttribute( OAttributeMetaData::getDatabaseAttributeName( DAFlags::ConvertEmpty ), PROPERTY_EMPTY_IS_NULL, "false"); 1515 } 1516 } 1517 EndElement()1518 void OListAndComboImport::EndElement() 1519 { 1520 // append the list source property the properties sequence of our importer 1521 // the string item list 1522 PropertyValue aItemList; 1523 aItemList.Name = PROPERTY_STRING_ITEM_LIST; 1524 aItemList.Value <<= comphelper::containerToSequence(m_aListSource); 1525 implPushBackPropertyValue(aItemList); 1526 1527 if (OControlElement::LISTBOX == m_eElementType) 1528 { 1529 OSL_ENSURE((m_aListSource.size() + m_nEmptyListItems) == (m_aValueList.size() + m_nEmptyValueItems), 1530 "OListAndComboImport::EndElement: inconsistence between labels and values!"); 1531 1532 if ( !m_bEncounteredLSAttrib ) 1533 { 1534 // the value sequence 1535 PropertyValue aValueList; 1536 aValueList.Name = PROPERTY_LISTSOURCE; 1537 aValueList.Value <<= comphelper::containerToSequence(m_aValueList); 1538 implPushBackPropertyValue(aValueList); 1539 } 1540 1541 // the select sequence 1542 PropertyValue aSelected; 1543 aSelected.Name = PROPERTY_SELECT_SEQ; 1544 aSelected.Value <<= comphelper::containerToSequence(m_aSelectedSeq); 1545 implPushBackPropertyValue(aSelected); 1546 1547 // the default select sequence 1548 PropertyValue aDefaultSelected; 1549 aDefaultSelected.Name = PROPERTY_DEFAULT_SELECT_SEQ; 1550 aDefaultSelected.Value <<= comphelper::containerToSequence(m_aDefaultSelectedSeq); 1551 implPushBackPropertyValue(aDefaultSelected); 1552 } 1553 1554 OControlImport::EndElement(); 1555 1556 // the external list source, if applicable 1557 if ( m_xElement.is() && !m_sCellListSource.isEmpty() ) 1558 m_rContext.registerCellRangeListSource( m_xElement, m_sCellListSource ); 1559 } 1560 doRegisterCellValueBinding(const OUString & _rBoundCellAddress)1561 void OListAndComboImport::doRegisterCellValueBinding( const OUString& _rBoundCellAddress ) 1562 { 1563 OUString sBoundCellAddress( _rBoundCellAddress ); 1564 if ( m_bLinkWithIndexes ) 1565 { 1566 // This is a HACK. We register a string which is no valid address, but allows 1567 // (somewhere else) to determine that a non-standard binding should be created. 1568 // This hack is acceptable for OOo 1.1.1, since the file format for value 1569 // bindings of form controls is to be changed afterwards, anyway. 1570 sBoundCellAddress += ":index"; 1571 } 1572 1573 OControlImport::doRegisterCellValueBinding( sBoundCellAddress ); 1574 } 1575 handleAttribute(sal_uInt16 _nNamespaceKey,const OUString & _rLocalName,const OUString & _rValue)1576 bool OListAndComboImport::handleAttribute(sal_uInt16 _nNamespaceKey, const OUString& _rLocalName, const OUString& _rValue) 1577 { 1578 static const sal_Char* pListSourceAttributeName = OAttributeMetaData::getDatabaseAttributeName(DAFlags::ListSource); 1579 if ( _rLocalName.equalsAscii(pListSourceAttributeName) ) 1580 { 1581 PropertyValue aListSource; 1582 aListSource.Name = PROPERTY_LISTSOURCE; 1583 1584 // it's the ListSource attribute 1585 m_bEncounteredLSAttrib = true; 1586 if ( OControlElement::COMBOBOX == m_eElementType ) 1587 { 1588 aListSource.Value <<= _rValue; 1589 } 1590 else 1591 { 1592 // a listbox which has a list-source attribute must have a list-source-type of something 1593 // not equal to ValueList. 1594 // In this case, the list-source value is simply the one and only element of the ListSource property. 1595 Sequence<OUString> aListSourcePropValue { _rValue }; 1596 aListSource.Value <<= aListSourcePropValue; 1597 } 1598 1599 implPushBackPropertyValue( aListSource ); 1600 return true; 1601 } 1602 1603 if ( _rLocalName.equalsAscii( OAttributeMetaData::getBindingAttributeName( BAFlags::ListCellRange ) ) ) 1604 { 1605 m_sCellListSource = _rValue; 1606 return true; 1607 } 1608 1609 if ( _rLocalName.equalsAscii( OAttributeMetaData::getBindingAttributeName( BAFlags::ListLinkingType ) ) ) 1610 { 1611 sal_Int16 nLinkageType = 0; 1612 PropertyConversion::convertString( 1613 ::cppu::UnoType<sal_Int16>::get(), 1614 _rValue, 1615 aListLinkageMap 1616 ) >>= nLinkageType; 1617 1618 m_bLinkWithIndexes = ( nLinkageType != 0 ); 1619 return true; 1620 } 1621 1622 return OControlImport::handleAttribute(_nNamespaceKey, _rLocalName, _rValue); 1623 } 1624 implPushBackLabel(const OUString & _rLabel)1625 void OListAndComboImport::implPushBackLabel(const OUString& _rLabel) 1626 { 1627 OSL_ENSURE(!m_nEmptyListItems, "OListAndComboImport::implPushBackValue: label list is already done!"); 1628 if (!m_nEmptyListItems) 1629 m_aListSource.push_back(_rLabel); 1630 } 1631 implPushBackValue(const OUString & _rValue)1632 void OListAndComboImport::implPushBackValue(const OUString& _rValue) 1633 { 1634 OSL_ENSURE(!m_nEmptyValueItems, "OListAndComboImport::implPushBackValue: value list is already done!"); 1635 if (!m_nEmptyValueItems) 1636 { 1637 OSL_ENSURE( !m_bEncounteredLSAttrib, "OListAndComboImport::implPushBackValue: invalid structure! Did you save this document with a version prior SRC641 m?" ); 1638 // We already had the list-source attribute, which means that the ListSourceType is 1639 // not ValueList, which means that the ListSource should contain only one string in 1640 // the first element of the sequence 1641 // All other values in the file are invalid 1642 1643 m_aValueList.push_back( _rValue ); 1644 } 1645 } 1646 implEmptyLabelFound()1647 void OListAndComboImport::implEmptyLabelFound() 1648 { 1649 ++m_nEmptyListItems; 1650 } 1651 implEmptyValueFound()1652 void OListAndComboImport::implEmptyValueFound() 1653 { 1654 ++m_nEmptyValueItems; 1655 } 1656 implSelectCurrentItem()1657 void OListAndComboImport::implSelectCurrentItem() 1658 { 1659 OSL_ENSURE((m_aListSource.size() + m_nEmptyListItems) == (m_aValueList.size() + m_nEmptyValueItems), 1660 "OListAndComboImport::implSelectCurrentItem: inconsistence between labels and values!"); 1661 1662 sal_Int16 nItemNumber = static_cast<sal_Int16>(m_aListSource.size() - 1 + m_nEmptyListItems); 1663 m_aSelectedSeq.push_back(nItemNumber); 1664 } 1665 implDefaultSelectCurrentItem()1666 void OListAndComboImport::implDefaultSelectCurrentItem() 1667 { 1668 OSL_ENSURE((m_aListSource.size() + m_nEmptyListItems) == (m_aValueList.size() + m_nEmptyValueItems), 1669 "OListAndComboImport::implDefaultSelectCurrentItem: inconsistence between labels and values!"); 1670 1671 sal_Int16 nItemNumber = static_cast<sal_Int16>(m_aListSource.size() - 1 + m_nEmptyListItems); 1672 m_aDefaultSelectedSeq.push_back(nItemNumber); 1673 } 1674 1675 //= OListOptionImport OListOptionImport(SvXMLImport & _rImport,sal_uInt16 _nPrefix,const OUString & _rName,const OListAndComboImportRef & _rListBox)1676 OListOptionImport::OListOptionImport(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const OUString& _rName, 1677 const OListAndComboImportRef& _rListBox) 1678 :SvXMLImportContext(_rImport, _nPrefix, _rName) 1679 ,m_xListBoxImport(_rListBox) 1680 { 1681 } 1682 StartElement(const Reference<XAttributeList> & _rxAttrList)1683 void OListOptionImport::StartElement(const Reference< XAttributeList >& _rxAttrList) 1684 { 1685 // the label and the value 1686 const SvXMLNamespaceMap& rMap = GetImport().GetNamespaceMap(); 1687 const OUString sLabelAttribute = rMap.GetQNameByKey( 1688 GetPrefix(), "label"); 1689 const OUString sValueAttribute = rMap.GetQNameByKey( 1690 GetPrefix(), "value"); 1691 1692 // the label attribute 1693 OUString sValue = _rxAttrList->getValueByName(sLabelAttribute); 1694 bool bNonexistentAttribute = false; 1695 if (sValue.isEmpty()) 1696 if (_rxAttrList->getTypeByName(sLabelAttribute).isEmpty()) 1697 // this attribute does not really exist 1698 bNonexistentAttribute = true; 1699 1700 if (bNonexistentAttribute) 1701 m_xListBoxImport->implEmptyLabelFound(); 1702 else 1703 m_xListBoxImport->implPushBackLabel( sValue ); 1704 1705 // the value attribute 1706 sValue = _rxAttrList->getValueByName(sValueAttribute); 1707 bNonexistentAttribute = false; 1708 if (sValue.isEmpty()) 1709 if (_rxAttrList->getTypeByName(sValueAttribute).isEmpty()) 1710 // this attribute does not really exist 1711 bNonexistentAttribute = true; 1712 1713 if (bNonexistentAttribute) 1714 m_xListBoxImport->implEmptyValueFound(); 1715 else 1716 m_xListBoxImport->implPushBackValue( sValue ); 1717 1718 // the current-selected and selected 1719 const OUString sSelectedAttribute = rMap.GetQNameByKey( 1720 GetPrefix(), OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCAFlags::CurrentSelected))); 1721 const OUString sDefaultSelectedAttribute = rMap.GetQNameByKey( 1722 GetPrefix(), OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCAFlags::Selected))); 1723 1724 // propagate the selected flag 1725 bool bSelected(false); 1726 (void)::sax::Converter::convertBool(bSelected, 1727 _rxAttrList->getValueByName(sSelectedAttribute)); 1728 if (bSelected) 1729 m_xListBoxImport->implSelectCurrentItem(); 1730 1731 // same for the default selected 1732 bool bDefaultSelected(false); 1733 (void)::sax::Converter::convertBool(bDefaultSelected, 1734 _rxAttrList->getValueByName(sDefaultSelectedAttribute)); 1735 if (bDefaultSelected) 1736 m_xListBoxImport->implDefaultSelectCurrentItem(); 1737 1738 SvXMLImportContext::StartElement(_rxAttrList); 1739 } 1740 1741 //= OComboItemImport OComboItemImport(SvXMLImport & _rImport,sal_uInt16 _nPrefix,const OUString & _rName,const OListAndComboImportRef & _rListBox)1742 OComboItemImport::OComboItemImport(SvXMLImport& _rImport, sal_uInt16 _nPrefix, const OUString& _rName, 1743 const OListAndComboImportRef& _rListBox) 1744 :SvXMLImportContext(_rImport, _nPrefix, _rName) 1745 ,m_xListBoxImport(_rListBox) 1746 { 1747 } 1748 StartElement(const Reference<XAttributeList> & _rxAttrList)1749 void OComboItemImport::StartElement(const Reference< XAttributeList >& _rxAttrList) 1750 { 1751 const OUString sLabelAttributeName = GetImport().GetNamespaceMap().GetQNameByKey( 1752 GetPrefix(), OUString::createFromAscii(OAttributeMetaData::getCommonControlAttributeName(CCAFlags::Label))); 1753 m_xListBoxImport->implPushBackLabel(_rxAttrList->getValueByName(sLabelAttributeName)); 1754 1755 SvXMLImportContext::StartElement(_rxAttrList); 1756 } 1757 1758 //= OColumnWrapperImport OColumnWrapperImport(OFormLayerXMLImport_Impl & _rImport,IEventAttacherManager & _rEventManager,sal_uInt16 _nPrefix,const OUString & _rName,const Reference<XNameContainer> & _rxParentContainer)1759 OColumnWrapperImport::OColumnWrapperImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const OUString& _rName, 1760 const Reference< XNameContainer >& _rxParentContainer) 1761 :SvXMLImportContext(_rImport.getGlobalContext(), _nPrefix, _rName) 1762 ,m_xParentContainer(_rxParentContainer) 1763 ,m_rFormImport(_rImport) 1764 ,m_rEventManager(_rEventManager) 1765 { 1766 } CreateChildContext(sal_uInt16 _nPrefix,const OUString & _rLocalName,const Reference<XAttributeList> &)1767 SvXMLImportContextRef OColumnWrapperImport::CreateChildContext(sal_uInt16 _nPrefix, const OUString& _rLocalName, 1768 const Reference< XAttributeList >&) 1769 { 1770 OControlImport* pReturn = implCreateChildContext(_nPrefix, _rLocalName, OElementNameMap::getElementType(_rLocalName)); 1771 if (pReturn) 1772 { 1773 OSL_ENSURE(m_xOwnAttributes.is(), "OColumnWrapperImport::CreateChildContext: had no form:column element!"); 1774 pReturn->addOuterAttributes(m_xOwnAttributes); 1775 } 1776 return pReturn; 1777 } StartElement(const Reference<XAttributeList> & _rxAttrList)1778 void OColumnWrapperImport::StartElement(const Reference< XAttributeList >& _rxAttrList) 1779 { 1780 OSL_ENSURE(!m_xOwnAttributes.is(), "OColumnWrapperImport::StartElement: already have the cloned list!"); 1781 1782 // clone the attributes 1783 Reference< XCloneable > xCloneList(_rxAttrList, UNO_QUERY); 1784 OSL_ENSURE(xCloneList.is(), "OColumnWrapperImport::StartElement: AttributeList not clonable!"); 1785 if ( xCloneList.is() ) 1786 m_xOwnAttributes.set(xCloneList->createClone(), UNO_QUERY); 1787 OSL_ENSURE(m_xOwnAttributes.is(), "OColumnWrapperImport::StartElement: no cloned list!"); 1788 } 1789 implCreateChildContext(sal_uInt16 _nPrefix,const OUString & _rLocalName,OControlElement::ElementType _eType)1790 OControlImport* OColumnWrapperImport::implCreateChildContext( 1791 sal_uInt16 _nPrefix, const OUString& _rLocalName, 1792 OControlElement::ElementType _eType) 1793 { 1794 OSL_ENSURE( (OControlElement::TEXT == _eType) 1795 || (OControlElement::TEXT_AREA == _eType) 1796 || (OControlElement::FORMATTED_TEXT == _eType) 1797 || (OControlElement::CHECKBOX == _eType) 1798 || (OControlElement::LISTBOX == _eType) 1799 || (OControlElement::COMBOBOX == _eType) 1800 || (OControlElement::TIME == _eType) 1801 || (OControlElement::DATE == _eType), 1802 "OColumnWrapperImport::implCreateChildContext: invalid or unrecognized sub element!"); 1803 1804 switch (_eType) 1805 { 1806 case OControlElement::COMBOBOX: 1807 case OControlElement::LISTBOX: 1808 return new OColumnImport<OListAndComboImport>(m_rFormImport, m_rEventManager, _nPrefix, _rLocalName, m_xParentContainer, _eType ); 1809 1810 case OControlElement::PASSWORD: 1811 return new OColumnImport<OPasswordImport>(m_rFormImport, m_rEventManager, _nPrefix, _rLocalName, m_xParentContainer, _eType ); 1812 1813 case OControlElement::TEXT: 1814 case OControlElement::TEXT_AREA: 1815 case OControlElement::FORMATTED_TEXT: 1816 return new OColumnImport< OTextLikeImport >( m_rFormImport, m_rEventManager, _nPrefix, _rLocalName, m_xParentContainer, _eType ); 1817 1818 default: 1819 return new OColumnImport<OControlImport>(m_rFormImport, m_rEventManager, _nPrefix, _rLocalName, m_xParentContainer, _eType ); 1820 } 1821 } 1822 1823 //= OGridImport OGridImport(OFormLayerXMLImport_Impl & _rImport,IEventAttacherManager & _rEventManager,sal_uInt16 _nPrefix,const OUString & _rName,const Reference<XNameContainer> & _rxParentContainer,OControlElement::ElementType _eType)1824 OGridImport::OGridImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const OUString& _rName, 1825 const Reference< XNameContainer >& _rxParentContainer, 1826 OControlElement::ElementType _eType) 1827 :OGridImport_Base(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, "column") 1828 { 1829 setElementType(_eType); 1830 } 1831 implCreateControlWrapper(sal_uInt16 _nPrefix,const OUString & _rLocalName)1832 SvXMLImportContext* OGridImport::implCreateControlWrapper(sal_uInt16 _nPrefix, const OUString& _rLocalName) 1833 { 1834 return new OColumnWrapperImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer); 1835 } 1836 1837 //= OFormImport OFormImport(OFormLayerXMLImport_Impl & _rImport,IEventAttacherManager & _rEventManager,sal_uInt16 _nPrefix,const OUString & _rName,const Reference<XNameContainer> & _rxParentContainer)1838 OFormImport::OFormImport(OFormLayerXMLImport_Impl& _rImport, IEventAttacherManager& _rEventManager, sal_uInt16 _nPrefix, const OUString& _rName, 1839 const Reference< XNameContainer >& _rxParentContainer) 1840 :OFormImport_Base(_rImport, _rEventManager, _nPrefix, _rName, _rxParentContainer, "control") 1841 { 1842 enableTrackAttributes(); 1843 } 1844 CreateChildContext(sal_uInt16 _nPrefix,const OUString & _rLocalName,const Reference<XAttributeList> & _rxAttrList)1845 SvXMLImportContextRef OFormImport::CreateChildContext(sal_uInt16 _nPrefix, const OUString& _rLocalName, 1846 const Reference< XAttributeList >& _rxAttrList) 1847 { 1848 if( token::IsXMLToken(_rLocalName, token::XML_FORM) ) 1849 return new OFormImport( m_rFormImport, *this, _nPrefix, _rLocalName, 1850 m_xMeAsContainer); 1851 else if ( token::IsXMLToken(_rLocalName, token::XML_CONNECTION_RESOURCE) ) 1852 return new OXMLDataSourceImport(GetImport(), _nPrefix, _rLocalName, _rxAttrList,m_xElement); 1853 else if( (token::IsXMLToken(_rLocalName, token::XML_EVENT_LISTENERS) && 1854 (XML_NAMESPACE_OFFICE == _nPrefix)) || 1855 token::IsXMLToken( _rLocalName, token::XML_PROPERTIES) ) 1856 return OElementImport::CreateChildContext( _nPrefix, _rLocalName, 1857 _rxAttrList ); 1858 else 1859 return implCreateChildContext( _nPrefix, _rLocalName, 1860 OElementNameMap::getElementType(_rLocalName) ); 1861 } 1862 StartElement(const Reference<XAttributeList> & _rxAttrList)1863 void OFormImport::StartElement(const Reference< XAttributeList >& _rxAttrList) 1864 { 1865 m_rFormImport.enterEventContext(); 1866 OFormImport_Base::StartElement(_rxAttrList); 1867 1868 // handle the target-frame attribute 1869 simulateDefaultedAttribute(OAttributeMetaData::getCommonControlAttributeName(CCAFlags::TargetFrame), PROPERTY_TARGETFRAME, "_blank"); 1870 } 1871 EndElement()1872 void OFormImport::EndElement() 1873 { 1874 OFormImport_Base::EndElement(); 1875 m_rFormImport.leaveEventContext(); 1876 } 1877 implCreateControlWrapper(sal_uInt16 _nPrefix,const OUString & _rLocalName)1878 SvXMLImportContext* OFormImport::implCreateControlWrapper(sal_uInt16 _nPrefix, const OUString& _rLocalName) 1879 { 1880 OSL_ENSURE( false, "illegal call to OFormImport::implCreateControlWrapper" ); 1881 return new SvXMLImportContext(GetImport(), _nPrefix, _rLocalName ); 1882 } 1883 handleAttribute(sal_uInt16 _nNamespaceKey,const OUString & _rLocalName,const OUString & _rValue)1884 bool OFormImport::handleAttribute(sal_uInt16 _nNamespaceKey, const OUString& _rLocalName, const OUString& _rValue) 1885 { 1886 // handle the master/details field attributes (they're way too special to let the OPropertyImport handle them) 1887 static const char* s_sMasterFieldsAttributeName = OAttributeMetaData::getFormAttributeName(faMasterFields); 1888 static const char* s_sDetailFieldsAttributeName = OAttributeMetaData::getFormAttributeName(faDetailFiels); 1889 1890 if ( _rLocalName.equalsAscii(s_sMasterFieldsAttributeName) ) 1891 { 1892 implTranslateStringListProperty(PROPERTY_MASTERFIELDS, _rValue); 1893 return true; 1894 } 1895 1896 if ( _rLocalName.equalsAscii(s_sDetailFieldsAttributeName) ) 1897 { 1898 implTranslateStringListProperty(PROPERTY_DETAILFIELDS, _rValue); 1899 return true; 1900 } 1901 1902 return OFormImport_Base::handleAttribute(_nNamespaceKey, _rLocalName, _rValue); 1903 } 1904 implTranslateStringListProperty(const OUString & _rPropertyName,const OUString & _rValue)1905 void OFormImport::implTranslateStringListProperty(const OUString& _rPropertyName, const OUString& _rValue) 1906 { 1907 PropertyValue aProp; 1908 aProp.Name = _rPropertyName; 1909 1910 Sequence< OUString > aList; 1911 1912 // split up the value string 1913 if (!_rValue.isEmpty()) 1914 { 1915 // For the moment, we build a vector instead of a Sequence. It's easier to handle because of its 1916 // push_back method 1917 ::std::vector< OUString > aElements; 1918 // estimate the number of tokens 1919 sal_Int32 nEstimate = 0, nLength = _rValue.getLength(); 1920 const sal_Unicode* pChars = _rValue.getStr(); 1921 for (sal_Int32 i=0; i<nLength; ++i, ++pChars) 1922 if (*pChars == ',') 1923 ++nEstimate; 1924 aElements.reserve(nEstimate + 1); 1925 // that's the worst case. If the string contains the separator character _quoted_, we reserved too much... 1926 1927 sal_Int32 nElementStart = 0; 1928 sal_Int32 nNextSep = 0; 1929 sal_Int32 nElementLength; 1930 OUString sElement; 1931 do 1932 { 1933 // extract the current element 1934 nNextSep = ::sax::Converter::indexOfComma( 1935 _rValue, nElementStart); 1936 if (-1 == nNextSep) 1937 nNextSep = nLength; 1938 sElement = _rValue.copy(nElementStart, nNextSep - nElementStart); 1939 1940 nElementLength = sElement.getLength(); 1941 // when writing the sequence, we quoted the single elements with " characters 1942 OSL_ENSURE( sElement.startsWith("\"") && sElement.endsWith("\""), 1943 "OFormImport::implTranslateStringListProperty: invalid quoted element name."); 1944 sElement = sElement.copy(1, nElementLength - 2); 1945 1946 aElements.push_back(sElement); 1947 1948 // switch to the next element 1949 nElementStart = 1 + nNextSep; 1950 } 1951 while (nElementStart < nLength); 1952 1953 aList = Sequence< OUString >(aElements.data(), aElements.size()); 1954 } 1955 else 1956 { 1957 OSL_FAIL("OFormImport::implTranslateStringListProperty: invalid value (empty)!"); 1958 } 1959 1960 aProp.Value <<= aList; 1961 1962 // add the property to the base class' array 1963 implPushBackPropertyValue(aProp); 1964 } 1965 //= OXMLDataSourceImport OXMLDataSourceImport(SvXMLImport & _rImport,sal_uInt16 nPrfx,const OUString & _sLocalName,const Reference<css::xml::sax::XAttributeList> & _xAttrList,const css::uno::Reference<css::beans::XPropertySet> & _xElement)1966 OXMLDataSourceImport::OXMLDataSourceImport( 1967 SvXMLImport& _rImport 1968 ,sal_uInt16 nPrfx 1969 , const OUString& _sLocalName 1970 ,const Reference< css::xml::sax::XAttributeList > & _xAttrList 1971 ,const css::uno::Reference< css::beans::XPropertySet >& _xElement) : 1972 SvXMLImportContext( _rImport, nPrfx, _sLocalName ) 1973 { 1974 OSL_ENSURE(_xAttrList.is(),"Attribute list is NULL!"); 1975 const SvXMLNamespaceMap& rMap = _rImport.GetNamespaceMap(); 1976 1977 sal_Int16 nLength = (_xElement.is() && _xAttrList.is()) ? _xAttrList->getLength() : 0; 1978 for(sal_Int16 i = 0; i < nLength; ++i) 1979 { 1980 OUString sLocalName; 1981 OUString sAttrName = _xAttrList->getNameByIndex( i ); 1982 sal_uInt16 nPrefix = rMap.GetKeyByAttrName( sAttrName, &sLocalName ); 1983 1984 if ( ( nPrefix == OAttributeMetaData::getCommonControlAttributeNamespace( CCAFlags::TargetLocation ) ) 1985 && ( sLocalName.equalsAscii( OAttributeMetaData::getCommonControlAttributeName( CCAFlags::TargetLocation ) ) ) 1986 ) 1987 { 1988 OUString sValue = _xAttrList->getValueByIndex( i ); 1989 sValue = _rImport.GetAbsoluteReference(sValue); 1990 INetURLObject aURL(sValue); 1991 if ( aURL.GetProtocol() == INetProtocol::File ) 1992 _xElement->setPropertyValue(PROPERTY_DATASOURCENAME,makeAny(sValue)); 1993 else 1994 _xElement->setPropertyValue(PROPERTY_URL,makeAny(sValue)); // the url is the "sdbc:" string 1995 break; 1996 } 1997 } 1998 } implCreateChildContext(sal_uInt16 _nPrefix,const OUString & _rLocalName,OControlElement::ElementType _eType)1999 OControlImport* OFormImport::implCreateChildContext( 2000 sal_uInt16 _nPrefix, const OUString& _rLocalName, 2001 OControlElement::ElementType _eType ) 2002 { 2003 switch (_eType) 2004 { 2005 case OControlElement::TEXT: 2006 case OControlElement::TEXT_AREA: 2007 case OControlElement::FORMATTED_TEXT: 2008 return new OTextLikeImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType); 2009 2010 case OControlElement::BUTTON: 2011 case OControlElement::IMAGE: 2012 case OControlElement::IMAGE_FRAME: 2013 return new OButtonImport( m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType ); 2014 2015 case OControlElement::COMBOBOX: 2016 case OControlElement::LISTBOX: 2017 return new OListAndComboImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType); 2018 2019 case OControlElement::RADIO: 2020 return new ORadioImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType); 2021 2022 case OControlElement::CHECKBOX: 2023 return new OImagePositionImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType); 2024 2025 case OControlElement::PASSWORD: 2026 return new OPasswordImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType); 2027 2028 case OControlElement::FRAME: 2029 case OControlElement::FIXED_TEXT: 2030 return new OReferredControlImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer); 2031 2032 case OControlElement::GRID: 2033 return new OGridImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType); 2034 2035 case OControlElement::VALUERANGE: 2036 return new OValueRangeImport( m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType ); 2037 2038 default: 2039 return new OControlImport(m_rFormImport, *this, _nPrefix, _rLocalName, m_xMeAsContainer, _eType); 2040 } 2041 } 2042 determineDefaultServiceName() const2043 OUString OFormImport::determineDefaultServiceName() const 2044 { 2045 return "com.sun.star.form.component.Form"; 2046 } 2047 2048 } // namespace xmloff 2049 2050 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 2051