Coverage Report

Created: 2026-05-16 09:25

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