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