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