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