1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_svx.hxx" 30 31 #include "svx/svxerr.hxx" 32 #include "fmpgeimp.hxx" 33 #include "fmundo.hxx" 34 #include "svx/fmtools.hxx" 35 #include "fmprop.hrc" 36 #include "fmservs.hxx" 37 #include "fmobj.hxx" 38 #include "formcontrolfactory.hxx" 39 #include "svx/svditer.hxx" 40 #include "svx/fmresids.hrc" 41 #include "svx/dbtoolsclient.hxx" 42 #include "treevisitor.hxx" 43 44 #include <com/sun/star/sdb/CommandType.hpp> 45 #include <com/sun/star/util/XCloneable.hpp> 46 #include <com/sun/star/container/EnumerableMap.hpp> 47 #include <com/sun/star/drawing/XControlShape.hpp> 48 49 #include <sfx2/objsh.hxx> 50 #include <svx/fmglob.hxx> 51 #include <svx/fmpage.hxx> 52 #include <svx/fmmodel.hxx> 53 #include <tools/resid.hxx> 54 #include <tools/diagnose_ex.h> 55 #include <tools/shl.hxx> 56 #include <vcl/stdtext.hxx> 57 #include <svx/dialmgr.hxx> 58 #include <comphelper/processfactory.hxx> 59 #include <comphelper/componentcontext.hxx> 60 #include <comphelper/uno3.hxx> 61 #include <comphelper/types.hxx> 62 #include <unotools/streamwrap.hxx> 63 #include <rtl/logfile.hxx> 64 65 using namespace ::com::sun::star::uno; 66 using namespace ::com::sun::star::lang; 67 using namespace ::com::sun::star::sdbc; 68 using namespace ::com::sun::star::sdb; 69 using namespace ::com::sun::star::container; 70 using namespace ::com::sun::star::beans; 71 using namespace ::com::sun::star::form; 72 using ::com::sun::star::util::XCloneable; 73 using ::com::sun::star::awt::XControlModel; 74 using ::com::sun::star::container::XMap; 75 using ::com::sun::star::container::EnumerableMap; 76 using ::com::sun::star::drawing::XControlShape; 77 using namespace ::svxform; 78 79 DBG_NAME(FmFormPageImpl) 80 //------------------------------------------------------------------------------ 81 FmFormPageImpl::FmFormPageImpl( FmFormPage& _rPage ) 82 :m_rPage( _rPage ) 83 ,m_bFirstActivation( sal_True ) 84 ,m_bAttemptedFormCreation( false ) 85 ,m_bInFind( false ) 86 { 87 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPageImpl::FmFormPageImpl" ); 88 DBG_CTOR(FmFormPageImpl,NULL); 89 } 90 91 //------------------------------------------------------------------------------ 92 namespace 93 { 94 typedef Reference< XInterface > FormComponent; 95 96 class FormComponentInfo 97 { 98 public: 99 size_t childCount( const FormComponent& _component ) const 100 { 101 Reference< XIndexAccess > xContainer( _component, UNO_QUERY ); 102 if ( xContainer.is() ) 103 return xContainer->getCount(); 104 return 0; 105 } 106 107 FormComponent getChild( const FormComponent& _component, size_t _index ) const 108 { 109 Reference< XIndexAccess > xContainer( _component, UNO_QUERY_THROW ); 110 return FormComponent( xContainer->getByIndex( _index ), UNO_QUERY ); 111 } 112 }; 113 114 typedef ::std::pair< FormComponent, FormComponent > FormComponentPair; 115 116 class FormHierarchyComparator 117 { 118 public: 119 FormHierarchyComparator() 120 { 121 } 122 123 size_t childCount( const FormComponentPair& _components ) const 124 { 125 size_t lhsCount = m_aComponentInfo.childCount( _components.first ); 126 size_t rhsCount = m_aComponentInfo.childCount( _components.second ); 127 if ( lhsCount != rhsCount ) 128 throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Found inconsistent form component hierarchies (1)!" ) ), NULL ); 129 return lhsCount; 130 } 131 132 FormComponentPair getChild( const FormComponentPair& _components, size_t _index ) const 133 { 134 return FormComponentPair( 135 m_aComponentInfo.getChild( _components.first, _index ), 136 m_aComponentInfo.getChild( _components.second, _index ) 137 ); 138 } 139 private: 140 FormComponentInfo m_aComponentInfo; 141 }; 142 143 typedef ::std::map< Reference< XControlModel >, Reference< XControlModel >, ::comphelper::OInterfaceCompare< XControlModel > > MapControlModels; 144 145 class FormComponentAssignment 146 { 147 public: 148 FormComponentAssignment( MapControlModels& _out_controlModelMap ) 149 :m_rControlModelMap( _out_controlModelMap ) 150 { 151 } 152 153 void process( const FormComponentPair& _component ) 154 { 155 Reference< XControlModel > lhsControlModel( _component.first, UNO_QUERY ); 156 Reference< XControlModel > rhsControlModel( _component.second, UNO_QUERY ); 157 if ( lhsControlModel.is() != rhsControlModel.is() ) 158 throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Found inconsistent form component hierarchies (2)!" ) ), NULL ); 159 160 if ( lhsControlModel.is() ) 161 m_rControlModelMap[ lhsControlModel ] = rhsControlModel; 162 } 163 164 private: 165 MapControlModels& m_rControlModelMap; 166 }; 167 } 168 169 //------------------------------------------------------------------------------ 170 void FmFormPageImpl::initFrom( FmFormPageImpl& i_foreignImpl ) 171 { 172 // clone the Forms collection 173 const Reference< XNameContainer > xForeignForms( const_cast< FmFormPageImpl& >( i_foreignImpl ).getForms( false ) ); 174 const Reference< XCloneable > xCloneable( xForeignForms, UNO_QUERY ); 175 if ( !xCloneable.is() ) 176 { 177 // great, nothing to do 178 OSL_ENSURE( !xForeignForms.is(), "FmFormPageImpl::FmFormPageImpl: a non-cloneable forms container!?" ); 179 return; 180 } 181 182 try 183 { 184 m_xForms.set( xCloneable->createClone(), UNO_QUERY_THROW ); 185 186 // create a mapping between the original control models and their clones 187 MapControlModels aModelAssignment; 188 189 typedef TreeVisitor< FormComponentPair, FormHierarchyComparator, FormComponentAssignment > FormComponentVisitor; 190 FormComponentVisitor aVisitor = FormComponentVisitor( FormHierarchyComparator() ); 191 192 FormComponentAssignment aAssignmentProcessor( aModelAssignment ); 193 aVisitor.process( FormComponentPair( xCloneable, m_xForms ), aAssignmentProcessor ); 194 195 // assign the cloned models to their SdrObjects 196 SdrObjListIter aForeignIter( i_foreignImpl.m_rPage ); 197 SdrObjListIter aOwnIter( m_rPage ); 198 199 OSL_ENSURE( aForeignIter.IsMore() == aOwnIter.IsMore(), "FmFormPageImpl::FmFormPageImpl: inconsistent number of objects (1)!" ); 200 while ( aForeignIter.IsMore() && aOwnIter.IsMore() ) 201 { 202 FmFormObj* pForeignObj = dynamic_cast< FmFormObj* >( aForeignIter.Next() ); 203 FmFormObj* pOwnObj = dynamic_cast< FmFormObj* >( aOwnIter.Next() ); 204 205 bool bForeignIsForm = pForeignObj && ( pForeignObj->GetObjInventor() == FmFormInventor ); 206 bool bOwnIsForm = pOwnObj && ( pOwnObj->GetObjInventor() == FmFormInventor ); 207 208 ENSURE_OR_BREAK( bForeignIsForm == bOwnIsForm, "FmFormPageImpl::FmFormPageImpl: inconsistent ordering of objects!" ); 209 // if this fires, don't attempt to do further assignments, something's completely messed up 210 211 if ( !bForeignIsForm ) 212 // no form control -> next round 213 continue; 214 215 Reference< XControlModel > xForeignModel( pForeignObj->GetUnoControlModel() ); 216 ENSURE_OR_CONTINUE( xForeignModel.is(), "FmFormPageImpl::FmFormPageImpl: control shape without control!" ); 217 // if this fires, the SdrObject does not have a UNO Control Model. This is pathological, but well ... 218 // So the cloned SdrObject will also not have a UNO Control Model. 219 220 MapControlModels::const_iterator assignment = aModelAssignment.find( xForeignModel ); 221 ENSURE_OR_CONTINUE( assignment != aModelAssignment.end(), "FmFormPageImpl::FmFormPageImpl: no clone found for this model!" ); 222 // if this fires, the source SdrObject has a model, but it is not part of the model hierarchy in 223 // i_foreignImpl.getForms(). 224 // Pathological, too ... 225 226 pOwnObj->SetUnoControlModel( assignment->second ); 227 } 228 OSL_ENSURE( aForeignIter.IsMore() == aOwnIter.IsMore(), "FmFormPageImpl::FmFormPageImpl: inconsistent number of objects (2)!" ); 229 } 230 catch( const Exception& ) 231 { 232 DBG_UNHANDLED_EXCEPTION(); 233 } 234 } 235 236 //------------------------------------------------------------------------------ 237 Reference< XMap > FmFormPageImpl::getControlToShapeMap() 238 { 239 Reference< XMap > xControlShapeMap( m_aControlShapeMap.get(), UNO_QUERY ); 240 if ( xControlShapeMap.is() ) 241 return xControlShapeMap; 242 243 xControlShapeMap = impl_createControlShapeMap_nothrow(); 244 m_aControlShapeMap = xControlShapeMap; 245 return xControlShapeMap; 246 } 247 248 //------------------------------------------------------------------------------ 249 namespace 250 { 251 static void lcl_insertFormObject_throw( const FmFormObj& _object, const Reference< XMap >& _map ) 252 { 253 // the control model 254 Reference< XControlModel > xControlModel( _object.GetUnoControlModel(), UNO_QUERY ); 255 OSL_ENSURE( xControlModel.is(), "lcl_insertFormObject_throw: suspicious: no control model!" ); 256 if ( !xControlModel.is() ) 257 return; 258 259 Reference< XControlShape > xControlShape( const_cast< FmFormObj& >( _object ).getUnoShape(), UNO_QUERY ); 260 OSL_ENSURE( xControlShape.is(), "lcl_insertFormObject_throw: suspicious: no control shape!" ); 261 if ( !xControlShape.is() ) 262 return; 263 264 _map->put( makeAny( xControlModel ), makeAny( xControlShape ) ); 265 } 266 267 static void lcl_removeFormObject_throw( const FmFormObj& _object, const Reference< XMap >& _map, bool i_ignoreNonExistence = false ) 268 { 269 // the control model 270 Reference< XControlModel > xControlModel( _object.GetUnoControlModel(), UNO_QUERY ); 271 OSL_ENSURE( xControlModel.is(), "lcl_removeFormObject: suspicious: no control model!" ); 272 if ( !xControlModel.is() ) 273 return; 274 275 #if OSL_DEBUG_LEVEL > 0 276 Any aOldAssignment = 277 #endif 278 _map->remove( makeAny( xControlModel ) ); 279 #if OSL_DEBUG_LEVEL > 0 280 (void)aOldAssignment; 281 #endif 282 OSL_ENSURE( !i_ignoreNonExistence || 283 ( aOldAssignment == makeAny( Reference< XControlShape >( const_cast< FmFormObj& >( _object ).getUnoShape(), UNO_QUERY ) ) ), 284 "lcl_removeFormObject: map was inconsistent!" ); 285 (void)i_ignoreNonExistence; 286 } 287 } 288 289 //------------------------------------------------------------------------------ 290 Reference< XMap > FmFormPageImpl::impl_createControlShapeMap_nothrow() 291 { 292 Reference< XMap > xMap; 293 294 try 295 { 296 ::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() ); 297 xMap.set( EnumerableMap::create( aContext.getUNOContext(), 298 ::cppu::UnoType< XControlModel >::get(), 299 ::cppu::UnoType< XControlShape >::get() 300 ).get(), UNO_SET_THROW ); 301 302 SdrObjListIter aPageIter( m_rPage ); 303 while ( aPageIter.IsMore() ) 304 { 305 // only FmFormObjs are what we're interested in 306 FmFormObj* pCurrent = FmFormObj::GetFormObject( aPageIter.Next() ); 307 if ( !pCurrent ) 308 continue; 309 310 lcl_insertFormObject_throw( *pCurrent, xMap ); 311 } 312 } 313 catch( const Exception& ) 314 { 315 DBG_UNHANDLED_EXCEPTION(); 316 } 317 return xMap; 318 } 319 320 //------------------------------------------------------------------------------ 321 const Reference< XNameContainer >& FmFormPageImpl::getForms( bool _bForceCreate ) 322 { 323 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPageImpl::getForms" ); 324 if ( m_xForms.is() || !_bForceCreate ) 325 return m_xForms; 326 327 if ( !m_bAttemptedFormCreation ) 328 { 329 m_bAttemptedFormCreation = true; 330 331 const ::rtl::OUString sFormsCollectionServiceName = ::rtl::OUString::createFromAscii("com.sun.star.form.Forms"); 332 m_xForms = Reference< XNameContainer > ( 333 ::comphelper::getProcessServiceFactory()->createInstance( sFormsCollectionServiceName ), 334 UNO_QUERY 335 ); 336 DBG_ASSERT( m_xForms.is(), "FmFormPageImpl::getForms: could not create a forms collection!" ); 337 338 if ( m_aFormsCreationHdl.IsSet() ) 339 { 340 m_aFormsCreationHdl.Call( this ); 341 } 342 343 FmFormModel* pFormsModel = PTR_CAST( FmFormModel, m_rPage.GetModel() ); 344 345 // give the newly created collection a place in the universe 346 Reference< XChild > xAsChild( m_xForms, UNO_QUERY ); 347 if ( xAsChild.is() ) 348 { 349 SfxObjectShell* pObjShell = pFormsModel ? pFormsModel->GetObjectShell() : NULL; 350 if ( pObjShell ) 351 xAsChild->setParent( pObjShell->GetModel() ); 352 } 353 354 // tell the UNDO environment that we have a new forms collection 355 if ( pFormsModel ) 356 pFormsModel->GetUndoEnv().AddForms( m_xForms ); 357 } 358 return m_xForms; 359 } 360 361 //------------------------------------------------------------------------------ 362 FmFormPageImpl::~FmFormPageImpl() 363 { 364 xCurrentForm = NULL; 365 366 ::comphelper::disposeComponent( m_xForms ); 367 DBG_DTOR(FmFormPageImpl,NULL); 368 } 369 370 //------------------------------------------------------------------------------ 371 bool FmFormPageImpl::validateCurForm() 372 { 373 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPageImpl::validateCurForm" ); 374 if ( !xCurrentForm.is() ) 375 return false; 376 377 Reference< XChild > xAsChild( xCurrentForm, UNO_QUERY ); 378 DBG_ASSERT( xAsChild.is(), "FmFormPageImpl::validateCurForm: a form which is no child??" ); 379 if ( !xAsChild.is() || !xAsChild->getParent().is() ) 380 xCurrentForm.clear(); 381 382 return xCurrentForm.is(); 383 } 384 385 //------------------------------------------------------------------------------ 386 void FmFormPageImpl::setCurForm(Reference< ::com::sun::star::form::XForm > xForm) 387 { 388 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPageImpl::setCurForm" ); 389 xCurrentForm = xForm; 390 } 391 392 //------------------------------------------------------------------------------ 393 Reference< XForm > FmFormPageImpl::getDefaultForm() 394 { 395 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPageImpl::getDefaultForm" ); 396 Reference< XForm > xForm; 397 398 Reference< XNameContainer > xForms( getForms() ); 399 400 // by default, we use our "current form" 401 if ( !validateCurForm() ) 402 { 403 // check whether there is a "standard" form 404 if ( xForms->hasElements() ) 405 { 406 // suche die Standardform 407 ::rtl::OUString sStandardFormname = String( SVX_RES( RID_STR_STDFORMNAME ) ); 408 409 try 410 { 411 if ( xForms->hasByName( sStandardFormname ) ) 412 xForm.set( xForms->getByName( sStandardFormname ), UNO_QUERY_THROW ); 413 else 414 { 415 Reference< XIndexAccess > xFormsByIndex( xForms, UNO_QUERY_THROW ); 416 xForm.set( xFormsByIndex->getByIndex(0), UNO_QUERY_THROW ); 417 } 418 } 419 catch( const Exception& ) 420 { 421 DBG_UNHANDLED_EXCEPTION(); 422 } 423 } 424 } 425 else 426 { 427 xForm = xCurrentForm; 428 } 429 430 // did not find an existing suitable form -> create a new one 431 if ( !xForm.is() ) 432 { 433 SdrModel* pModel = m_rPage.GetModel(); 434 435 if( pModel->IsUndoEnabled() ) 436 { 437 XubString aStr(SVX_RES(RID_STR_FORM)); 438 XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_INSERT)); 439 aUndoStr.SearchAndReplace('#', aStr); 440 pModel->BegUndo(aUndoStr); 441 } 442 443 try 444 { 445 xForm.set( ::comphelper::getProcessServiceFactory()->createInstance( FM_SUN_COMPONENT_FORM ), UNO_QUERY ); 446 447 // a form should always have the command type table as default 448 Reference< XPropertySet > xFormProps( xForm, UNO_QUERY_THROW ); 449 xFormProps->setPropertyValue( FM_PROP_COMMANDTYPE, makeAny( sal_Int32( CommandType::TABLE ) ) ); 450 451 // and the "Standard" name 452 ::rtl::OUString sName = String( SVX_RES( RID_STR_STDFORMNAME ) ); 453 xFormProps->setPropertyValue( FM_PROP_NAME, makeAny( sName ) ); 454 455 Reference< XIndexContainer > xContainer( xForms, UNO_QUERY ); 456 if( pModel->IsUndoEnabled() ) 457 { 458 pModel->AddUndo(new FmUndoContainerAction(*(FmFormModel*)pModel, 459 FmUndoContainerAction::Inserted, 460 xContainer, 461 xForm, 462 xContainer->getCount())); 463 } 464 xForms->insertByName( sName, makeAny( xForm ) ); 465 xCurrentForm = xForm; 466 } 467 catch( const Exception& ) 468 { 469 DBG_UNHANDLED_EXCEPTION(); 470 xForm.clear(); 471 } 472 473 if( pModel->IsUndoEnabled() ) 474 pModel->EndUndo(); 475 } 476 477 return xForm; 478 } 479 480 //------------------------------------------------------------------------------ 481 Reference< ::com::sun::star::form::XForm > FmFormPageImpl::findPlaceInFormComponentHierarchy( 482 const Reference< XFormComponent > & rContent, const Reference< XDataSource > & rDatabase, 483 const ::rtl::OUString& rDBTitle, const ::rtl::OUString& rCursorSource, sal_Int32 nCommandType ) 484 { 485 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPageImpl::findPlaceInFormComponentHierarchy" ); 486 // if the control already is child of a form, don't do anything 487 if (!rContent.is() || rContent->getParent().is()) 488 return NULL; 489 490 Reference< XForm > xForm; 491 492 // Wenn Datenbank und CursorSource gesetzt sind, dann wird 493 // die Form anhand dieser Kriterien gesucht, ansonsten nur aktuelle 494 // und die StandardForm 495 if (rDatabase.is() && rCursorSource.getLength()) 496 { 497 validateCurForm(); 498 499 // erst in der aktuellen form suchen 500 xForm = findFormForDataSource( xCurrentForm, rDatabase, rCursorSource, nCommandType ); 501 502 Reference< ::com::sun::star::container::XIndexAccess > xFormsByIndex( getForms(), UNO_QUERY ); 503 DBG_ASSERT(xFormsByIndex.is(), "FmFormPageImpl::findPlaceInFormComponentHierarchy : no index access for my forms collection !"); 504 sal_Int32 nCount = xFormsByIndex->getCount(); 505 for (sal_Int32 i = 0; !xForm.is() && i < nCount; i++) 506 { 507 Reference< ::com::sun::star::form::XForm > xToSearch; 508 xFormsByIndex->getByIndex(i) >>= xToSearch; 509 xForm = findFormForDataSource( xToSearch, rDatabase, rCursorSource, nCommandType ); 510 } 511 512 // wenn keine ::com::sun::star::form gefunden, dann eine neue erzeugen 513 if (!xForm.is()) 514 { 515 SdrModel* pModel = m_rPage.GetModel(); 516 517 const bool bUndo = pModel->IsUndoEnabled(); 518 519 if( bUndo ) 520 { 521 XubString aStr(SVX_RES(RID_STR_FORM)); 522 XubString aUndoStr(SVX_RES(RID_STR_UNDO_CONTAINER_INSERT)); 523 aUndoStr.SearchAndReplace('#', aStr); 524 pModel->BegUndo(aUndoStr); 525 } 526 527 xForm = Reference< ::com::sun::star::form::XForm >(::comphelper::getProcessServiceFactory()->createInstance(FM_SUN_COMPONENT_FORM), UNO_QUERY); 528 // a form should always have the command type table as default 529 Reference< ::com::sun::star::beans::XPropertySet > xFormProps(xForm, UNO_QUERY); 530 try { xFormProps->setPropertyValue(FM_PROP_COMMANDTYPE, makeAny(sal_Int32(CommandType::TABLE))); } 531 catch(Exception&) { } 532 533 if (rDBTitle.getLength()) 534 xFormProps->setPropertyValue(FM_PROP_DATASOURCE,makeAny(rDBTitle)); 535 else 536 { 537 Reference< ::com::sun::star::beans::XPropertySet > xDatabaseProps(rDatabase, UNO_QUERY); 538 Any aDatabaseUrl = xDatabaseProps->getPropertyValue(FM_PROP_URL); 539 xFormProps->setPropertyValue(FM_PROP_DATASOURCE, aDatabaseUrl); 540 } 541 542 xFormProps->setPropertyValue(FM_PROP_COMMAND,makeAny(rCursorSource)); 543 xFormProps->setPropertyValue(FM_PROP_COMMANDTYPE, makeAny(nCommandType)); 544 545 Reference< ::com::sun::star::container::XNameAccess > xNamedSet( getForms(), UNO_QUERY ); 546 547 const bool bTableOrQuery = ( CommandType::TABLE == nCommandType ) || ( CommandType::QUERY == nCommandType ); 548 ::rtl::OUString sName = FormControlFactory::getUniqueName( xNamedSet, 549 bTableOrQuery ? rCursorSource : ::rtl::OUString( String( SVX_RES( RID_STR_STDFORMNAME ) ) ) ); 550 551 xFormProps->setPropertyValue( FM_PROP_NAME, makeAny( sName ) ); 552 553 if( bUndo ) 554 { 555 Reference< ::com::sun::star::container::XIndexContainer > xContainer( getForms(), UNO_QUERY ); 556 pModel->AddUndo(new FmUndoContainerAction(*(FmFormModel*)pModel, 557 FmUndoContainerAction::Inserted, 558 xContainer, 559 xForm, 560 xContainer->getCount())); 561 } 562 563 getForms()->insertByName( sName, makeAny( xForm ) ); 564 565 if( bUndo ) 566 pModel->EndUndo(); 567 } 568 xCurrentForm = xForm; 569 } 570 571 xForm = getDefaultForm(); 572 return xForm; 573 } 574 575 //------------------------------------------------------------------------------ 576 Reference< XForm > FmFormPageImpl::findFormForDataSource( 577 const Reference< XForm > & rForm, const Reference< XDataSource > & _rxDatabase, 578 const ::rtl::OUString& _rCursorSource, sal_Int32 nCommandType) 579 { 580 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "svx", "Ocke.Janssen@sun.com", "FmFormPageImpl::findFormForDataSource" ); 581 Reference< XForm > xResultForm; 582 Reference< XRowSet > xDBForm(rForm, UNO_QUERY); 583 Reference< XPropertySet > xFormProps(rForm, UNO_QUERY); 584 if (!xDBForm.is() || !xFormProps.is()) 585 return xResultForm; 586 587 OSL_ENSURE(_rxDatabase.is(), "FmFormPageImpl::findFormForDataSource: invalid data source!"); 588 ::rtl::OUString sLookupName; // the name of the data source we're looking for 589 ::rtl::OUString sFormDataSourceName; // the name of the data source the current connection in the form is based on 590 try 591 { 592 Reference< XPropertySet > xDSProps(_rxDatabase, UNO_QUERY); 593 if (xDSProps.is()) 594 xDSProps->getPropertyValue(FM_PROP_NAME) >>= sLookupName; 595 596 xFormProps->getPropertyValue(FM_PROP_DATASOURCE) >>= sFormDataSourceName; 597 // if there's no DataSourceName set at the form, check whether we can deduce one from its 598 // ActiveConnection 599 if (0 == sFormDataSourceName.getLength()) 600 { 601 Reference< XConnection > xFormConnection; 602 xFormProps->getPropertyValue( FM_PROP_ACTIVE_CONNECTION ) >>= xFormConnection; 603 if ( !xFormConnection.is() ) 604 OStaticDataAccessTools().isEmbeddedInDatabase( xFormProps, xFormConnection ); 605 if (xFormConnection.is()) 606 { 607 Reference< XChild > xConnAsChild(xFormConnection, UNO_QUERY); 608 if (xConnAsChild.is()) 609 { 610 Reference< XDataSource > xFormDS(xConnAsChild->getParent(), UNO_QUERY); 611 if (xFormDS.is()) 612 { 613 xDSProps = xDSProps.query(xFormDS); 614 if (xDSProps.is()) 615 xDSProps->getPropertyValue(FM_PROP_NAME) >>= sFormDataSourceName; 616 } 617 } 618 } 619 } 620 } 621 catch(const Exception& e) 622 { 623 (void)e; 624 OSL_ENSURE(sal_False, "FmFormPageImpl::findFormForDataSource: caught an exception!"); 625 } 626 627 if (sLookupName == sFormDataSourceName) 628 { 629 // jetzt noch ueberpruefen ob CursorSource und Type uebereinstimmen 630 ::rtl::OUString aCursorSource = ::comphelper::getString(xFormProps->getPropertyValue(FM_PROP_COMMAND)); 631 sal_Int32 nType = ::comphelper::getINT32(xFormProps->getPropertyValue(FM_PROP_COMMANDTYPE)); 632 if (!aCursorSource.getLength() || ((nType == nCommandType) && (aCursorSource == _rCursorSource))) // found the form 633 { 634 xResultForm = rForm; 635 // Ist noch keine Datenquelle gesetzt, wird dieses hier nachgeholt 636 if (!aCursorSource.getLength()) 637 { 638 xFormProps->setPropertyValue(FM_PROP_COMMAND, makeAny(_rCursorSource)); 639 xFormProps->setPropertyValue(FM_PROP_COMMANDTYPE, makeAny((sal_Int32)nCommandType)); 640 } 641 } 642 } 643 644 // as long as xResultForm is NULL, search the child forms of rForm 645 Reference< XIndexAccess > xComponents(rForm, UNO_QUERY); 646 sal_Int32 nCount = xComponents->getCount(); 647 for (sal_Int32 i = 0; !xResultForm.is() && i < nCount; ++i) 648 { 649 Reference< ::com::sun::star::form::XForm > xSearchForm; 650 xComponents->getByIndex(i) >>= xSearchForm; 651 // continue searching in the sub form 652 if (xSearchForm.is()) 653 xResultForm = findFormForDataSource( xSearchForm, _rxDatabase, _rCursorSource, nCommandType ); 654 } 655 return xResultForm; 656 } 657 658 //------------------------------------------------------------------------------ 659 ::rtl::OUString FmFormPageImpl::setUniqueName(const Reference< XFormComponent > & xFormComponent, const Reference< XForm > & xControls) 660 { 661 #if OSL_DEBUG_LEVEL > 0 662 try 663 { 664 Reference< XChild > xChild( xFormComponent, UNO_QUERY_THROW ); 665 OSL_ENSURE( !xChild->getParent().is(), "FmFormPageImpl::setUniqueName: to be called before insertion!" ); 666 } 667 catch( const Exception& ) 668 { 669 DBG_UNHANDLED_EXCEPTION(); 670 } 671 #endif 672 ::rtl::OUString sName; 673 Reference< ::com::sun::star::beans::XPropertySet > xSet(xFormComponent, UNO_QUERY); 674 if (xSet.is()) 675 { 676 sName = ::comphelper::getString( xSet->getPropertyValue( FM_PROP_NAME ) ); 677 Reference< ::com::sun::star::container::XNameAccess > xNameAcc(xControls, UNO_QUERY); 678 679 if (!sName.getLength() || xNameAcc->hasByName(sName)) 680 { 681 // setzen eines default Namens ueber die ClassId 682 sal_Int16 nClassId( FormComponentType::CONTROL ); 683 xSet->getPropertyValue( FM_PROP_CLASSID ) >>= nClassId; 684 685 ::rtl::OUString sDefaultName = FormControlFactory::getDefaultUniqueName_ByComponentType( 686 Reference< XNameAccess >( xControls, UNO_QUERY ), xSet ); 687 688 // bei Radiobuttons, die einen Namen haben, diesen nicht ueberschreiben! 689 if (!sName.getLength() || nClassId != ::com::sun::star::form::FormComponentType::RADIOBUTTON) 690 { 691 xSet->setPropertyValue(FM_PROP_NAME, makeAny(sDefaultName)); 692 } 693 694 sName = sDefaultName; 695 } 696 } 697 return sName; 698 } 699 700 //---------------------------------------------------------------------------------------------------------------------- 701 void FmFormPageImpl::formModelAssigned( const FmFormObj& _object ) 702 { 703 Reference< XMap > xControlShapeMap( m_aControlShapeMap.get(), UNO_QUERY ); 704 if ( !xControlShapeMap.is() ) 705 // our map does not exist -> not interested in this event 706 return; 707 708 try 709 { 710 lcl_removeFormObject_throw( _object, xControlShapeMap, false ); 711 lcl_insertFormObject_throw( _object, xControlShapeMap ); 712 } 713 catch( const Exception& ) 714 { 715 DBG_UNHANDLED_EXCEPTION(); 716 } 717 } 718 719 //---------------------------------------------------------------------------------------------------------------------- 720 void FmFormPageImpl::formObjectInserted( const FmFormObj& _object ) 721 { 722 Reference< XMap > xControlShapeMap( m_aControlShapeMap.get(), UNO_QUERY ); 723 if ( !xControlShapeMap.is() ) 724 // our map does not exist -> not interested in this event 725 return; 726 727 try 728 { 729 lcl_insertFormObject_throw( _object, xControlShapeMap ); 730 } 731 catch( const Exception& ) 732 { 733 DBG_UNHANDLED_EXCEPTION(); 734 } 735 } 736 737 //---------------------------------------------------------------------------------------------------------------------- 738 void FmFormPageImpl::formObjectRemoved( const FmFormObj& _object ) 739 { 740 Reference< XMap > xControlShapeMap( m_aControlShapeMap.get(), UNO_QUERY ); 741 if ( !xControlShapeMap.is() ) 742 // our map does not exist -> not interested in this event 743 return; 744 745 try 746 { 747 lcl_removeFormObject_throw( _object, xControlShapeMap ); 748 } 749 catch( const Exception& ) 750 { 751 DBG_UNHANDLED_EXCEPTION(); 752 } 753 } 754