Coverage Report

Created: 2026-07-10 11:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/svx/source/form/fmtools.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 <fmprop.hxx>
22
#include <fmservs.hxx>
23
#include <svx/fmtools.hxx>
24
#include <svx/svdobjkind.hxx>
25
26
#include <com/sun/star/beans/XPropertySet.hpp>
27
#include <com/sun/star/container/XIndexAccess.hpp>
28
#include <com/sun/star/io/XPersistObject.hpp>
29
#include <com/sun/star/lang/XServiceInfo.hpp>
30
#include <com/sun/star/sdb/ErrorCondition.hpp>
31
#include <com/sun/star/sdb/ErrorMessageDialog.hpp>
32
#include <com/sun/star/sdb/SQLContext.hpp>
33
#include <com/sun/star/sdb/SQLErrorEvent.hpp>
34
#include <com/sun/star/sdb/XCompletedConnection.hpp>
35
#include <com/sun/star/sdb/XResultSetAccess.hpp>
36
#include <com/sun/star/sdbc/XRowSet.hpp>
37
#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
38
#include <com/sun/star/util/Language.hpp>
39
40
#include <comphelper/processfactory.hxx>
41
#include <comphelper/property.hxx>
42
#include <comphelper/types.hxx>
43
#include <tools/debug.hxx>
44
#include <comphelper/diagnose_ex.hxx>
45
46
using namespace ::com::sun::star::uno;
47
using namespace ::com::sun::star::lang;
48
using namespace ::com::sun::star::awt;
49
using namespace ::com::sun::star::beans;
50
using namespace ::com::sun::star::container;
51
using namespace ::com::sun::star::ui::dialogs;
52
using namespace ::com::sun::star::sdbc;
53
using namespace ::com::sun::star::sdbcx;
54
using namespace ::com::sun::star::sdb;
55
using namespace ::svxform;
56
57
namespace
58
{
59
    bool lcl_shouldDisplayError( const Any& _rError )
60
0
    {
61
0
        SQLException aError;
62
0
        if ( !( _rError >>= aError ) )
63
0
            return true;
64
65
0
        if ( ! aError.Message.startsWith( "[OOoBase]" ) )
66
            // it is an exception *not* thrown by an OOo Base core component
67
0
            return true;
68
69
        // the only exception we do not display ATM is a RowSetVetoException, which
70
        // has been raised because an XRowSetApprovalListener vetoed a change
71
0
        if ( aError.ErrorCode + ErrorCondition::ROW_SET_OPERATION_VETOED == 0 )
72
0
            return false;
73
74
        // everything else is to be displayed
75
0
        return true;
76
0
    }
77
}
78
79
void displayException(const Any& _rExcept, const css::uno::Reference<css::awt::XWindow>& rParent)
80
0
{
81
    // check whether we need to display it
82
0
    if ( !lcl_shouldDisplayError( _rExcept ) )
83
0
        return;
84
85
0
    try
86
0
    {
87
0
        Reference< XExecutableDialog > xErrorDialog = ErrorMessageDialog::create(::comphelper::getProcessComponentContext(), u""_ustr, rParent, _rExcept);
88
0
        xErrorDialog->execute();
89
0
    }
90
0
    catch(const Exception&)
91
0
    {
92
0
        TOOLS_WARN_EXCEPTION("svx.form", "could not display the error message!");
93
0
    }
94
0
}
95
96
void displayException(const css::sdbc::SQLException& _rExcept, const css::uno::Reference<css::awt::XWindow>& rParent)
97
0
{
98
0
    displayException(Any(_rExcept), rParent);
99
0
}
100
101
void displayException(const css::sdb::SQLContext& _rExcept, const css::uno::Reference<css::awt::XWindow>& rParent)
102
0
{
103
0
    displayException(Any(_rExcept), rParent);
104
0
}
105
106
void displayException(const css::sdb::SQLErrorEvent& _rEvent, const css::uno::Reference<css::awt::XWindow>& rParent)
107
0
{
108
0
    displayException(_rEvent.Reason, rParent);
109
0
}
110
111
sal_Int32 getElementPos(const Reference< css::container::XIndexAccess>& xCont, const Reference< XInterface >& xElement)
112
0
{
113
0
    sal_Int32 nIndex = -1;
114
0
    if (!xCont.is())
115
0
        return nIndex;
116
117
118
0
    Reference< XInterface > xNormalized( xElement, UNO_QUERY );
119
0
    DBG_ASSERT( xNormalized.is(), "getElementPos: invalid element!" );
120
0
    if ( xNormalized.is() )
121
0
    {
122
        // find child position
123
0
        nIndex = xCont->getCount();
124
0
        while (nIndex--)
125
0
        {
126
0
            try
127
0
            {
128
0
                Reference< XInterface > xCurrent(xCont->getByIndex( nIndex ),UNO_QUERY);
129
0
                DBG_ASSERT( xCurrent.get() == Reference< XInterface >( xCurrent, UNO_QUERY ).get(),
130
0
                    "getElementPos: container element not normalized!" );
131
0
                if ( xNormalized.get() == xCurrent.get() )
132
0
                    break;
133
0
            }
134
0
            catch(Exception&)
135
0
            {
136
0
                TOOLS_WARN_EXCEPTION( "svx", "getElementPos" );
137
0
            }
138
139
0
        }
140
0
    }
141
0
    return nIndex;
142
0
}
143
144
145
OUString getLabelName(const Reference< css::beans::XPropertySet>& xControlModel)
146
0
{
147
0
    if (!xControlModel.is())
148
0
        return OUString();
149
150
0
    if (::comphelper::hasProperty(FM_PROP_CONTROLLABEL, xControlModel))
151
0
    {
152
0
        Reference< css::beans::XPropertySet> xLabelSet;
153
0
        xControlModel->getPropertyValue(FM_PROP_CONTROLLABEL) >>= xLabelSet;
154
0
        if (xLabelSet.is() && ::comphelper::hasProperty(FM_PROP_LABEL, xLabelSet))
155
0
        {
156
0
            Any aLabel( xLabelSet->getPropertyValue(FM_PROP_LABEL) );
157
0
            if ((aLabel.getValueTypeClass() == TypeClass_STRING) && !::comphelper::getString(aLabel).isEmpty())
158
0
                return ::comphelper::getString(aLabel);
159
0
        }
160
0
    }
161
162
0
    return ::comphelper::getString(xControlModel->getPropertyValue(FM_PROP_CONTROLSOURCE));
163
0
}
164
165
166
// = CursorWrapper
167
168
CursorWrapper::CursorWrapper(const Reference< css::sdbc::XRowSet>& _rxCursor, bool bUseCloned)
169
0
{
170
0
    ImplConstruct(Reference< css::sdbc::XResultSet>(_rxCursor), bUseCloned);
171
0
}
172
173
174
CursorWrapper::CursorWrapper(const Reference< css::sdbc::XResultSet>& _rxCursor, bool bUseCloned)
175
0
{
176
0
    ImplConstruct(_rxCursor, bUseCloned);
177
0
}
178
179
180
void CursorWrapper::ImplConstruct(const Reference< css::sdbc::XResultSet>& _rxCursor, bool bUseCloned)
181
0
{
182
0
    if (bUseCloned)
183
0
    {
184
0
        Reference< css::sdb::XResultSetAccess> xAccess(_rxCursor, UNO_QUERY);
185
0
        try
186
0
        {
187
0
            m_xMoveOperations = xAccess.is() ? xAccess->createResultSet() : Reference< css::sdbc::XResultSet>();
188
0
        }
189
0
        catch(Exception&)
190
0
        {
191
0
        }
192
0
    }
193
0
    else
194
0
        m_xMoveOperations   = _rxCursor;
195
196
0
    m_xBookmarkOperations.set(m_xMoveOperations, css::uno::UNO_QUERY);
197
0
    m_xColumnsSupplier.set(m_xMoveOperations, css::uno::UNO_QUERY);
198
0
    m_xPropertyAccess.set(m_xMoveOperations, css::uno::UNO_QUERY);
199
200
0
    if ( !m_xMoveOperations.is() || !m_xBookmarkOperations.is() || !m_xColumnsSupplier.is() || !m_xPropertyAccess.is() )
201
0
    {   // all or nothing !!
202
0
        m_xMoveOperations = nullptr;
203
0
        m_xBookmarkOperations = nullptr;
204
0
        m_xColumnsSupplier = nullptr;
205
0
    }
206
0
    else
207
0
        m_xGeneric = m_xMoveOperations.get();
208
0
}
209
210
CursorWrapper& CursorWrapper::operator=(const Reference< css::sdbc::XRowSet>& _rxCursor)
211
0
{
212
0
    m_xMoveOperations.set(_rxCursor);
213
0
    m_xBookmarkOperations.set(_rxCursor, UNO_QUERY);
214
0
    m_xColumnsSupplier.set(_rxCursor, UNO_QUERY);
215
0
    if (!m_xMoveOperations.is() || !m_xBookmarkOperations.is() || !m_xColumnsSupplier.is())
216
0
    {   // all or nothing !!
217
0
        m_xMoveOperations = nullptr;
218
0
        m_xBookmarkOperations = nullptr;
219
0
        m_xColumnsSupplier = nullptr;
220
0
    }
221
0
    return *this;
222
0
}
223
224
FmXDisposeListener::~FmXDisposeListener()
225
0
{
226
0
    setAdapter(nullptr);
227
0
}
228
229
void FmXDisposeListener::setAdapter(FmXDisposeMultiplexer* pAdapter)
230
0
{
231
0
    std::scoped_lock aGuard(m_aMutex);
232
0
    m_pAdapter = pAdapter;
233
0
}
234
235
FmXDisposeMultiplexer::FmXDisposeMultiplexer(FmXDisposeListener* _pListener, const Reference< css::lang::XComponent>& _rxObject)
236
0
    :m_xObject(_rxObject)
237
0
    ,m_pListener(_pListener)
238
0
{
239
0
    m_pListener->setAdapter(this);
240
241
0
    if (m_xObject.is())
242
0
        m_xObject->addEventListener(this);
243
0
}
244
245
FmXDisposeMultiplexer::~FmXDisposeMultiplexer()
246
0
{
247
0
}
248
249
// css::lang::XEventListener
250
251
void FmXDisposeMultiplexer::disposing(const css::lang::EventObject& /*Source*/)
252
0
{
253
0
    Reference< css::lang::XEventListener> xPreventDelete(this);
254
255
0
    if (m_pListener)
256
0
    {
257
0
        m_pListener->disposing(0);
258
0
        m_pListener->setAdapter(nullptr);
259
0
        m_pListener = nullptr;
260
0
    }
261
0
    m_xObject = nullptr;
262
0
}
263
264
265
void FmXDisposeMultiplexer::dispose()
266
0
{
267
0
    if (m_xObject.is())
268
0
    {
269
0
        Reference< css::lang::XEventListener> xPreventDelete(this);
270
271
0
        m_xObject->removeEventListener(this);
272
0
        m_xObject = nullptr;
273
274
0
        m_pListener->setAdapter(nullptr);
275
0
        m_pListener = nullptr;
276
0
    }
277
0
}
278
279
280
SdrObjKind getControlTypeByObject(const Reference< css::lang::XServiceInfo>& _rxObject)
281
0
{
282
    // ask for the persistent service name
283
0
    Reference< css::io::XPersistObject> xPersistence(_rxObject, UNO_QUERY);
284
0
    DBG_ASSERT(xPersistence.is(), "::getControlTypeByObject : argument should be a css::io::XPersistObject !");
285
0
    if (!xPersistence.is())
286
0
        return SdrObjKind::FormControl;
287
288
0
    OUString sPersistentServiceName = xPersistence->getServiceName();
289
0
    if (sPersistentServiceName == FM_COMPONENT_EDIT)   // 5.0-Name
290
0
    {
291
        // may be a simple edit field or a formatted field, dependent of the supported services
292
0
        if (_rxObject->supportsService(FM_SUN_COMPONENT_FORMATTEDFIELD))
293
0
            return SdrObjKind::FormFormattedField;
294
0
        return SdrObjKind::FormEdit;
295
0
    }
296
0
    if (sPersistentServiceName == FM_COMPONENT_TEXTFIELD)
297
0
        return SdrObjKind::FormEdit;
298
0
    if (sPersistentServiceName == FM_COMPONENT_COMMANDBUTTON)
299
0
        return SdrObjKind::FormButton;
300
0
    if (sPersistentServiceName == FM_COMPONENT_FIXEDTEXT)
301
0
        return SdrObjKind::FormFixedText;
302
0
    if (sPersistentServiceName == FM_COMPONENT_LISTBOX)
303
0
        return SdrObjKind::FormListbox;
304
0
    if (sPersistentServiceName == FM_COMPONENT_CHECKBOX)
305
0
        return SdrObjKind::FormCheckbox;
306
0
    if (sPersistentServiceName == FM_COMPONENT_RADIOBUTTON)
307
0
        return SdrObjKind::FormRadioButton;
308
0
    if (sPersistentServiceName == FM_COMPONENT_GROUPBOX)
309
0
        return SdrObjKind::FormGroupBox;
310
0
    if (sPersistentServiceName == FM_COMPONENT_COMBOBOX)
311
0
        return SdrObjKind::FormCombobox;
312
0
    if (sPersistentServiceName == FM_COMPONENT_GRID)   // 5.0-Name
313
0
        return SdrObjKind::FormGrid;
314
0
    if (sPersistentServiceName == FM_COMPONENT_GRIDCONTROL)
315
0
        return SdrObjKind::FormGrid;
316
0
    if (sPersistentServiceName == FM_COMPONENT_IMAGEBUTTON)
317
0
        return SdrObjKind::FormImageButton;
318
0
    if (sPersistentServiceName == FM_COMPONENT_FILECONTROL)
319
0
        return SdrObjKind::FormFileControl;
320
0
    if (sPersistentServiceName == FM_COMPONENT_DATEFIELD)
321
0
        return SdrObjKind::FormDateField;
322
0
    if (sPersistentServiceName == FM_COMPONENT_TIMEFIELD)
323
0
        return SdrObjKind::FormTimeField;
324
0
    if (sPersistentServiceName == FM_COMPONENT_NUMERICFIELD)
325
0
        return SdrObjKind::FormNumericField;
326
0
    if (sPersistentServiceName == FM_COMPONENT_CURRENCYFIELD)
327
0
        return SdrObjKind::FormCurrencyField;
328
0
    if (sPersistentServiceName == FM_COMPONENT_PATTERNFIELD)
329
0
        return SdrObjKind::FormPatternField;
330
0
    if (sPersistentServiceName == FM_COMPONENT_HIDDEN) // 5.0-Name
331
0
        return SdrObjKind::FormHidden;
332
0
    if (sPersistentServiceName == FM_COMPONENT_HIDDENCONTROL)
333
0
        return SdrObjKind::FormHidden;
334
0
    if (sPersistentServiceName == FM_COMPONENT_IMAGECONTROL)
335
0
        return SdrObjKind::FormImageControl;
336
0
    if (sPersistentServiceName == FM_COMPONENT_FORMATTEDFIELD)
337
0
    {
338
0
        OSL_FAIL("::getControlTypeByObject : suspicious persistent service name (formatted field) !");
339
            // objects with that service name should exist as they aren't compatible with older versions
340
0
        return SdrObjKind::FormFormattedField;
341
0
    }
342
0
    if ( sPersistentServiceName == FM_SUN_COMPONENT_SCROLLBAR )
343
0
        return SdrObjKind::FormScrollbar;
344
0
    if ( sPersistentServiceName == FM_SUN_COMPONENT_SPINBUTTON )
345
0
        return SdrObjKind::FormSpinButton;
346
0
    if ( sPersistentServiceName == FM_SUN_COMPONENT_NAVIGATIONBAR )
347
0
        return SdrObjKind::FormNavigationBar;
348
349
0
    OSL_FAIL("::getControlTypeByObject : unknown object type !");
350
0
    return SdrObjKind::FormControl;
351
0
}
352
353
354
bool isRowSetAlive(const Reference< XInterface >& _rxRowSet)
355
0
{
356
0
    bool bIsAlive = false;
357
0
    Reference< css::sdbcx::XColumnsSupplier> xSupplyCols(_rxRowSet, UNO_QUERY);
358
0
    Reference< css::container::XIndexAccess> xCols;
359
0
    if (xSupplyCols.is())
360
0
        xCols.set(xSupplyCols->getColumns(), UNO_QUERY);
361
0
    if (xCols.is() && (xCols->getCount() > 0))
362
0
        bIsAlive = true;
363
364
0
    return bIsAlive;
365
0
}
366
367
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */