xref: /aoo42x/main/svx/source/form/fmpgeimp.cxx (revision cdf0e10c)
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