Bug Summary

File:home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx
Warning:line 3463, column 5
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name formcontroller.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SVXCORE_DLLIMPLEMENTATION -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/epoxy/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/pdfium/public -D COMPONENT_BUILD -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/svx/inc -I /home/maarten/src/libreoffice/core/svx/source/inc -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/svx/sdi -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx

/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx

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 <fmcontrolbordermanager.hxx>
22#include <fmcontrollayout.hxx>
23#include <formcontroller.hxx>
24#include <formfeaturedispatcher.hxx>
25#include <fmdocumentclassification.hxx>
26#include <formcontrolling.hxx>
27#include <fmprop.hxx>
28#include <svx/dialmgr.hxx>
29#include <svx/strings.hrc>
30#include <fmservs.hxx>
31#include <svx/fmtools.hxx>
32#include <fmurl.hxx>
33
34#include <com/sun/star/awt/FocusChangeReason.hpp>
35#include <com/sun/star/awt/XCheckBox.hpp>
36#include <com/sun/star/awt/XComboBox.hpp>
37#include <com/sun/star/awt/XListBox.hpp>
38#include <com/sun/star/awt/XVclWindowPeer.hpp>
39#include <com/sun/star/awt/TabController.hpp>
40#include <com/sun/star/beans/PropertyAttribute.hpp>
41#include <com/sun/star/container/XIdentifierReplace.hpp>
42#include <com/sun/star/form/TabulatorCycle.hpp>
43#include <com/sun/star/form/validation/XValidatableFormComponent.hpp>
44#include <com/sun/star/form/XBoundComponent.hpp>
45#include <com/sun/star/form/XBoundControl.hpp>
46#include <com/sun/star/form/XGridControl.hpp>
47#include <com/sun/star/form/XLoadable.hpp>
48#include <com/sun/star/form/XReset.hpp>
49#include <com/sun/star/form/control/FilterControl.hpp>
50#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
51#include <com/sun/star/lang/XMultiServiceFactory.hpp>
52#include <com/sun/star/lang/NoSupportException.hpp>
53#include <com/sun/star/sdb/ParametersRequest.hpp>
54#include <com/sun/star/sdb/RowChangeAction.hpp>
55#include <com/sun/star/sdb/SQLFilterOperator.hpp>
56#include <com/sun/star/sdb/XInteractionSupplyParameters.hpp>
57#include <com/sun/star/sdbc/ColumnValue.hpp>
58#include <com/sun/star/task/InteractionHandler.hpp>
59#include <com/sun/star/form/runtime/FormOperations.hpp>
60#include <com/sun/star/form/runtime/FormFeature.hpp>
61#include <com/sun/star/container/XContainer.hpp>
62#include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
63#include <com/sun/star/util/NumberFormatter.hpp>
64#include <com/sun/star/sdb/SQLContext.hpp>
65#include <com/sun/star/sdb/XColumn.hpp>
66
67#include <comphelper/enumhelper.hxx>
68#include <comphelper/interaction.hxx>
69#include <comphelper/processfactory.hxx>
70#include <comphelper/property.hxx>
71#include <comphelper/sequence.hxx>
72#include <comphelper/flagguard.hxx>
73#include <comphelper/types.hxx>
74#include <cppuhelper/supportsservice.hxx>
75#include <connectivity/IParseContext.hxx>
76#include <connectivity/dbtools.hxx>
77#include <connectivity/sqlparse.hxx>
78#include <toolkit/controls/unocontrol.hxx>
79#include <toolkit/helper/vclunohelper.hxx>
80#include <tools/debug.hxx>
81#include <tools/diagnose_ex.h>
82#include <unotools/localedatawrapper.hxx>
83#include <vcl/svapp.hxx>
84#include <vcl/settings.hxx>
85#include <vcl/window.hxx>
86#include <o3tl/safeint.hxx>
87#include <osl/mutex.hxx>
88#include <sal/log.hxx>
89
90#include <algorithm>
91#include <iterator>
92
93using namespace ::com::sun::star;
94using namespace ::comphelper;
95using namespace ::connectivity;
96using namespace ::dbtools;
97
98
99css::uno::Reference< css::uno::XInterface >
100 FormController_NewInstance_Impl( const css::uno::Reference< css::lang::XMultiServiceFactory > & _rxORB )
101{
102 return *( new ::svxform::FormController( comphelper::getComponentContext(_rxORB) ) );
103}
104
105namespace svxform
106{
107
108 using ::com::sun::star::sdb::XColumn;
109 using ::com::sun::star::awt::XControl;
110 using ::com::sun::star::awt::TabController;
111 using ::com::sun::star::awt::XToolkit;
112 using ::com::sun::star::awt::XWindowPeer;
113 using ::com::sun::star::form::XGrid;
114 using ::com::sun::star::beans::XPropertySet;
115 using ::com::sun::star::uno::UNO_SET_THROW;
116 using ::com::sun::star::uno::UNO_QUERY_THROW;
117 using ::com::sun::star::container::XIndexAccess;
118 using ::com::sun::star::uno::Exception;
119 using ::com::sun::star::uno::XInterface;
120 using ::com::sun::star::uno::UNO_QUERY;
121 using ::com::sun::star::uno::Sequence;
122 using ::com::sun::star::uno::Reference;
123 using ::com::sun::star::beans::XPropertySetInfo;
124 using ::com::sun::star::beans::PropertyValue;
125 using ::com::sun::star::lang::IndexOutOfBoundsException;
126 using ::com::sun::star::sdb::XInteractionSupplyParameters;
127 using ::com::sun::star::awt::XTextComponent;
128 using ::com::sun::star::awt::XTextListener;
129 using ::com::sun::star::uno::Any;
130 using ::com::sun::star::frame::XDispatch;
131 using ::com::sun::star::lang::XMultiServiceFactory;
132 using ::com::sun::star::uno::Type;
133 using ::com::sun::star::lang::IllegalArgumentException;
134 using ::com::sun::star::sdbc::XConnection;
135 using ::com::sun::star::sdbc::XRowSet;
136 using ::com::sun::star::sdbc::XDatabaseMetaData;
137 using ::com::sun::star::util::XNumberFormatsSupplier;
138 using ::com::sun::star::util::NumberFormatter;
139 using ::com::sun::star::util::XNumberFormatter;
140 using ::com::sun::star::sdbcx::XColumnsSupplier;
141 using ::com::sun::star::container::XNameAccess;
142 using ::com::sun::star::lang::EventObject;
143 using ::com::sun::star::beans::Property;
144 using ::com::sun::star::container::XEnumeration;
145 using ::com::sun::star::form::XFormComponent;
146 using ::com::sun::star::form::runtime::XFormOperations;
147 using ::com::sun::star::form::runtime::FilterEvent;
148 using ::com::sun::star::form::runtime::XFilterControllerListener;
149 using ::com::sun::star::awt::XControlContainer;
150 using ::com::sun::star::container::XIdentifierReplace;
151 using ::com::sun::star::form::XFormControllerListener;
152 using ::com::sun::star::awt::XWindow;
153 using ::com::sun::star::sdbc::XResultSet;
154 using ::com::sun::star::awt::XControlModel;
155 using ::com::sun::star::awt::XTabControllerModel;
156 using ::com::sun::star::beans::PropertyChangeEvent;
157 using ::com::sun::star::form::validation::XValidatableFormComponent;
158 using ::com::sun::star::form::XLoadable;
159 using ::com::sun::star::form::XBoundControl;
160 using ::com::sun::star::beans::XPropertyChangeListener;
161 using ::com::sun::star::awt::TextEvent;
162 using ::com::sun::star::form::XBoundComponent;
163 using ::com::sun::star::awt::XCheckBox;
164 using ::com::sun::star::awt::XComboBox;
165 using ::com::sun::star::awt::XListBox;
166 using ::com::sun::star::awt::ItemEvent;
167 using ::com::sun::star::util::XModifyListener;
168 using ::com::sun::star::form::XReset;
169 using ::com::sun::star::frame::XDispatchProviderInterception;
170 using ::com::sun::star::form::XGridControl;
171 using ::com::sun::star::awt::XVclWindowPeer;
172 using ::com::sun::star::form::validation::XValidator;
173 using ::com::sun::star::awt::FocusEvent;
174 using ::com::sun::star::sdb::SQLContext;
175 using ::com::sun::star::container::XChild;
176 using ::com::sun::star::form::TabulatorCycle_RECORDS;
177 using ::com::sun::star::container::ContainerEvent;
178 using ::com::sun::star::lang::DisposedException;
179 using ::com::sun::star::lang::Locale;
180 using ::com::sun::star::lang::NoSupportException;
181 using ::com::sun::star::sdb::RowChangeEvent;
182 using ::com::sun::star::frame::XStatusListener;
183 using ::com::sun::star::frame::XDispatchProviderInterceptor;
184 using ::com::sun::star::sdb::SQLErrorEvent;
185 using ::com::sun::star::form::DatabaseParameterEvent;
186 using ::com::sun::star::sdb::ParametersRequest;
187 using ::com::sun::star::task::XInteractionRequest;
188 using ::com::sun::star::util::URL;
189 using ::com::sun::star::frame::FeatureStateEvent;
190 using ::com::sun::star::form::runtime::XFormControllerContext;
191 using ::com::sun::star::task::InteractionHandler;
192 using ::com::sun::star::task::XInteractionHandler;
193 using ::com::sun::star::form::runtime::FormOperations;
194 using ::com::sun::star::container::XContainer;
195 using ::com::sun::star::sdbc::SQLWarning;
196
197 namespace ColumnValue = ::com::sun::star::sdbc::ColumnValue;
198 namespace PropertyAttribute = ::com::sun::star::beans::PropertyAttribute;
199 namespace FocusChangeReason = ::com::sun::star::awt::FocusChangeReason;
200 namespace RowChangeAction = ::com::sun::star::sdb::RowChangeAction;
201 namespace FormFeature = ::com::sun::star::form::runtime::FormFeature;
202
203namespace {
204
205struct ColumnInfo
206{
207 // information about the column itself
208 Reference< XColumn > xColumn;
209 sal_Int32 nNullable;
210 bool bAutoIncrement;
211 bool bReadOnly;
212 OUString sName;
213
214 // information about the control(s) bound to this column
215
216 /// the first control which is bound to the given column, and which requires input
217 Reference< XControl > xFirstControlWithInputRequired;
218 /** the first grid control which contains a column which is bound to the given database column, and requires
219 input
220 */
221 Reference< XGrid > xFirstGridWithInputRequiredColumn;
222 /** if xFirstControlWithInputRequired is a grid control, then nRequiredGridColumn specifies the position
223 of the grid column which is actually bound
224 */
225 sal_Int32 nRequiredGridColumn;
226
227 ColumnInfo()
228 :xColumn()
229 ,nNullable( ColumnValue::NULLABLE_UNKNOWN )
230 ,bAutoIncrement( false )
231 ,bReadOnly( false )
232 ,sName()
233 ,xFirstControlWithInputRequired()
234 ,xFirstGridWithInputRequiredColumn()
235 ,nRequiredGridColumn( -1 )
236 {
237 }
238};
239
240}
241
242class ColumnInfoCache
243{
244public:
245 explicit ColumnInfoCache( const Reference< XColumnsSupplier >& _rxColSupplier );
246
247 size_t getColumnCount() const { return m_aColumns.size(); }
248 const ColumnInfo& getColumnInfo( size_t _pos );
249
250 bool controlsInitialized() const { return m_bControlsInitialized; }
251 void initializeControls( const Sequence< Reference< XControl > >& _rControls );
252 void deinitializeControls();
253
254private:
255 typedef ::std::vector< ColumnInfo > ColumnInfos;
256 ColumnInfos m_aColumns;
257 bool m_bControlsInitialized;
258};
259
260
261ColumnInfoCache::ColumnInfoCache( const Reference< XColumnsSupplier >& _rxColSupplier )
262 :m_aColumns()
263 ,m_bControlsInitialized( false )
264{
265 try
266 {
267 m_aColumns.clear();
268
269 Reference< XIndexAccess > xColumns( _rxColSupplier->getColumns(), UNO_QUERY_THROW );
270 sal_Int32 nColumnCount = xColumns->getCount();
271 m_aColumns.reserve( nColumnCount );
272
273 Reference< XPropertySet > xColumnProps;
274 for ( sal_Int32 i = 0; i < nColumnCount; ++i )
275 {
276 ColumnInfo aColInfo;
277 aColInfo.xColumn.set( xColumns->getByIndex(i), UNO_QUERY_THROW );
278
279 xColumnProps.set( aColInfo.xColumn, UNO_QUERY_THROW );
280 OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_ISNULLABLE ) >>= aColInfo.nNullable )do { if (!(xColumnProps->getPropertyValue( "IsNullable" ) >>=
aColInfo.nNullable)) do { if (true && (!(0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "280" ": "), "OSL_ASSERT: %s", "0"); } } while (false); }
while (0)
;
281 OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_AUTOINCREMENT ) >>= aColInfo.bAutoIncrement )do { if (!(xColumnProps->getPropertyValue( "IsAutoIncrement"
) >>= aColInfo.bAutoIncrement)) do { if (true &&
(!(0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), (
"legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "281" ": "), "OSL_ASSERT: %s", "0"); } } while (false); }
while (0)
;
282 OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_NAME ) >>= aColInfo.sName )do { if (!(xColumnProps->getPropertyValue( "Name" ) >>=
aColInfo.sName)) do { if (true && (!(0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "282" ": "), "OSL_ASSERT: %s", "0"); } } while (false); }
while (0)
;
283 OSL_VERIFY( xColumnProps->getPropertyValue( FM_PROP_ISREADONLY ) >>= aColInfo.bReadOnly )do { if (!(xColumnProps->getPropertyValue( "IsReadOnly" ) >>=
aColInfo.bReadOnly)) do { if (true && (!(0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "283" ": "), "OSL_ASSERT: %s", "0"); } } while (false); }
while (0)
;
284
285 m_aColumns.push_back( aColInfo );
286 }
287 }
288 catch( const Exception& )
289 {
290 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "290" ": ", "svx" );
;
291 }
292}
293
294
295namespace
296{
297 bool lcl_isBoundTo( const Reference< XPropertySet >& _rxControlModel, const Reference< XInterface >& _rxNormDBField )
298 {
299 Reference< XInterface > xNormBoundField( _rxControlModel->getPropertyValue( FM_PROP_BOUNDFIELD"BoundField" ), UNO_QUERY );
300 return ( xNormBoundField == _rxNormDBField );
301 }
302
303 bool lcl_isInputRequired( const Reference< XPropertySet >& _rxControlModel )
304 {
305 bool bInputRequired = false;
306 OSL_VERIFY( _rxControlModel->getPropertyValue( FM_PROP_INPUT_REQUIRED ) >>= bInputRequired )do { if (!(_rxControlModel->getPropertyValue( "InputRequired"
) >>= bInputRequired)) do { if (true && (!(0))
) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "306" ": "), "OSL_ASSERT: %s", "0"); } } while (false); }
while (0)
;
307 return bInputRequired;
308 }
309
310 void lcl_resetColumnControlInfo( ColumnInfo& _rColInfo )
311 {
312 _rColInfo.xFirstControlWithInputRequired.clear();
313 _rColInfo.xFirstGridWithInputRequiredColumn.clear();
314 _rColInfo.nRequiredGridColumn = -1;
315 }
316}
317
318
319void ColumnInfoCache::deinitializeControls()
320{
321 for (auto& rCol : m_aColumns)
322 {
323 lcl_resetColumnControlInfo( rCol );
324 }
325 m_bControlsInitialized = false;
326}
327
328
329void ColumnInfoCache::initializeControls( const Sequence< Reference< XControl > >& _rControls )
330{
331 try
332 {
333 // for every of our known columns, find the controls which are bound to this column
334 for (auto& rCol : m_aColumns)
335 {
336 OSL_ENSURE( !rCol.xFirstControlWithInputRequired.is() && !rCol.xFirstGridWithInputRequiredColumn.is()do { if (true && (!(!rCol.xFirstControlWithInputRequired
.is() && !rCol.xFirstGridWithInputRequiredColumn.is()
&& ( rCol.nRequiredGridColumn == -1 )))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "337" ": "), "%s", "ColumnInfoCache::initializeControls: called me twice?"
); } } while (false)
337 && ( rCol.nRequiredGridColumn == -1 ), "ColumnInfoCache::initializeControls: called me twice?" )do { if (true && (!(!rCol.xFirstControlWithInputRequired
.is() && !rCol.xFirstGridWithInputRequiredColumn.is()
&& ( rCol.nRequiredGridColumn == -1 )))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "337" ": "), "%s", "ColumnInfoCache::initializeControls: called me twice?"
); } } while (false)
;
338
339 lcl_resetColumnControlInfo( rCol );
340
341 Reference< XInterface > xNormColumn( rCol.xColumn, UNO_QUERY_THROW );
342
343 const Reference< XControl >* pControl( _rControls.getConstArray() );
344 const Reference< XControl >* pControlEnd( pControl + _rControls.getLength() );
345 for ( ; pControl != pControlEnd; ++pControl )
346 {
347 if ( !pControl->is() )
348 continue;
349
350 Reference< XPropertySet > xModel( (*pControl)->getModel(), UNO_QUERY_THROW );
351 Reference< XPropertySetInfo > xModelPSI( xModel->getPropertySetInfo(), UNO_SET_THROW );
352
353 // special handling for grid controls
354 Reference< XGrid > xGrid( *pControl, UNO_QUERY );
355 if ( xGrid.is() )
356 {
357 Reference< XIndexAccess > xGridColAccess( xModel, UNO_QUERY_THROW );
358 sal_Int32 gridColCount = xGridColAccess->getCount();
359 sal_Int32 gridCol = 0;
360 for ( gridCol = 0; gridCol < gridColCount; ++gridCol )
361 {
362 Reference< XPropertySet > xGridColumnModel( xGridColAccess->getByIndex( gridCol ), UNO_QUERY_THROW );
363
364 if ( !lcl_isBoundTo( xGridColumnModel, xNormColumn )
365 || !lcl_isInputRequired( xGridColumnModel )
366 )
367 continue; // with next grid column
368
369 break;
370 }
371
372 if ( gridCol < gridColCount )
373 {
374 // found a grid column which is bound to the given
375 rCol.xFirstGridWithInputRequiredColumn = xGrid;
376 rCol.nRequiredGridColumn = gridCol;
377 break;
378 }
379
380 continue; // with next control
381 }
382
383 if ( !xModelPSI->hasPropertyByName( FM_PROP_BOUNDFIELD"BoundField" )
384 || !lcl_isBoundTo( xModel, xNormColumn )
385 || !lcl_isInputRequired( xModel )
386 )
387 continue; // with next control
388
389 break;
390 }
391
392 if ( pControl == pControlEnd )
393 // did not find a control which is bound to this particular column, and for which the input is required
394 continue; // with next DB column
395
396 rCol.xFirstControlWithInputRequired = *pControl;
397 }
398 }
399 catch( const Exception& )
400 {
401 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "401" ": ", "svx" );
;
402 }
403
404 m_bControlsInitialized = true;
405}
406
407
408const ColumnInfo& ColumnInfoCache::getColumnInfo( size_t _pos )
409{
410 if ( _pos >= m_aColumns.size() )
411 throw IndexOutOfBoundsException();
412
413 return m_aColumns[ _pos ];
414}
415
416namespace {
417
418class OParameterContinuation : public OInteraction< XInteractionSupplyParameters >
419{
420 Sequence< PropertyValue > m_aValues;
421
422public:
423 OParameterContinuation() { }
424
425 const Sequence< PropertyValue >& getValues() const { return m_aValues; }
426
427// XInteractionSupplyParameters
428 virtual void SAL_CALL setParameters( const Sequence< PropertyValue >& _rValues ) override;
429};
430
431}
432
433void SAL_CALL OParameterContinuation::setParameters( const Sequence< PropertyValue >& _rValues )
434{
435 m_aValues = _rValues;
436}
437
438
439// FmXAutoControl
440
441struct FmFieldInfo
442{
443 OUString aFieldName;
444 Reference< XPropertySet > xField;
445 Reference< XTextComponent > xText;
446
447 FmFieldInfo(const Reference< XPropertySet >& _xField, const Reference< XTextComponent >& _xText)
448 :xField(_xField)
449 ,xText(_xText)
450 {xField->getPropertyValue(FM_PROP_NAME"Name") >>= aFieldName;}
451};
452
453namespace {
454
455class FmXAutoControl: public UnoControl
456
457{
458public:
459 FmXAutoControl() :UnoControl()
460 {
461 }
462
463 virtual OUString GetComponentServiceName() override {return "Edit";}
464 virtual void SAL_CALL createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer ) override;
465
466protected:
467 virtual void ImplSetPeerProperty( const OUString& rPropName, const Any& rVal ) override;
468};
469
470}
471
472void FmXAutoControl::createPeer( const Reference< XToolkit > & rxToolkit, const Reference< XWindowPeer > & rParentPeer )
473{
474 UnoControl::createPeer( rxToolkit, rParentPeer );
475
476 Reference< XTextComponent > xText(getPeer() , UNO_QUERY);
477 if (xText.is())
478 {
479 xText->setText(SvxResId(RID_STR_AUTOFIELDreinterpret_cast<char const *>("RID_STR_AUTOFIELD" "\004"
u8"<AutoField>")
));
480 xText->setEditable(false);
481 }
482}
483
484
485void FmXAutoControl::ImplSetPeerProperty( const OUString& rPropName, const Any& rVal )
486{
487 // these properties are ignored
488 if (rPropName == FM_PROP_TEXT"Text")
489 return;
490
491 UnoControl::ImplSetPeerProperty( rPropName, rVal );
492}
493
494
495IMPL_LINK_NOARG( FormController, OnActivateTabOrder, Timer*, void )void FormController::LinkStubOnActivateTabOrder(void * instance
, Timer* data) { return static_cast<FormController *>(instance
)->OnActivateTabOrder(data); } void FormController::OnActivateTabOrder
(__attribute__ ((unused)) Timer*)
496{
497 activateTabOrder();
498}
499
500namespace {
501
502struct UpdateAllListeners
503{
504 bool operator()( const Reference< XDispatch >& _rxDispatcher ) const
505 {
506 static_cast< svx::OSingleFeatureDispatcher* >( _rxDispatcher.get() )->updateAllListeners();
507 // the return is a dummy only so we can use this struct in a lambda expression
508 return true;
509 }
510};
511
512}
513
514IMPL_LINK_NOARG( FormController, OnInvalidateFeatures, Timer*, void )void FormController::LinkStubOnInvalidateFeatures(void * instance
, Timer* data) { return static_cast<FormController *>(instance
)->OnInvalidateFeatures(data); } void FormController::OnInvalidateFeatures
(__attribute__ ((unused)) Timer*)
515{
516 ::osl::MutexGuard aGuard( m_aMutex );
517 for (const auto& rFeature : m_aInvalidFeatures)
518 {
519 DispatcherContainer::const_iterator aDispatcherPos = m_aFeatureDispatchers.find( rFeature );
520 if ( aDispatcherPos != m_aFeatureDispatchers.end() )
521 {
522 // TODO: for the real and actual listener notifications, we should release
523 // our mutex
524 UpdateAllListeners( )( aDispatcherPos->second );
525 }
526 }
527}
528
529FormController::FormController(const Reference< css::uno::XComponentContext > & _rxORB )
530 :FormController_BASE( m_aMutex )
531 ,OPropertySetHelper( FormController_BASE::rBHelper )
532 ,OSQLParserClient( _rxORB )
533 ,m_xComponentContext( _rxORB )
534 ,m_aActivateListeners(m_aMutex)
535 ,m_aModifyListeners(m_aMutex)
536 ,m_aErrorListeners(m_aMutex)
537 ,m_aDeleteListeners(m_aMutex)
538 ,m_aRowSetApproveListeners(m_aMutex)
539 ,m_aParameterListeners(m_aMutex)
540 ,m_aFilterListeners(m_aMutex)
541 ,m_xFormOperations()
542 ,m_aMode( OUString( "DataMode" ) )
543 ,m_aLoadEvent( LINK( this, FormController, OnLoad )::tools::detail::makeLink( ::tools::detail::castTo<FormController
*>(this), &FormController::LinkStubOnLoad)
)
544 ,m_aToggleEvent( LINK( this, FormController, OnToggleAutoFields )::tools::detail::makeLink( ::tools::detail::castTo<FormController
*>(this), &FormController::LinkStubOnToggleAutoFields
)
)
545 ,m_aActivationEvent( LINK( this, FormController, OnActivated )::tools::detail::makeLink( ::tools::detail::castTo<FormController
*>(this), &FormController::LinkStubOnActivated)
)
546 ,m_aDeactivationEvent( LINK( this, FormController, OnDeactivated )::tools::detail::makeLink( ::tools::detail::castTo<FormController
*>(this), &FormController::LinkStubOnDeactivated)
)
547 ,m_nCurrentFilterPosition(-1)
548 ,m_bCurrentRecordModified(false)
549 ,m_bCurrentRecordNew(false)
550 ,m_bLocked(false)
551 ,m_bDBConnection(false)
552 ,m_bCycle(false)
553 ,m_bCanInsert(false)
554 ,m_bCanUpdate(false)
555 ,m_bCommitLock(false)
556 ,m_bModified(false)
557 ,m_bControlsSorted(false)
558 ,m_bFiltering(false)
559 ,m_bAttachEvents(true)
560 ,m_bDetachEvents(true)
561 ,m_bAttemptedHandlerCreation( false )
562 ,m_bSuspendFilterTextListening( false )
563{
564
565 osl_atomic_increment(&m_refCount)__sync_add_and_fetch((&m_refCount), 1);
566 {
567 m_xTabController = TabController::create( m_xComponentContext );
568 m_xAggregate.set( m_xTabController, UNO_QUERY_THROW );
569 m_xAggregate->setDelegator( *this );
570 }
571 osl_atomic_decrement(&m_refCount)__sync_sub_and_fetch((&m_refCount), 1);
572
573 m_aTabActivationIdle.SetPriority( TaskPriority::LOWEST );
574 m_aTabActivationIdle.SetInvokeHandler( LINK( this, FormController, OnActivateTabOrder )::tools::detail::makeLink( ::tools::detail::castTo<FormController
*>(this), &FormController::LinkStubOnActivateTabOrder
)
);
575
576 m_aFeatureInvalidationTimer.SetTimeout( 200 );
577 m_aFeatureInvalidationTimer.SetInvokeHandler( LINK( this, FormController, OnInvalidateFeatures )::tools::detail::makeLink( ::tools::detail::castTo<FormController
*>(this), &FormController::LinkStubOnInvalidateFeatures
)
);
578}
579
580
581FormController::~FormController()
582{
583 {
584 ::osl::MutexGuard aGuard( m_aMutex );
585
586 m_aLoadEvent.CancelPendingCall();
587 m_aToggleEvent.CancelPendingCall();
588 m_aActivationEvent.CancelPendingCall();
589 m_aDeactivationEvent.CancelPendingCall();
590
591 if ( m_aTabActivationIdle.IsActive() )
592 m_aTabActivationIdle.Stop();
593 }
594
595 if ( m_aFeatureInvalidationTimer.IsActive() )
596 m_aFeatureInvalidationTimer.Stop();
597
598 disposeAllFeaturesAndDispatchers();
599
600 if ( m_xFormOperations.is() )
601 m_xFormOperations->dispose();
602 m_xFormOperations.clear();
603
604 // release of aggregation
605 if ( m_xAggregate.is() )
606 {
607 m_xAggregate->setDelegator( nullptr );
608 m_xAggregate.clear();
609 }
610}
611
612
613void SAL_CALL FormController::acquire() throw ()
614{
615 FormController_BASE::acquire();
616}
617
618
619void SAL_CALL FormController::release() throw ()
620{
621 FormController_BASE::release();
622}
623
624
625Any SAL_CALL FormController::queryInterface( const Type& _rType )
626{
627 Any aRet = FormController_BASE::queryInterface( _rType );
628 if ( !aRet.hasValue() )
629 aRet = OPropertySetHelper::queryInterface( _rType );
630 if ( !aRet.hasValue() )
631 aRet = m_xAggregate->queryAggregation( _rType );
632 return aRet;
633}
634
635
636Sequence< sal_Int8 > SAL_CALL FormController::getImplementationId()
637{
638 return css::uno::Sequence<sal_Int8>();
639}
640
641Sequence< Type > SAL_CALL FormController::getTypes( )
642{
643 return comphelper::concatSequences(
644 FormController_BASE::getTypes(),
645 ::cppu::OPropertySetHelper::getTypes()
646 );
647}
648
649// XServiceInfo
650sal_Bool SAL_CALL FormController::supportsService(const OUString& ServiceName)
651{
652 return cppu::supportsService(this, ServiceName);
653}
654
655OUString SAL_CALL FormController::getImplementationName()
656{
657 return "org.openoffice.comp.svx.FormController";
658}
659
660Sequence< OUString> SAL_CALL FormController::getSupportedServiceNames()
661{
662 // service names which are supported only, but cannot be used to created an
663 // instance at a service factory
664 Sequence<OUString> aNonCreatableServiceNames { "com.sun.star.form.FormControllerDispatcher" };
665
666 // services which can be used to created an instance at a service factory
667 Sequence< OUString > aCreatableServiceNames( getSupportedServiceNames_Static() );
668 return ::comphelper::concatSequences( aCreatableServiceNames, aNonCreatableServiceNames );
669}
670
671
672sal_Bool SAL_CALL FormController::approveReset(const EventObject& /*rEvent*/)
673{
674 return true;
675}
676
677
678void SAL_CALL FormController::resetted(const EventObject& rEvent)
679{
680 ::osl::MutexGuard aGuard(m_aMutex);
681 if (getCurrentControl().is() && (getCurrentControl()->getModel() == rEvent.Source))
682 m_bModified = false;
683}
684
685
686Sequence< OUString> const & FormController::getSupportedServiceNames_Static()
687{
688 static Sequence< OUString> const aServices
689 {
690 "com.sun.star.form.runtime.FormController",
691 "com.sun.star.awt.control.TabController"
692 };
693 return aServices;
694}
695
696
697namespace
698{
699 struct ResetComponentText
700 {
701 void operator()( const Reference< XTextComponent >& _rxText )
702 {
703 _rxText->setText( OUString() );
704 }
705 };
706
707 struct RemoveComponentTextListener
708 {
709 explicit RemoveComponentTextListener( const Reference< XTextListener >& _rxListener )
710 :m_xListener( _rxListener )
711 {
712 }
713
714 void operator()( const Reference< XTextComponent >& _rxText )
715 {
716 _rxText->removeTextListener( m_xListener );
717 }
718
719 private:
720 Reference< XTextListener > m_xListener;
721 };
722}
723
724
725void FormController::impl_setTextOnAllFilter_throw()
726{
727 m_bSuspendFilterTextListening = true;
728 ::comphelper::FlagGuard aResetFlag( m_bSuspendFilterTextListening );
729
730 // reset the text for all controls
731 ::std::for_each( m_aFilterComponents.begin(), m_aFilterComponents.end(), ResetComponentText() );
732
733 if ( m_aFilterRows.empty() )
734 // nothing to do anymore
735 return;
736
737 if ( m_nCurrentFilterPosition < 0 )
738 return;
739
740 // set the text for all filters
741 OSL_ENSURE( m_aFilterRows.size() > o3tl::make_unsigned(m_nCurrentFilterPosition),do { if (true && (!(m_aFilterRows.size() > o3tl::make_unsigned
(m_nCurrentFilterPosition)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "742" ": "), "%s", "FormController::impl_setTextOnAllFilter_throw: m_nCurrentFilterPosition too big"
); } } while (false)
742 "FormController::impl_setTextOnAllFilter_throw: m_nCurrentFilterPosition too big" )do { if (true && (!(m_aFilterRows.size() > o3tl::make_unsigned
(m_nCurrentFilterPosition)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "742" ": "), "%s", "FormController::impl_setTextOnAllFilter_throw: m_nCurrentFilterPosition too big"
); } } while (false)
;
743
744 if ( o3tl::make_unsigned(m_nCurrentFilterPosition) < m_aFilterRows.size() )
745 {
746 FmFilterRow& rRow = m_aFilterRows[ m_nCurrentFilterPosition ];
747 for (const auto& rEntry : rRow)
748 {
749 rEntry.first->setText( rEntry.second );
750 }
751 }
752}
753// OPropertySetHelper
754
755sal_Bool FormController::convertFastPropertyValue( Any & /*rConvertedValue*/, Any & /*rOldValue*/,
756 sal_Int32 /*nHandle*/, const Any& /*rValue*/ )
757{
758 return false;
759}
760
761
762void FormController::setFastPropertyValue_NoBroadcast( sal_Int32 /*nHandle*/, const Any& /*rValue*/ )
763{
764}
765
766
767void FormController::getFastPropertyValue( Any& rValue, sal_Int32 nHandle ) const
768{
769 switch (nHandle)
770 {
771 case FM_ATTR_FILTER( 0 + 1 ):
772 {
773 OUStringBuffer aFilter;
774 Reference<XConnection> xConnection(getConnection(Reference< XRowSet>(m_xModelAsIndex, UNO_QUERY)));
775 if (xConnection.is())
776 {
777 Reference< XNumberFormatsSupplier> xFormatSupplier( getNumberFormats( xConnection, true ) );
778 Reference< XNumberFormatter> xFormatter = NumberFormatter::create(m_xComponentContext);
779 xFormatter->attachNumberFormatsSupplier(xFormatSupplier);
780
781 // now add the filter rows
782 try
783 {
784 for (const FmFilterRow& rRow : m_aFilterRows)
785 {
786 if ( rRow.empty() )
787 continue;
788
789 OUStringBuffer aRowFilter;
790 for ( FmFilterRow::const_iterator condition = rRow.begin(); condition != rRow.end(); ++condition )
791 {
792 // get the field of the controls map
793 Reference< XControl > xControl( condition->first, UNO_QUERY_THROW );
794 Reference< XPropertySet > xModelProps( xControl->getModel(), UNO_QUERY_THROW );
795 Reference< XPropertySet > xField( xModelProps->getPropertyValue( FM_PROP_BOUNDFIELD"BoundField" ), UNO_QUERY_THROW );
796
797 OUString sFilterValue( condition->second );
798
799 OUString sErrorMsg;
800 const std::unique_ptr< OSQLParseNode > pParseNode =
801 predicateTree( sErrorMsg, sFilterValue, xFormatter, xField );
802 OSL_ENSURE( pParseNode != nullptr, "FormController::getFastPropertyValue: could not parse the field value predicate!" )do { if (true && (!(pParseNode != nullptr))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "802" ": "), "%s", "FormController::getFastPropertyValue: could not parse the field value predicate!"
); } } while (false)
;
803 if ( pParseNode != nullptr )
804 {
805 OUString sCriteria;
806 // don't use a parse context here, we need it unlocalized
807 pParseNode->parseNodeToStr( sCriteria, xConnection );
808 if ( condition != rRow.begin() )
809 aRowFilter.append( " AND " );
810 aRowFilter.append( sCriteria );
811 }
812 }
813 if ( !aRowFilter.isEmpty() )
814 {
815 if ( !aFilter.isEmpty() )
816 aFilter.append( " OR " );
817
818 aFilter.append( "( " );
819 aFilter.append( aRowFilter.makeStringAndClear() );
820 aFilter.append( " )" );
821 }
822 }
823 }
824 catch( const Exception& )
825 {
826 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "826" ": ", "svx" );
;
827 aFilter.setLength(0);
828 }
829 }
830 rValue <<= aFilter.makeStringAndClear();
831 }
832 break;
833
834 case FM_ATTR_FORM_OPERATIONS( 0 + 2 ):
835 rValue <<= m_xFormOperations;
836 break;
837 }
838}
839
840
841Reference< XPropertySetInfo > FormController::getPropertySetInfo()
842{
843 static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
844 return xInfo;
845}
846
847
848void FormController::fillProperties(
849 Sequence< Property >& /* [out] */ _rProps,
850 Sequence< Property >& /* [out] */ /*_rAggregateProps*/
851 ) const
852{
853 _rProps.realloc(2);
854 sal_Int32 nPos = 0;
855 Property* pDesc = _rProps.getArray();
856
857 pDesc[nPos++] = Property(FM_PROP_FILTER"Filter", FM_ATTR_FILTER( 0 + 1 ),
858 cppu::UnoType<OUString>::get(),
859 PropertyAttribute::READONLY);
860 pDesc[nPos++] = Property(FM_PROP_FORM_OPERATIONS"FormOperations", FM_ATTR_FORM_OPERATIONS( 0 + 2 ),
861 cppu::UnoType<XFormOperations>::get(),
862 PropertyAttribute::READONLY);
863}
864
865
866::cppu::IPropertyArrayHelper& FormController::getInfoHelper()
867{
868 return *getArrayHelper();
869}
870
871// XFilterController
872
873void SAL_CALL FormController::addFilterControllerListener( const Reference< XFilterControllerListener >& Listener )
874{
875 m_aFilterListeners.addInterface( Listener );
876}
877
878
879void SAL_CALL FormController::removeFilterControllerListener( const Reference< XFilterControllerListener >& Listener )
880{
881 m_aFilterListeners.removeInterface( Listener );
882}
883
884
885::sal_Int32 SAL_CALL FormController::getFilterComponents()
886{
887 ::osl::MutexGuard aGuard( m_aMutex );
888 impl_checkDisposed_throw();
889
890 return m_aFilterComponents.size();
891}
892
893
894::sal_Int32 SAL_CALL FormController::getDisjunctiveTerms()
895{
896 ::osl::MutexGuard aGuard( m_aMutex );
897 impl_checkDisposed_throw();
898
899 return m_aFilterRows.size();
900}
901
902
903void SAL_CALL FormController::setPredicateExpression( ::sal_Int32 Component, ::sal_Int32 Term, const OUString& PredicateExpression )
904{
905 ::osl::MutexGuard aGuard( m_aMutex );
906 impl_checkDisposed_throw();
907
908 if ( ( Component < 0 ) || ( Component >= getFilterComponents() ) || ( Term < 0 ) || ( Term >= getDisjunctiveTerms() ) )
909 throw IndexOutOfBoundsException( OUString(), *this );
910
911 Reference< XTextComponent > xText( m_aFilterComponents[ Component ] );
912 xText->setText( PredicateExpression );
913
914 FmFilterRow& rFilterRow = m_aFilterRows[ Term ];
915 if ( !PredicateExpression.isEmpty() )
916 rFilterRow[ xText ] = PredicateExpression;
917 else
918 rFilterRow.erase( xText );
919}
920
921
922Reference< XControl > FormController::getFilterComponent( ::sal_Int32 Component )
923{
924 ::osl::MutexGuard aGuard( m_aMutex );
925 impl_checkDisposed_throw();
926
927 if ( ( Component < 0 ) || ( Component >= getFilterComponents() ) )
928 throw IndexOutOfBoundsException( OUString(), *this );
929
930 return Reference< XControl >( m_aFilterComponents[ Component ], UNO_QUERY );
931}
932
933
934Sequence< Sequence< OUString > > FormController::getPredicateExpressions()
935{
936 ::osl::MutexGuard aGuard( m_aMutex );
937 impl_checkDisposed_throw();
938
939 Sequence< Sequence< OUString > > aExpressions( m_aFilterRows.size() );
940 sal_Int32 termIndex = 0;
941 for (const FmFilterRow& rRow : m_aFilterRows)
942 {
943 Sequence< OUString > aConjunction( m_aFilterComponents.size() );
944 sal_Int32 componentIndex = 0;
945 for (const auto& rComp : m_aFilterComponents)
946 {
947 FmFilterRow::const_iterator predicate = rRow.find( rComp );
948 if ( predicate != rRow.end() )
949 aConjunction[ componentIndex ] = predicate->second;
950 ++componentIndex;
951 }
952
953 aExpressions[ termIndex ] = aConjunction;
954 ++termIndex;
955 }
956
957 return aExpressions;
958}
959
960
961void SAL_CALL FormController::removeDisjunctiveTerm( ::sal_Int32 Term )
962{
963 // SYNCHRONIZED -->
964 ::osl::ClearableMutexGuard aGuard( m_aMutex );
965 impl_checkDisposed_throw();
966
967 if ( ( Term < 0 ) || ( Term >= getDisjunctiveTerms() ) )
968 throw IndexOutOfBoundsException( OUString(), *this );
969
970 // if the to-be-deleted row is our current row, we need to shift
971 if ( Term == m_nCurrentFilterPosition )
972 {
973 if ( m_nCurrentFilterPosition < sal_Int32( m_aFilterRows.size() - 1 ) )
974 ++m_nCurrentFilterPosition;
975 else
976 --m_nCurrentFilterPosition;
977 }
978
979 FmFilterRows::iterator pos = m_aFilterRows.begin() + Term;
980 m_aFilterRows.erase( pos );
981
982 // adjust m_nCurrentFilterPosition if the removed row preceded it
983 if ( Term < m_nCurrentFilterPosition )
984 --m_nCurrentFilterPosition;
985
986 SAL_WARN_IF( !( ( m_nCurrentFilterPosition < 0 ) != ( m_aFilterRows.empty() ) ),do { if (true && (!( ( m_nCurrentFilterPosition < 0
) != ( m_aFilterRows.empty() ) ))) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "svx.form")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "FormController::removeDisjunctiveTerm: inconsistency!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx.form"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "987" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "FormController::removeDisjunctiveTerm: inconsistency!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "FormController::removeDisjunctiveTerm: inconsistency!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx.form"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "987" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FormController::removeDisjunctiveTerm: inconsistency!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx.form"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "987" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "FormController::removeDisjunctiveTerm: inconsistency!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "FormController::removeDisjunctiveTerm: inconsistency!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx.form"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "987" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
987 "svx.form", "FormController::removeDisjunctiveTerm: inconsistency!" )do { if (true && (!( ( m_nCurrentFilterPosition < 0
) != ( m_aFilterRows.empty() ) ))) { switch (sal_detail_log_report
(::SAL_DETAIL_LOG_LEVEL_WARN, "svx.form")) { case SAL_DETAIL_LOG_ACTION_IGNORE
: break; case SAL_DETAIL_LOG_ACTION_LOG: if (sizeof ::sal::detail
::getResult( ::sal::detail::StreamStart() << "FormController::removeDisjunctiveTerm: inconsistency!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx.form"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "987" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "FormController::removeDisjunctiveTerm: inconsistency!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "FormController::removeDisjunctiveTerm: inconsistency!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx.form"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "987" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "FormController::removeDisjunctiveTerm: inconsistency!"
) == 1) { ::sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx.form"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "987" ": "), ::sal::detail::unwrapStream( ::sal::detail::
StreamStart() << "FormController::removeDisjunctiveTerm: inconsistency!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "FormController::removeDisjunctiveTerm: inconsistency!"
; ::sal::detail::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx.form"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "987" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
988
989 // update the texts in the filter controls
990 impl_setTextOnAllFilter_throw();
991
992 FilterEvent aEvent;
993 aEvent.Source = *this;
994 aEvent.DisjunctiveTerm = Term;
995 aGuard.clear();
996 // <-- SYNCHRONIZED
997
998 m_aFilterListeners.notifyEach( &XFilterControllerListener::disjunctiveTermRemoved, aEvent );
999}
1000
1001
1002void SAL_CALL FormController::appendEmptyDisjunctiveTerm()
1003{
1004 // SYNCHRONIZED -->
1005 ::osl::ClearableMutexGuard aGuard( m_aMutex );
1006 impl_checkDisposed_throw();
1007
1008 impl_appendEmptyFilterRow( aGuard );
1009 // <-- SYNCHRONIZED
1010}
1011
1012
1013::sal_Int32 SAL_CALL FormController::getActiveTerm()
1014{
1015 ::osl::MutexGuard aGuard( m_aMutex );
1016 impl_checkDisposed_throw();
1017
1018 return m_nCurrentFilterPosition;
1019}
1020
1021
1022void SAL_CALL FormController::setActiveTerm( ::sal_Int32 ActiveTerm )
1023{
1024 ::osl::MutexGuard aGuard( m_aMutex );
1025 impl_checkDisposed_throw();
1026
1027 if ( ( ActiveTerm < 0 ) || ( ActiveTerm >= getDisjunctiveTerms() ) )
1028 throw IndexOutOfBoundsException( OUString(), *this );
1029
1030 if ( ActiveTerm == getActiveTerm() )
1031 return;
1032
1033 m_nCurrentFilterPosition = ActiveTerm;
1034 impl_setTextOnAllFilter_throw();
1035}
1036
1037// XElementAccess
1038
1039sal_Bool SAL_CALL FormController::hasElements()
1040{
1041 ::osl::MutexGuard aGuard( m_aMutex );
1042 return !m_aChildren.empty();
1043}
1044
1045
1046Type SAL_CALL FormController::getElementType()
1047{
1048 return cppu::UnoType<XFormController>::get();
1049
1050}
1051
1052// XEnumerationAccess
1053
1054Reference< XEnumeration > SAL_CALL FormController::createEnumeration()
1055{
1056 ::osl::MutexGuard aGuard( m_aMutex );
1057 return new ::comphelper::OEnumerationByIndex(this);
1058}
1059
1060// XIndexAccess
1061
1062sal_Int32 SAL_CALL FormController::getCount()
1063{
1064 ::osl::MutexGuard aGuard( m_aMutex );
1065 return m_aChildren.size();
1066}
1067
1068
1069Any SAL_CALL FormController::getByIndex(sal_Int32 Index)
1070{
1071 ::osl::MutexGuard aGuard( m_aMutex );
1072 if (Index < 0 ||
1073 Index >= static_cast<sal_Int32>(m_aChildren.size()))
1074 throw IndexOutOfBoundsException();
1075
1076 return makeAny( m_aChildren[ Index ] );
1077}
1078
1079// EventListener
1080
1081void SAL_CALL FormController::disposing(const EventObject& e)
1082{
1083 // has the container been disposed
1084 ::osl::MutexGuard aGuard( m_aMutex );
1085 Reference< XControlContainer > xContainer(e.Source, UNO_QUERY);
1086 if (xContainer.is())
1087 {
1088 setContainer(Reference< XControlContainer > ());
1089 }
1090 else
1091 {
1092 // has a control been disposed
1093 Reference< XControl > xControl(e.Source, UNO_QUERY);
1094 if (xControl.is())
1095 {
1096 if (getContainer().is())
1097 removeControl(xControl);
1098 }
1099 }
1100}
1101
1102// OComponentHelper
1103
1104void FormController::disposeAllFeaturesAndDispatchers()
1105{
1106 for (auto& rDispatcher : m_aFeatureDispatchers)
1107 {
1108 try
1109 {
1110 ::comphelper::disposeComponent( rDispatcher.second );
1111 }
1112 catch( const Exception& )
1113 {
1114 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1114" ": ", "svx" );
;
1115 }
1116 }
1117 m_aFeatureDispatchers.clear();
1118}
1119
1120
1121void FormController::disposing()
1122{
1123 EventObject aEvt( *this );
1124
1125 // if we're still active, simulate a "deactivated" event
1126 if ( m_xActiveControl.is() )
1127 m_aActivateListeners.notifyEach( &XFormControllerListener::formDeactivated, aEvt );
1128
1129 // notify all our listeners
1130 m_aActivateListeners.disposeAndClear(aEvt);
1131 m_aModifyListeners.disposeAndClear(aEvt);
1132 m_aErrorListeners.disposeAndClear(aEvt);
1133 m_aDeleteListeners.disposeAndClear(aEvt);
1134 m_aRowSetApproveListeners.disposeAndClear(aEvt);
1135 m_aParameterListeners.disposeAndClear(aEvt);
1136 m_aFilterListeners.disposeAndClear(aEvt);
1137
1138 removeBoundFieldListener();
1139 stopFiltering();
1140
1141 m_aControlBorderManager.restoreAll();
1142
1143 m_aFilterRows.clear();
1144
1145 ::osl::MutexGuard aGuard( m_aMutex );
1146 m_xActiveControl = nullptr;
1147 implSetCurrentControl( nullptr );
1148
1149 // clean up our children
1150 for (const auto& rpChild : m_aChildren)
1151 {
1152 // search the position of the model within the form
1153 Reference< XFormComponent > xForm(rpChild->getModel(), UNO_QUERY);
1154 sal_uInt32 nPos = m_xModelAsIndex->getCount();
1155 Reference< XFormComponent > xTemp;
1156 for( ; nPos; )
1157 {
1158
1159 m_xModelAsIndex->getByIndex( --nPos ) >>= xTemp;
1160 if ( xForm.get() == xTemp.get() )
1161 {
1162 Reference< XInterface > xIfc( rpChild, UNO_QUERY );
1163 m_xModelAsManager->detach( nPos, xIfc );
1164 break;
1165 }
1166 }
1167
1168 Reference< XComponent > (rpChild, UNO_QUERY_THROW)->dispose();
1169 }
1170 m_aChildren.clear();
1171
1172 disposeAllFeaturesAndDispatchers();
1173
1174 if ( m_xFormOperations.is() )
1175 m_xFormOperations->dispose();
1176 m_xFormOperations.clear();
1177
1178 if (m_bDBConnection)
1179 unload();
1180
1181 setContainer( nullptr );
1182 setModel( nullptr );
1183 setParent( nullptr );
1184
1185 ::comphelper::disposeComponent( m_xComposer );
1186
1187 m_bDBConnection = false;
1188}
1189
1190
1191namespace
1192{
1193 bool lcl_shouldUseDynamicControlBorder( const Reference< XInterface >& _rxForm, const Any& _rDynamicColorProp )
1194 {
1195 bool bDoUse = false;
1196 if ( !( _rDynamicColorProp >>= bDoUse ) )
1197 {
1198 DocumentType eDocType = DocumentClassification::classifyHostDocument( _rxForm );
1199 return ControlLayouter::useDynamicBorderColor( eDocType );
1200 }
1201 return bDoUse;
1202 }
1203}
1204
1205
1206void SAL_CALL FormController::propertyChange(const PropertyChangeEvent& evt)
1207{
1208 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1208" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
1209 if ( evt.PropertyName == FM_PROP_BOUNDFIELD"BoundField" )
1210 {
1211 Reference<XPropertySet> xOldBound;
1212 evt.OldValue >>= xOldBound;
1213 if ( !xOldBound.is() && evt.NewValue.hasValue() )
1214 {
1215 Reference< XControlModel > xControlModel(evt.Source,UNO_QUERY);
1216 Reference< XControl > xControl = findControl(m_aControls,xControlModel,false,false);
1217 if ( xControl.is() )
1218 {
1219 startControlModifyListening( xControl );
1220 Reference<XPropertySet> xProp(xControlModel,UNO_QUERY);
1221 if ( xProp.is() )
1222 xProp->removePropertyChangeListener(FM_PROP_BOUNDFIELD"BoundField", this);
1223 }
1224 }
1225 }
1226 else
1227 {
1228 bool bModifiedChanged = (evt.PropertyName == FM_PROP_ISMODIFIED"IsModified");
1229 bool bNewChanged = (evt.PropertyName == FM_PROP_ISNEW"IsNew");
1230 if (bModifiedChanged || bNewChanged)
1231 {
1232 ::osl::MutexGuard aGuard( m_aMutex );
1233 if (bModifiedChanged)
1234 m_bCurrentRecordModified = ::comphelper::getBOOL(evt.NewValue);
1235 else
1236 m_bCurrentRecordNew = ::comphelper::getBOOL(evt.NewValue);
1237
1238 // toggle the locking
1239 if (m_bLocked != determineLockState())
1240 {
1241 m_bLocked = !m_bLocked;
1242 setLocks();
1243 if (isListeningForChanges())
1244 startListening();
1245 else
1246 stopListening();
1247 }
1248
1249 if ( bNewChanged )
1250 m_aToggleEvent.Call();
1251
1252 if (!m_bCurrentRecordModified)
1253 m_bModified = false;
1254 }
1255 else if ( evt.PropertyName == FM_PROP_DYNAMIC_CONTROL_BORDER"DynamicControlBorder" )
1256 {
1257 bool bEnable = lcl_shouldUseDynamicControlBorder( evt.Source, evt.NewValue );
1258 if ( bEnable )
1259 {
1260 m_aControlBorderManager.enableDynamicBorderColor();
1261 if ( m_xActiveControl.is() )
1262 m_aControlBorderManager.focusGained( m_xActiveControl.get() );
1263 }
1264 else
1265 {
1266 m_aControlBorderManager.disableDynamicBorderColor();
1267 }
1268 }
1269 }
1270}
1271
1272
1273bool FormController::replaceControl( const Reference< XControl >& _rxExistentControl, const Reference< XControl >& _rxNewControl )
1274{
1275 bool bSuccess = false;
1276 try
1277 {
1278 Reference< XIdentifierReplace > xContainer( getContainer(), UNO_QUERY );
1279 DBG_ASSERT( xContainer.is(), "FormController::replaceControl: yes, it's not required by the service description, but XIdentifierReplace would be nice!" )do { if (true && (!(xContainer.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1279" ": "), "%s", "FormController::replaceControl: yes, it's not required by the service description, but XIdentifierReplace would be nice!"
); } } while (false)
;
1280 if ( xContainer.is() )
1281 {
1282 // look up the ID of _rxExistentControl
1283 Sequence< sal_Int32 > aIdentifiers( xContainer->getIdentifiers() );
1284 const sal_Int32* pIdentifiers = std::find_if(aIdentifiers.begin(), aIdentifiers.end(),
1285 [&xContainer, &_rxExistentControl](const sal_Int32 nId) {
1286 Reference< XControl > xCheck( xContainer->getByIdentifier( nId ), UNO_QUERY );
1287 return xCheck == _rxExistentControl;
1288 });
1289 DBG_ASSERT( pIdentifiers != aIdentifiers.end(), "FormController::replaceControl: did not find the control in the container!" )do { if (true && (!(pIdentifiers != aIdentifiers.end(
)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1289" ": "), "%s", "FormController::replaceControl: did not find the control in the container!"
); } } while (false)
;
1290 if ( pIdentifiers != aIdentifiers.end() )
1291 {
1292 bool bReplacedWasActive = ( m_xActiveControl.get() == _rxExistentControl.get() );
1293 bool bReplacedWasCurrent = ( m_xCurrentControl.get() == _rxExistentControl.get() );
1294
1295 if ( bReplacedWasActive )
1296 {
1297 m_xActiveControl = nullptr;
1298 implSetCurrentControl( nullptr );
1299 }
1300 else if ( bReplacedWasCurrent )
1301 {
1302 implSetCurrentControl( _rxNewControl );
1303 }
1304
1305 // carry over the model
1306 _rxNewControl->setModel( _rxExistentControl->getModel() );
1307
1308 xContainer->replaceByIdentifer( *pIdentifiers, makeAny( _rxNewControl ) );
1309 bSuccess = true;
1310
1311 if ( bReplacedWasActive )
1312 {
1313 Reference< XWindow > xControlWindow( _rxNewControl, UNO_QUERY );
1314 if ( xControlWindow.is() )
1315 xControlWindow->setFocus();
1316 }
1317 }
1318 }
1319 }
1320 catch( const Exception& )
1321 {
1322 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1322" ": ", "svx" );
;
1323 }
1324
1325 Reference< XControl > xDisposeIt( bSuccess ? _rxExistentControl : _rxNewControl );
1326 ::comphelper::disposeComponent( xDisposeIt );
1327 return bSuccess;
1328}
1329
1330
1331void FormController::toggleAutoFields(bool bAutoFields)
1332{
1333 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1333" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
1334
1335
1336 Sequence< Reference< XControl > > aControlsCopy( m_aControls );
1337 const Reference< XControl >* pControls = aControlsCopy.getConstArray();
1338 sal_Int32 nControls = aControlsCopy.getLength();
1339
1340 if (bAutoFields)
1341 {
1342 // as we don't want new controls to be attached to the scripting environment
1343 // we change attach flags
1344 m_bAttachEvents = false;
1345 for (sal_Int32 i = nControls; i > 0;)
1346 {
1347 Reference< XControl > xControl = pControls[--i];
1348 if (xControl.is())
1349 {
1350 Reference< XPropertySet > xSet(xControl->getModel(), UNO_QUERY);
1351 if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD"BoundField", xSet))
1352 {
1353 // does the model use a bound field ?
1354 Reference< XPropertySet > xField;
1355 xSet->getPropertyValue(FM_PROP_BOUNDFIELD"BoundField") >>= xField;
1356
1357 // is it an autofield?
1358 if ( xField.is()
1359 && ::comphelper::hasProperty( FM_PROP_AUTOINCREMENT"IsAutoIncrement", xField )
1360 && ::comphelper::getBOOL( xField->getPropertyValue( FM_PROP_AUTOINCREMENT"IsAutoIncrement" ) )
1361 )
1362 {
1363 replaceControl( xControl, new FmXAutoControl() );
1364 }
1365 }
1366 }
1367 }
1368 m_bAttachEvents = true;
1369 }
1370 else
1371 {
1372 m_bDetachEvents = false;
1373 for (sal_Int32 i = nControls; i > 0;)
1374 {
1375 Reference< XControl > xControl = pControls[--i];
1376 if (xControl.is())
1377 {
1378 Reference< XPropertySet > xSet(xControl->getModel(), UNO_QUERY);
1379 if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD"BoundField", xSet))
1380 {
1381 // does the model use a bound field ?
1382 Reference< XPropertySet > xField;
1383 xSet->getPropertyValue(FM_PROP_BOUNDFIELD"BoundField") >>= xField;
1384
1385 // is it an autofield?
1386 if ( xField.is()
1387 && ::comphelper::hasProperty( FM_PROP_AUTOINCREMENT"IsAutoIncrement", xField )
1388 && ::comphelper::getBOOL( xField->getPropertyValue(FM_PROP_AUTOINCREMENT"IsAutoIncrement" ) )
1389 )
1390 {
1391 OUString sServiceName;
1392 OSL_VERIFY( xSet->getPropertyValue( FM_PROP_DEFAULTCONTROL ) >>= sServiceName )do { if (!(xSet->getPropertyValue( "DefaultControl" ) >>=
sServiceName)) do { if (true && (!(0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1392" ": "), "OSL_ASSERT: %s", "0"); } } while (false);
} while (0)
;
1393 Reference< XControl > xNewControl( m_xComponentContext->getServiceManager()->createInstanceWithContext( sServiceName, m_xComponentContext ), UNO_QUERY );
1394 replaceControl( xControl, xNewControl );
1395 }
1396 }
1397 }
1398 }
1399 m_bDetachEvents = true;
1400 }
1401}
1402
1403
1404IMPL_LINK_NOARG(FormController, OnToggleAutoFields, void*, void)void FormController::LinkStubOnToggleAutoFields(void * instance
, void* data) { return static_cast<FormController *>(instance
)->OnToggleAutoFields(data); } void FormController::OnToggleAutoFields
(__attribute__ ((unused)) void*)
1405{
1406 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1406" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
1407
1408 toggleAutoFields(m_bCurrentRecordNew);
1409}
1410
1411// XTextListener
1412void SAL_CALL FormController::textChanged(const TextEvent& e)
1413{
1414 // SYNCHRONIZED -->
1415 ::osl::ClearableMutexGuard aGuard( m_aMutex );
1416 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1416" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
1417 if ( !m_bFiltering )
1418 {
1419 impl_onModify();
1420 return;
1421 }
1422
1423 if ( m_bSuspendFilterTextListening )
1424 return;
1425
1426 Reference< XTextComponent > xText(e.Source,UNO_QUERY);
1427 OUString aText = xText->getText();
1428
1429 if ( m_aFilterRows.empty() )
1430 appendEmptyDisjunctiveTerm();
1431
1432 // find the current row
1433 if ( ( m_nCurrentFilterPosition < 0 ) || ( o3tl::make_unsigned(m_nCurrentFilterPosition) >= m_aFilterRows.size() ) )
1434 {
1435 OSL_ENSURE( false, "FormController::textChanged: m_nCurrentFilterPosition is wrong!" )do { if (true && (!(false))) { sal_detail_logFormat((
SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1435" ": "), "%s", "FormController::textChanged: m_nCurrentFilterPosition is wrong!"
); } } while (false)
;
1436 return;
1437 }
1438
1439 FmFilterRow& rRow = m_aFilterRows[ m_nCurrentFilterPosition ];
1440
1441 // do we have a new filter
1442 if (!aText.isEmpty())
1443 rRow[xText] = aText;
1444 else
1445 {
1446 // do we have the control in the row
1447 FmFilterRow::iterator iter = rRow.find(xText);
1448 // erase the entry out of the row
1449 if (iter != rRow.end())
1450 rRow.erase(iter);
1451 }
1452
1453 // multiplex the event to our FilterControllerListeners
1454 FilterEvent aEvent;
1455 aEvent.Source = *this;
1456 aEvent.FilterComponent = ::std::find( m_aFilterComponents.begin(), m_aFilterComponents.end(), xText ) - m_aFilterComponents.begin();
1457 aEvent.DisjunctiveTerm = getActiveTerm();
1458 aEvent.PredicateExpression = aText;
1459
1460 aGuard.clear();
1461 // <-- SYNCHRONIZED
1462
1463 // notify the changed filter expression
1464 m_aFilterListeners.notifyEach( &XFilterControllerListener::predicateExpressionChanged, aEvent );
1465}
1466
1467// XItemListener
1468void SAL_CALL FormController::itemStateChanged(const ItemEvent& /*rEvent*/)
1469{
1470 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1470" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
1471 impl_onModify();
1472}
1473
1474// XModificationBroadcaster
1475void SAL_CALL FormController::addModifyListener(const Reference< XModifyListener > & l)
1476{
1477 ::osl::MutexGuard aGuard( m_aMutex );
1478 impl_checkDisposed_throw();
1479 m_aModifyListeners.addInterface( l );
1480}
1481
1482void FormController::removeModifyListener(const Reference< XModifyListener > & l)
1483{
1484 ::osl::MutexGuard aGuard( m_aMutex );
1485 impl_checkDisposed_throw();
1486 m_aModifyListeners.removeInterface( l );
1487}
1488
1489// XModificationListener
1490void FormController::modified( const EventObject& _rEvent )
1491{
1492 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1492" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
1493
1494 try
1495 {
1496 if ( _rEvent.Source != m_xActiveControl )
1497 { // let this control grab the focus
1498 // (this case may happen if somebody moves the scroll wheel of the mouse over a control
1499 // which does not have the focus)
1500 // 85511 - 29.05.2001 - frank.schoenheit@germany.sun.com
1501
1502 // also, it happens when an image control gets a new image by double-clicking it
1503 // #i88458# / 2009-01-12 / frank.schoenheit@sun.com
1504 Reference< XWindow > xControlWindow( _rEvent.Source, UNO_QUERY_THROW );
1505 xControlWindow->setFocus();
1506 }
1507 }
1508 catch( const Exception& )
1509 {
1510 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1510" ": ", "svx" );
;
1511 }
1512
1513 impl_onModify();
1514}
1515
1516void FormController::impl_checkDisposed_throw() const
1517{
1518 if ( impl_isDisposed_nofail() )
1519 throw DisposedException( OUString(), *const_cast< FormController* >( this ) );
1520}
1521
1522void FormController::impl_onModify()
1523{
1524 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1524" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
1525
1526 {
1527 ::osl::MutexGuard aGuard( m_aMutex );
1528 if ( !m_bModified )
1529 m_bModified = true;
1530 }
1531
1532 EventObject aEvt(static_cast<cppu::OWeakObject*>(this));
1533 m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvt );
1534}
1535
1536void FormController::impl_addFilterRow( const FmFilterRow& _row )
1537{
1538 m_aFilterRows.push_back( _row );
1539
1540 if ( m_aFilterRows.size() == 1 )
1541 { // that's the first row ever
1542 OSL_ENSURE( m_nCurrentFilterPosition == -1, "FormController::impl_addFilterRow: inconsistency!" )do { if (true && (!(m_nCurrentFilterPosition == -1)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1542" ": "), "%s", "FormController::impl_addFilterRow: inconsistency!"
); } } while (false)
;
1543 m_nCurrentFilterPosition = 0;
1544 }
1545}
1546
1547void FormController::impl_appendEmptyFilterRow( ::osl::ClearableMutexGuard& _rClearBeforeNotify )
1548{
1549 // SYNCHRONIZED -->
1550 impl_addFilterRow( FmFilterRow() );
1551
1552 // notify the listeners
1553 FilterEvent aEvent;
1554 aEvent.Source = *this;
1555 aEvent.DisjunctiveTerm = static_cast<sal_Int32>(m_aFilterRows.size()) - 1;
1556 _rClearBeforeNotify.clear();
1557 // <-- SYNCHRONIZED
1558 m_aFilterListeners.notifyEach( &XFilterControllerListener::disjunctiveTermAdded, aEvent );
1559}
1560
1561bool FormController::determineLockState() const
1562{
1563 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1563" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
1564 // a.) in filter mode we are always locked
1565 // b.) if we have no valid model or our model (a result set) is not alive -> we're locked
1566 // c.) if we are inserting everything is OK and we are not locked
1567 // d.) if are not updatable or on invalid position
1568 Reference< XResultSet > xResultSet(m_xModelAsIndex, UNO_QUERY);
1569 if (m_bFiltering || !xResultSet.is() || !isRowSetAlive(xResultSet))
1570 return true;
1571 else
1572 return !(m_bCanInsert && m_bCurrentRecordNew)
1573 && (xResultSet->isBeforeFirst() || xResultSet->isAfterLast() || xResultSet->rowDeleted() || !m_bCanUpdate);
1574}
1575
1576// FocusListener
1577void FormController::focusGained(const FocusEvent& e)
1578{
1579 // SYNCHRONIZED -->
1580 ::osl::ClearableMutexGuard aGuard( m_aMutex );
1581 impl_checkDisposed_throw();
1582
1583 m_aControlBorderManager.focusGained( e.Source );
1584
1585 Reference< XControl > xControl(e.Source, UNO_QUERY);
1586 if (m_bDBConnection)
1587 {
1588 // do we need to keep the locking of the commit
1589 // we hold the lock as long as the control differs from the current
1590 // otherwise we disabled the lock
1591 m_bCommitLock = m_bCommitLock && xControl.get() != m_xCurrentControl.get();
1592 if (m_bCommitLock)
1593 return;
1594
1595 // when do we have to commit a value to form or a filter
1596 // a.) if the current value is modified
1597 // b.) there must be a current control
1598 // c.) and it must be different from the new focus owning control or
1599 // d.) the focus is moving around (so we have only one control)
1600
1601 if ( ( m_bModified || m_bFiltering )
1602 && m_xCurrentControl.is()
1603 && ( ( xControl.get() != m_xCurrentControl.get() )
1604 || ( ( e.FocusFlags & FocusChangeReason::AROUND )
1605 && ( m_bCycle || m_bFiltering )
1606 )
1607 )
1608 )
1609 {
1610 // check the old control if the content is ok
1611#if OSL_DEBUG_LEVEL1 > 0 && !defined NDEBUG
1612 Reference< XBoundControl > xLockingTest(m_xCurrentControl, UNO_QUERY);
1613 bool bControlIsLocked = xLockingTest.is() && xLockingTest->getLock();
1614 assert(!bControlIsLocked && "FormController::Gained: I'm modified and the current control is locked ? How this ?")(static_cast <bool> (!bControlIsLocked && "FormController::Gained: I'm modified and the current control is locked ? How this ?"
) ? void (0) : __assert_fail ("!bControlIsLocked && \"FormController::Gained: I'm modified and the current control is locked ? How this ?\""
, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
, 1614, __extension__ __PRETTY_FUNCTION__))
;
1615 // normally, a locked control should not be modified, so probably my bModified must
1616 // have been set from a different context, which I would not understand ...
1617#endif
1618 DBG_ASSERT(m_xCurrentControl.is(), "no CurrentControl set")do { if (true && (!(m_xCurrentControl.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1618" ": "), "%s", "no CurrentControl set"); } } while (
false)
;
1619 // first the control ask if it supports the IFace
1620 Reference< XBoundComponent > xBound(m_xCurrentControl, UNO_QUERY);
1621 if (!xBound.is() && m_xCurrentControl.is())
1622 xBound.set(m_xCurrentControl->getModel(), UNO_QUERY);
1623
1624 // lock if we lose the focus during commit
1625 m_bCommitLock = true;
1626
1627 // commit unsuccessful, reset focus
1628 if (xBound.is() && !xBound->commit())
1629 {
1630 // the commit failed and we don't commit again until the current control
1631 // which couldn't be commit gains the focus again
1632 Reference< XWindow > xWindow(m_xCurrentControl, UNO_QUERY);
1633 if (xWindow.is())
1634 xWindow->setFocus();
1635 return;
1636 }
1637 else
1638 {
1639 m_bModified = false;
1640 m_bCommitLock = false;
1641 }
1642 }
1643
1644 if (!m_bFiltering && m_bCycle && (e.FocusFlags & FocusChangeReason::AROUND) && m_xCurrentControl.is())
1645 {
1646 OSL_ENSURE( m_xFormOperations.is(), "FormController::focusGained: hmm?" )do { if (true && (!(m_xFormOperations.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1646" ": "), "%s", "FormController::focusGained: hmm?")
; } } while (false)
;
1647 // should have been created in setModel
1648 try
1649 {
1650 if ( e.FocusFlags & FocusChangeReason::FORWARD )
1651 {
1652 if ( m_xFormOperations.is() && m_xFormOperations->isEnabled( FormFeature::MoveToNext ) )
1653 m_xFormOperations->execute( FormFeature::MoveToNext );
1654 }
1655 else // backward
1656 {
1657 if ( m_xFormOperations.is() && m_xFormOperations->isEnabled( FormFeature::MoveToPrevious ) )
1658 m_xFormOperations->execute( FormFeature::MoveToPrevious );
1659 }
1660 }
1661 catch ( const Exception& )
1662 {
1663 // don't handle this any further. That's an ... admissible error.
1664 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1664" ": ", "svx" );
;
1665 }
1666 }
1667 }
1668
1669 // still one and the same control
1670 if ( ( m_xActiveControl == xControl )
1671 && ( xControl == m_xCurrentControl )
1672 )
1673 {
1674 DBG_ASSERT(m_xCurrentControl.is(), "No CurrentControl selected")do { if (true && (!(m_xCurrentControl.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1674" ": "), "%s", "No CurrentControl selected"); } } while
(false)
;
1675 return;
1676 }
1677
1678 bool bActivated = !m_xActiveControl.is() && xControl.is();
1679
1680 m_xActiveControl = xControl;
1681
1682 implSetCurrentControl( xControl );
1683 SAL_WARN_IF( !m_xCurrentControl.is(), "svx.form", "implSetCurrentControl did nonsense!" )do { if (true && (!m_xCurrentControl.is())) { switch (
sal_detail_log_report(::SAL_DETAIL_LOG_LEVEL_WARN, "svx.form"
)) { case SAL_DETAIL_LOG_ACTION_IGNORE: break; case SAL_DETAIL_LOG_ACTION_LOG
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "implSetCurrentControl did nonsense!") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx.form"), (
"/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1683" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "implSetCurrentControl did nonsense!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "implSetCurrentControl did nonsense!"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx.form"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1683" ": "), sal_detail_stream, 0); }; break; case SAL_DETAIL_LOG_ACTION_FATAL
: if (sizeof ::sal::detail::getResult( ::sal::detail::StreamStart
() << "implSetCurrentControl did nonsense!") == 1) { ::
sal_detail_log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx.form"), (
"/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1683" ": "), ::sal::detail::unwrapStream( ::sal::detail
::StreamStart() << "implSetCurrentControl did nonsense!"
), 0); } else { ::std::ostringstream sal_detail_stream; sal_detail_stream
<< "implSetCurrentControl did nonsense!"; ::sal::detail
::log( (::SAL_DETAIL_LOG_LEVEL_WARN), ("svx.form"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1683" ": "), sal_detail_stream, 0); }; std::abort(); break
; } } } while (false)
;
1684
1685 if ( bActivated )
1686 {
1687 // (asynchronously) call activation handlers
1688 m_aActivationEvent.Call();
1689
1690 // call modify listeners
1691 if ( m_bModified )
1692 m_aModifyListeners.notifyEach( &XModifyListener::modified, EventObject( *this ) );
1693 }
1694
1695 // invalidate all features which depend on the currently focused control
1696 if ( m_bDBConnection && !m_bFiltering )
1697 implInvalidateCurrentControlDependentFeatures();
1698
1699 if ( !m_xCurrentControl.is() )
1700 return;
1701
1702 // control gets focus, then possibly in the visible range
1703 Reference< XFormControllerContext > xContext( m_xFormControllerContext );
1704 Reference< XControl > xCurrentControl( m_xCurrentControl );
1705 aGuard.clear();
1706 // <-- SYNCHRONIZED
1707
1708 if ( xContext.is() )
1709 xContext->makeVisible( xCurrentControl );
1710}
1711
1712IMPL_LINK_NOARG( FormController, OnActivated, void*, void )void FormController::LinkStubOnActivated(void * instance, void
* data) { return static_cast<FormController *>(instance
)->OnActivated(data); } void FormController::OnActivated(__attribute__
((unused)) void*)
1713{
1714 EventObject aEvent;
1715 aEvent.Source = *this;
1716 m_aActivateListeners.notifyEach( &XFormControllerListener::formActivated, aEvent );
1717}
1718
1719IMPL_LINK_NOARG( FormController, OnDeactivated, void*, void )void FormController::LinkStubOnDeactivated(void * instance, void
* data) { return static_cast<FormController *>(instance
)->OnDeactivated(data); } void FormController::OnDeactivated
(__attribute__ ((unused)) void*)
1720{
1721 EventObject aEvent;
1722 aEvent.Source = *this;
1723 m_aActivateListeners.notifyEach( &XFormControllerListener::formDeactivated, aEvent );
1724}
1725
1726void FormController::focusLost(const FocusEvent& e)
1727{
1728 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1728" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
1729
1730 m_aControlBorderManager.focusLost( e.Source );
1731
1732 Reference< XWindowPeer > xNext(e.NextFocus, UNO_QUERY);
1733 // if focus hasn't passed to some other window, e.g. focus in a welded item, don't deactivate
1734 if (!xNext)
1735 return;
1736 Reference< XControl > xNextControl = isInList(xNext);
1737 if (!xNextControl.is())
1738 {
1739 m_xActiveControl = nullptr;
1740 m_aDeactivationEvent.Call();
1741 }
1742}
1743
1744void SAL_CALL FormController::mousePressed( const awt::MouseEvent& /*_rEvent*/ )
1745{
1746 // not interested in
1747}
1748
1749void SAL_CALL FormController::mouseReleased( const awt::MouseEvent& /*_rEvent*/ )
1750{
1751 // not interested in
1752}
1753
1754void SAL_CALL FormController::mouseEntered( const awt::MouseEvent& _rEvent )
1755{
1756 m_aControlBorderManager.mouseEntered( _rEvent.Source );
1757}
1758
1759void SAL_CALL FormController::mouseExited( const awt::MouseEvent& _rEvent )
1760{
1761 m_aControlBorderManager.mouseExited( _rEvent.Source );
1762}
1763
1764void SAL_CALL FormController::componentValidityChanged( const EventObject& _rSource )
1765{
1766 Reference< XControl > xControl( findControl( m_aControls, Reference< XControlModel >( _rSource.Source, UNO_QUERY ), false, false ) );
1767 Reference< XValidatableFormComponent > xValidatable( _rSource.Source, UNO_QUERY );
1768
1769 OSL_ENSURE( xControl.is() && xValidatable.is(), "FormController::componentValidityChanged: huh?" )do { if (true && (!(xControl.is() && xValidatable
.is()))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), (
"legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1769" ": "), "%s", "FormController::componentValidityChanged: huh?"
); } } while (false)
;
1770
1771 if ( xControl.is() && xValidatable.is() )
1772 m_aControlBorderManager.validityChanged( xControl, xValidatable );
1773}
1774
1775
1776void FormController::setModel(const Reference< XTabControllerModel > & Model)
1777{
1778 ::osl::MutexGuard aGuard( m_aMutex );
1779 impl_checkDisposed_throw();
1780
1781 DBG_ASSERT(m_xTabController.is(), "FormController::setModel : invalid aggregate !")do { if (true && (!(m_xTabController.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1781" ": "), "%s", "FormController::setModel : invalid aggregate !"
); } } while (false)
;
1782
1783 try
1784 {
1785 // disconnect from the old model
1786 if (m_xModelAsIndex.is())
1787 {
1788 if (m_bDBConnection)
1789 {
1790 // we are currently working on the model
1791 EventObject aEvt(m_xModelAsIndex);
1792 unloaded(aEvt);
1793 }
1794
1795 Reference< XLoadable > xForm(m_xModelAsIndex, UNO_QUERY);
1796 if (xForm.is())
1797 xForm->removeLoadListener(this);
1798
1799 Reference< XSQLErrorBroadcaster > xBroadcaster(m_xModelAsIndex, UNO_QUERY);
1800 if (xBroadcaster.is())
1801 xBroadcaster->removeSQLErrorListener(this);
1802
1803 Reference< XDatabaseParameterBroadcaster > xParamBroadcaster(m_xModelAsIndex, UNO_QUERY);
1804 if (xParamBroadcaster.is())
1805 xParamBroadcaster->removeParameterListener(this);
1806
1807 }
1808
1809 disposeAllFeaturesAndDispatchers();
1810
1811 if ( m_xFormOperations.is() )
1812 m_xFormOperations->dispose();
1813 m_xFormOperations.clear();
1814
1815 // set the new model wait for the load event
1816 if (m_xTabController.is())
1817 m_xTabController->setModel(Model);
1818 m_xModelAsIndex.set(Model, UNO_QUERY);
1819 m_xModelAsManager.set(Model, UNO_QUERY);
1820
1821 // only if both ifaces exit, the controller will work successful
1822 if (!m_xModelAsIndex.is() || !m_xModelAsManager.is())
1823 {
1824 m_xModelAsManager = nullptr;
1825 m_xModelAsIndex = nullptr;
1826 }
1827
1828 if (m_xModelAsIndex.is())
1829 {
1830 // re-create m_xFormOperations
1831 m_xFormOperations = FormOperations::createWithFormController( m_xComponentContext, this );
1832 m_xFormOperations->setFeatureInvalidation( this );
1833
1834 // adding load and ui interaction listeners
1835 Reference< XLoadable > xForm(Model, UNO_QUERY);
1836 if (xForm.is())
1837 xForm->addLoadListener(this);
1838
1839 Reference< XSQLErrorBroadcaster > xBroadcaster(Model, UNO_QUERY);
1840 if (xBroadcaster.is())
1841 xBroadcaster->addSQLErrorListener(this);
1842
1843 Reference< XDatabaseParameterBroadcaster > xParamBroadcaster(Model, UNO_QUERY);
1844 if (xParamBroadcaster.is())
1845 xParamBroadcaster->addParameterListener(this);
1846
1847 // well, is the database already loaded?
1848 // then we have to simulate a load event
1849 Reference< XLoadable > xCursor(m_xModelAsIndex, UNO_QUERY);
1850 if (xCursor.is() && xCursor->isLoaded())
1851 {
1852 EventObject aEvt(xCursor);
1853 loaded(aEvt);
1854 }
1855
1856 Reference< XPropertySet > xModelProps( m_xModelAsIndex, UNO_QUERY );
1857 Reference< XPropertySetInfo > xPropInfo( xModelProps->getPropertySetInfo() );
1858 if ( xPropInfo.is()
1859 && xPropInfo->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER"DynamicControlBorder" )
1860 && xPropInfo->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_FOCUS"ControlBorderColorOnFocus" )
1861 && xPropInfo->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_MOUSE"ControlBorderColorOnHover" )
1862 && xPropInfo->hasPropertyByName( FM_PROP_CONTROL_BORDER_COLOR_INVALID"ControlBorderColorOnInvalid" )
1863 )
1864 {
1865 bool bEnableDynamicControlBorder = lcl_shouldUseDynamicControlBorder(
1866 xModelProps.get(), xModelProps->getPropertyValue( FM_PROP_DYNAMIC_CONTROL_BORDER"DynamicControlBorder" ) );
1867 if ( bEnableDynamicControlBorder )
1868 m_aControlBorderManager.enableDynamicBorderColor();
1869 else
1870 m_aControlBorderManager.disableDynamicBorderColor();
1871
1872 Color nColor;
1873 if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_FOCUS"ControlBorderColorOnFocus" ) >>= nColor )
1874 m_aControlBorderManager.setStatusColor( ControlStatus::Focused, nColor );
1875 if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_MOUSE"ControlBorderColorOnHover" ) >>= nColor )
1876 m_aControlBorderManager.setStatusColor( ControlStatus::MouseHover, nColor );
1877 if ( xModelProps->getPropertyValue( FM_PROP_CONTROL_BORDER_COLOR_INVALID"ControlBorderColorOnInvalid" ) >>= nColor )
1878 m_aControlBorderManager.setStatusColor( ControlStatus::Invalid, nColor );
1879 }
1880 }
1881 }
1882 catch( const Exception& )
1883 {
1884 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1884" ": ", "svx" );
;
1885 }
1886}
1887
1888
1889Reference< XTabControllerModel > FormController::getModel()
1890{
1891 ::osl::MutexGuard aGuard( m_aMutex );
1892 impl_checkDisposed_throw();
1893
1894 DBG_ASSERT(m_xTabController.is(), "FormController::getModel : invalid aggregate !")do { if (true && (!(m_xTabController.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1894" ": "), "%s", "FormController::getModel : invalid aggregate !"
); } } while (false)
;
1895 if (!m_xTabController.is())
1896 return Reference< XTabControllerModel > ();
1897 return m_xTabController->getModel();
1898}
1899
1900
1901void FormController::addToEventAttacher(const Reference< XControl > & xControl)
1902{
1903 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1903" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
1904 OSL_ENSURE( xControl.is(), "FormController::addToEventAttacher: invalid control - how did you reach this?" )do { if (true && (!(xControl.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1904" ": "), "%s", "FormController::addToEventAttacher: invalid control - how did you reach this?"
); } } while (false)
;
1905 if ( !xControl.is() )
1906 return; /* throw IllegalArgumentException(); */
1907
1908 // register at the event attacher
1909 Reference< XFormComponent > xComp(xControl->getModel(), UNO_QUERY);
1910 if (!(xComp.is() && m_xModelAsIndex.is()))
1911 return;
1912
1913 // and look for the position of the ControlModel in it
1914 sal_uInt32 nPos = m_xModelAsIndex->getCount();
1915 Reference< XFormComponent > xTemp;
1916 for( ; nPos; )
1917 {
1918 m_xModelAsIndex->getByIndex(--nPos) >>= xTemp;
1919 if (xComp.get() == xTemp.get())
1920 {
1921 m_xModelAsManager->attach( nPos, Reference<XInterface>( xControl, UNO_QUERY ), makeAny(xControl) );
1922 break;
1923 }
1924 }
1925}
1926
1927
1928void FormController::removeFromEventAttacher(const Reference< XControl > & xControl)
1929{
1930 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1930" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
1931 OSL_ENSURE( xControl.is(), "FormController::removeFromEventAttacher: invalid control - how did you reach this?" )do { if (true && (!(xControl.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1931" ": "), "%s", "FormController::removeFromEventAttacher: invalid control - how did you reach this?"
); } } while (false)
;
1932 if ( !xControl.is() )
1933 return; /* throw IllegalArgumentException(); */
1934
1935 // register at the event attacher
1936 Reference< XFormComponent > xComp(xControl->getModel(), UNO_QUERY);
1937 if ( !(xComp.is() && m_xModelAsIndex.is()) )
1938 return;
1939
1940 // and look for the position of the ControlModel in it
1941 sal_uInt32 nPos = m_xModelAsIndex->getCount();
1942 Reference< XFormComponent > xTemp;
1943 for( ; nPos; )
1944 {
1945 m_xModelAsIndex->getByIndex(--nPos) >>= xTemp;
1946 if (xComp.get() == xTemp.get())
1947 {
1948 m_xModelAsManager->detach( nPos, Reference<XInterface>( xControl, UNO_QUERY ) );
1949 break;
1950 }
1951 }
1952}
1953
1954
1955void FormController::setContainer(const Reference< XControlContainer > & xContainer)
1956{
1957 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1957" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
1958 Reference< XTabControllerModel > xTabModel(getModel());
1959 DBG_ASSERT(xTabModel.is() || !xContainer.is(), "No Model defined")do { if (true && (!(xTabModel.is() || !xContainer.is(
)))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1959" ": "), "%s", "No Model defined"); } } while (false
)
;
1960 // if we have a new container we need a model
1961 DBG_ASSERT(m_xTabController.is(), "FormController::setContainer : invalid aggregate !")do { if (true && (!(m_xTabController.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "1961" ": "), "%s", "FormController::setContainer : invalid aggregate !"
); } } while (false)
;
1962
1963 ::osl::MutexGuard aGuard( m_aMutex );
1964 Reference< XContainer > xCurrentContainer;
1965 if (m_xTabController.is())
1966 xCurrentContainer.set(m_xTabController->getContainer(), UNO_QUERY);
1967 if (xCurrentContainer.is())
1968 {
1969 xCurrentContainer->removeContainerListener(this);
1970
1971 if ( m_aTabActivationIdle.IsActive() )
1972 m_aTabActivationIdle.Stop();
1973
1974 // clear the filter map
1975 ::std::for_each( m_aFilterComponents.begin(), m_aFilterComponents.end(), RemoveComponentTextListener( this ) );
1976 m_aFilterComponents.clear();
1977
1978 // collecting the controls
1979 for ( const Reference< XControl >& rControl : std::as_const(m_aControls) )
1980 implControlRemoved( rControl, true );
1981
1982 // make database-specific things
1983 if (m_bDBConnection && isListeningForChanges())
1984 stopListening();
1985
1986 m_aControls.realloc( 0 );
1987 }
1988
1989 if (m_xTabController.is())
1990 m_xTabController->setContainer(xContainer);
1991
1992 // What controls belong to the container?
1993 if (xContainer.is() && xTabModel.is())
1994 {
1995 const Sequence< Reference< XControlModel > > aModels = xTabModel->getControlModels();
1996 Sequence< Reference< XControl > > aAllControls = xContainer->getControls();
1997
1998 sal_Int32 nCount = aModels.getLength();
1999 m_aControls = Sequence< Reference< XControl > >( nCount );
2000 Reference< XControl > * pControls = m_aControls.getArray();
2001
2002 // collecting the controls
2003 sal_Int32 j = 0;
2004 for (const Reference< XControlModel >& rModel : aModels )
2005 {
2006 Reference< XControl > xControl = findControl( aAllControls, rModel, false, true );
2007 if ( xControl.is() )
2008 {
2009 pControls[j++] = xControl;
2010 implControlInserted( xControl, true );
2011 }
2012 }
2013
2014 // not every model had an associated control
2015 if (j != nCount)
2016 m_aControls.realloc(j);
2017
2018 // listen at the container
2019 Reference< XContainer > xNewContainer(xContainer, UNO_QUERY);
2020 if (xNewContainer.is())
2021 xNewContainer->addContainerListener(this);
2022
2023 // make database-specific things
2024 if (m_bDBConnection)
2025 {
2026 m_bLocked = determineLockState();
2027 setLocks();
2028 if (!isLocked())
2029 startListening();
2030 }
2031 }
2032 // the controls are in the right order
2033 m_bControlsSorted = true;
2034}
2035
2036
2037Reference< XControlContainer > FormController::getContainer()
2038{
2039 ::osl::MutexGuard aGuard( m_aMutex );
2040 impl_checkDisposed_throw();
2041
2042 DBG_ASSERT(m_xTabController.is(), "FormController::getContainer : invalid aggregate !")do { if (true && (!(m_xTabController.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2042" ": "), "%s", "FormController::getContainer : invalid aggregate !"
); } } while (false)
;
2043 if (!m_xTabController.is())
2044 return Reference< XControlContainer > ();
2045 return m_xTabController->getContainer();
2046}
2047
2048
2049Sequence< Reference< XControl > > FormController::getControls()
2050{
2051 ::osl::MutexGuard aGuard( m_aMutex );
2052 impl_checkDisposed_throw();
2053
2054 if (!m_bControlsSorted)
2055 {
2056 Reference< XTabControllerModel > xModel = getModel();
2057 if (!xModel.is())
2058 return m_aControls;
2059
2060 const Sequence< Reference< XControlModel > > aControlModels = xModel->getControlModels();
2061 sal_Int32 nModels = aControlModels.getLength();
2062
2063 Sequence< Reference< XControl > > aNewControls(nModels);
2064
2065 Reference< XControl > * pControls = aNewControls.getArray();
2066 Reference< XControl > xControl;
2067
2068 // rearrange the controls according to the tab order sequence
2069 sal_Int32 j = 0;
2070 for ( const Reference< XControlModel >& rModel : aControlModels )
2071 {
2072 xControl = findControl( m_aControls, rModel, true, true );
2073 if ( xControl.is() )
2074 pControls[j++] = xControl;
2075 }
2076
2077 // not every model had an associated control
2078 if ( j != nModels )
2079 aNewControls.realloc( j );
2080
2081 m_aControls = aNewControls;
2082 m_bControlsSorted = true;
2083 }
2084 return m_aControls;
2085}
2086
2087
2088void FormController::autoTabOrder()
2089{
2090 ::osl::MutexGuard aGuard( m_aMutex );
2091 impl_checkDisposed_throw();
2092
2093 DBG_ASSERT(m_xTabController.is(), "FormController::autoTabOrder : invalid aggregate !")do { if (true && (!(m_xTabController.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2093" ": "), "%s", "FormController::autoTabOrder : invalid aggregate !"
); } } while (false)
;
2094 if (m_xTabController.is())
2095 m_xTabController->autoTabOrder();
2096}
2097
2098
2099void FormController::activateTabOrder()
2100{
2101 ::osl::MutexGuard aGuard( m_aMutex );
2102 impl_checkDisposed_throw();
2103
2104 DBG_ASSERT(m_xTabController.is(), "FormController::activateTabOrder : invalid aggregate !")do { if (true && (!(m_xTabController.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2104" ": "), "%s", "FormController::activateTabOrder : invalid aggregate !"
); } } while (false)
;
2105 if (m_xTabController.is())
2106 m_xTabController->activateTabOrder();
2107}
2108
2109
2110void FormController::setControlLock(const Reference< XControl > & xControl)
2111{
2112 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2112" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
2113 bool bLocked = isLocked();
2114
2115 // It is locked
2116 // a. if the entire record is locked
2117 // b. if the associated field is locked
2118 Reference< XBoundControl > xBound(xControl, UNO_QUERY);
2119 if (!(xBound.is() &&
2120 ( (bLocked && bLocked != bool(xBound->getLock())) ||
2121 !bLocked))) // always uncheck individual fields when unlocking
2122 return;
2123
2124 // there is a data source
2125 Reference< XPropertySet > xSet(xControl->getModel(), UNO_QUERY);
2126 if (!(xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD"BoundField", xSet)))
2127 return;
2128
2129 // what about the ReadOnly and Enable properties
2130 bool bTouch = true;
2131 if (::comphelper::hasProperty(FM_PROP_ENABLED"Enabled", xSet))
2132 bTouch = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ENABLED"Enabled"));
2133 if (::comphelper::hasProperty(FM_PROP_READONLY"ReadOnly", xSet))
2134 bTouch = !::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_READONLY"ReadOnly"));
2135
2136 if (!bTouch)
2137 return;
2138
2139 Reference< XPropertySet > xField;
2140 xSet->getPropertyValue(FM_PROP_BOUNDFIELD"BoundField") >>= xField;
2141 if (!xField.is())
2142 return;
2143
2144 if (bLocked)
2145 xBound->setLock(bLocked);
2146 else
2147 {
2148 try
2149 {
2150 Any aVal = xField->getPropertyValue(FM_PROP_ISREADONLY"IsReadOnly");
2151 if (aVal.hasValue() && ::comphelper::getBOOL(aVal))
2152 xBound->setLock(true);
2153 else
2154 xBound->setLock(bLocked);
2155 }
2156 catch( const Exception& )
2157 {
2158 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2158" ": ", "svx" );
;
2159 }
2160
2161 }
2162}
2163
2164
2165void FormController::setLocks()
2166{
2167 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2167" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
2168 // lock/unlock all controls connected to a data source
2169 for ( const Reference< XControl >& rControl : std::as_const(m_aControls) )
2170 setControlLock( rControl );
2171}
2172
2173
2174namespace
2175{
2176 bool lcl_shouldListenForModifications( const Reference< XControl >& _rxControl, const Reference< XPropertyChangeListener >& _rxBoundFieldListener )
2177 {
2178 bool bShould = false;
2179
2180 Reference< XBoundComponent > xBound( _rxControl, UNO_QUERY );
2181 if ( xBound.is() )
2182 {
2183 bShould = true;
2184 }
2185 else if ( _rxControl.is() )
2186 {
2187 Reference< XPropertySet > xModelProps( _rxControl->getModel(), UNO_QUERY );
2188 if ( xModelProps.is() && ::comphelper::hasProperty( FM_PROP_BOUNDFIELD"BoundField", xModelProps ) )
2189 {
2190 Reference< XPropertySet > xField;
2191 xModelProps->getPropertyValue( FM_PROP_BOUNDFIELD"BoundField" ) >>= xField;
2192 bShould = xField.is();
2193
2194 if ( !bShould && _rxBoundFieldListener.is() )
2195 xModelProps->addPropertyChangeListener( FM_PROP_BOUNDFIELD"BoundField", _rxBoundFieldListener );
2196 }
2197 }
2198
2199 return bShould;
2200 }
2201}
2202
2203
2204void FormController::startControlModifyListening(const Reference< XControl > & xControl)
2205{
2206 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2206" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
2207
2208 bool bModifyListening = lcl_shouldListenForModifications( xControl, this );
2209
2210 // artificial while
2211 while ( bModifyListening )
2212 {
2213 Reference< XModifyBroadcaster > xMod(xControl, UNO_QUERY);
2214 if (xMod.is())
2215 {
2216 xMod->addModifyListener(this);
2217 break;
2218 }
2219
2220 // all the text to prematurely recognize a modified
2221 Reference< XTextComponent > xText(xControl, UNO_QUERY);
2222 if (xText.is())
2223 {
2224 xText->addTextListener(this);
2225 break;
2226 }
2227
2228 Reference< XCheckBox > xBox(xControl, UNO_QUERY);
2229 if (xBox.is())
2230 {
2231 xBox->addItemListener(this);
2232 break;
2233 }
2234
2235 Reference< XComboBox > xCbBox(xControl, UNO_QUERY);
2236 if (xCbBox.is())
2237 {
2238 xCbBox->addItemListener(this);
2239 break;
2240 }
2241
2242 Reference< XListBox > xListBox(xControl, UNO_QUERY);
2243 if (xListBox.is())
2244 {
2245 xListBox->addItemListener(this);
2246 break;
2247 }
2248 break;
2249 }
2250}
2251
2252
2253void FormController::stopControlModifyListening(const Reference< XControl > & xControl)
2254{
2255 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2255" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
2256
2257 bool bModifyListening = lcl_shouldListenForModifications( xControl, nullptr );
2258
2259 // artificial while
2260 while (bModifyListening)
2261 {
2262 Reference< XModifyBroadcaster > xMod(xControl, UNO_QUERY);
2263 if (xMod.is())
2264 {
2265 xMod->removeModifyListener(this);
2266 break;
2267 }
2268 // all the text to prematurely recognize a modified
2269 Reference< XTextComponent > xText(xControl, UNO_QUERY);
2270 if (xText.is())
2271 {
2272 xText->removeTextListener(this);
2273 break;
2274 }
2275
2276 Reference< XCheckBox > xBox(xControl, UNO_QUERY);
2277 if (xBox.is())
2278 {
2279 xBox->removeItemListener(this);
2280 break;
2281 }
2282
2283 Reference< XComboBox > xCbBox(xControl, UNO_QUERY);
2284 if (xCbBox.is())
2285 {
2286 xCbBox->removeItemListener(this);
2287 break;
2288 }
2289
2290 Reference< XListBox > xListBox(xControl, UNO_QUERY);
2291 if (xListBox.is())
2292 {
2293 xListBox->removeItemListener(this);
2294 break;
2295 }
2296 break;
2297 }
2298}
2299
2300
2301void FormController::startListening()
2302{
2303 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2303" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
2304 m_bModified = false;
2305
2306 // now register at bound fields
2307 for ( const Reference< XControl >& rControl : std::as_const(m_aControls) )
2308 startControlModifyListening( rControl );
2309}
2310
2311
2312void FormController::stopListening()
2313{
2314 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2314" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
2315 m_bModified = false;
2316
2317 // now register at bound fields
2318 for ( const Reference< XControl >& rControl : std::as_const(m_aControls) )
2319 stopControlModifyListening( rControl );
2320}
2321
2322
2323Reference< XControl > FormController::findControl(Sequence< Reference< XControl > >& _rControls, const Reference< XControlModel > & xCtrlModel ,bool _bRemove,bool _bOverWrite) const
2324{
2325 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2325" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
2326 DBG_ASSERT( xCtrlModel.is(), "findControl - which ?!" )do { if (true && (!(xCtrlModel.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2326" ": "), "%s", "findControl - which ?!"); } } while
(false)
;
2327
2328 Reference< XControl >* pControls = std::find_if(_rControls.begin(), _rControls.end(),
2329 [&xCtrlModel](const Reference< XControl >& rControl) {
2330 return rControl.is() && rControl->getModel().get() == xCtrlModel.get(); });
2331 if (pControls != _rControls.end())
2332 {
2333 Reference< XControl > xControl( *pControls );
2334 if ( _bRemove )
2335 {
2336 auto i = static_cast<sal_Int32>(std::distance(_rControls.begin(), pControls));
2337 ::comphelper::removeElementAt( _rControls, i );
2338 }
2339 else if ( _bOverWrite )
2340 pControls->clear();
2341 return xControl;
2342 }
2343 return Reference< XControl > ();
2344}
2345
2346
2347void FormController::implControlInserted( const Reference< XControl>& _rxControl, bool _bAddToEventAttacher )
2348{
2349 Reference< XWindow > xWindow( _rxControl, UNO_QUERY );
2350 if ( xWindow.is() )
2351 {
2352 xWindow->addFocusListener( this );
2353 xWindow->addMouseListener( this );
2354
2355 if ( _bAddToEventAttacher )
2356 addToEventAttacher( _rxControl );
2357 }
2358
2359 // add a dispatch interceptor to the control (if supported)
2360 Reference< XDispatchProviderInterception > xInterception( _rxControl, UNO_QUERY );
2361 if ( xInterception.is() )
2362 createInterceptor( xInterception );
2363
2364 if ( !_rxControl.is() )
2365 return;
2366
2367 Reference< XControlModel > xModel( _rxControl->getModel() );
2368
2369 // we want to know about the reset of the model of our controls
2370 // (for correctly resetting m_bModified)
2371 Reference< XReset > xReset( xModel, UNO_QUERY );
2372 if ( xReset.is() )
2373 xReset->addResetListener( this );
2374
2375 // and we want to know about the validity, to visually indicate it
2376 Reference< XValidatableFormComponent > xValidatable( xModel, UNO_QUERY );
2377 if ( xValidatable.is() )
2378 {
2379 xValidatable->addFormComponentValidityListener( this );
2380 m_aControlBorderManager.validityChanged( _rxControl, xValidatable );
2381 }
2382
2383}
2384
2385
2386void FormController::implControlRemoved( const Reference< XControl>& _rxControl, bool _bRemoveFromEventAttacher )
2387{
2388 Reference< XWindow > xWindow( _rxControl, UNO_QUERY );
2389 if ( xWindow.is() )
2390 {
2391 xWindow->removeFocusListener( this );
2392 xWindow->removeMouseListener( this );
2393
2394 if ( _bRemoveFromEventAttacher )
2395 removeFromEventAttacher( _rxControl );
2396 }
2397
2398 Reference< XDispatchProviderInterception > xInterception( _rxControl, UNO_QUERY);
2399 if ( xInterception.is() )
2400 deleteInterceptor( xInterception );
2401
2402 if ( _rxControl.is() )
2403 {
2404 Reference< XControlModel > xModel( _rxControl->getModel() );
2405
2406 Reference< XReset > xReset( xModel, UNO_QUERY );
2407 if ( xReset.is() )
2408 xReset->removeResetListener( this );
2409
2410 Reference< XValidatableFormComponent > xValidatable( xModel, UNO_QUERY );
2411 if ( xValidatable.is() )
2412 xValidatable->removeFormComponentValidityListener( this );
2413 }
2414}
2415
2416
2417void FormController::implSetCurrentControl( const Reference< XControl >& _rxControl )
2418{
2419 if ( m_xCurrentControl.get() == _rxControl.get() )
2420 return;
2421
2422 Reference< XGridControl > xGridControl( m_xCurrentControl, UNO_QUERY );
2423 if ( xGridControl.is() )
2424 xGridControl->removeGridControlListener( this );
2425
2426 m_xCurrentControl = _rxControl;
2427
2428 xGridControl.set( m_xCurrentControl, UNO_QUERY );
2429 if ( xGridControl.is() )
2430 xGridControl->addGridControlListener( this );
2431}
2432
2433
2434void FormController::insertControl(const Reference< XControl > & xControl)
2435{
2436 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2436" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
2437 m_bControlsSorted = false;
2438 m_aControls.realloc(m_aControls.getLength() + 1);
2439 m_aControls.getArray()[m_aControls.getLength() - 1] = xControl;
2440
2441 if (m_pColumnInfoCache)
2442 m_pColumnInfoCache->deinitializeControls();
2443
2444 implControlInserted( xControl, m_bAttachEvents );
2445
2446 if (m_bDBConnection && !m_bFiltering)
2447 setControlLock(xControl);
2448
2449 if (isListeningForChanges() && m_bAttachEvents)
2450 startControlModifyListening( xControl );
2451}
2452
2453
2454void FormController::removeControl(const Reference< XControl > & xControl)
2455{
2456 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2456" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
2457 auto pControl = std::find_if(m_aControls.begin(), m_aControls.end(),
2458 [&xControl](const Reference< XControl >& rControl) { return xControl.get() == rControl.get(); });
2459 if (pControl != m_aControls.end())
2460 {
2461 auto nIndex = static_cast<sal_Int32>(std::distance(m_aControls.begin(), pControl));
2462 ::comphelper::removeElementAt( m_aControls, nIndex );
2463 }
2464
2465 FilterComponents::iterator componentPos = ::std::find( m_aFilterComponents.begin(), m_aFilterComponents.end(), xControl );
2466 if ( componentPos != m_aFilterComponents.end() )
2467 m_aFilterComponents.erase( componentPos );
2468
2469 implControlRemoved( xControl, m_bDetachEvents );
2470
2471 if ( isListeningForChanges() && m_bDetachEvents )
2472 stopControlModifyListening( xControl );
2473}
2474
2475// XLoadListener
2476
2477void FormController::loaded(const EventObject& rEvent)
2478{
2479 OSL_ENSURE( rEvent.Source == m_xModelAsIndex, "FormController::loaded: where did this come from?" )do { if (true && (!(rEvent.Source == m_xModelAsIndex)
)) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2479" ": "), "%s", "FormController::loaded: where did this come from?"
); } } while (false)
;
2480
2481 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2481" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
2482 ::osl::MutexGuard aGuard( m_aMutex );
2483 Reference< XRowSet > xForm(rEvent.Source, UNO_QUERY);
2484 // do we have a connected data source
2485 if (xForm.is() && getConnection(xForm).is())
2486 {
2487 Reference< XPropertySet > xSet(xForm, UNO_QUERY);
2488 if (xSet.is())
2489 {
2490 Any aVal = xSet->getPropertyValue(FM_PROP_CYCLE"Cycle");
2491 sal_Int32 aVal2 = 0;
2492 ::cppu::enum2int(aVal2,aVal);
2493 m_bCycle = !aVal.hasValue() || static_cast<form::TabulatorCycle>(aVal2) == TabulatorCycle_RECORDS;
2494 m_bCanUpdate = canUpdate(xSet);
2495 m_bCanInsert = canInsert(xSet);
2496 m_bCurrentRecordModified = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISMODIFIED"IsModified"));
2497 m_bCurrentRecordNew = ::comphelper::getBOOL(xSet->getPropertyValue(FM_PROP_ISNEW"IsNew"));
2498
2499 startFormListening( xSet, false );
2500
2501 // set the locks for the current controls
2502 if (getContainer().is())
2503 {
2504 m_aLoadEvent.Call();
2505 }
2506 }
2507 else
2508 {
2509 m_bCanInsert = m_bCanUpdate = m_bCycle = false;
2510 m_bCurrentRecordModified = false;
2511 m_bCurrentRecordNew = false;
2512 m_bLocked = false;
2513 }
2514 m_bDBConnection = true;
2515 }
2516 else
2517 {
2518 m_bDBConnection = false;
2519 m_bCanInsert = m_bCanUpdate = m_bCycle = false;
2520 m_bCurrentRecordModified = false;
2521 m_bCurrentRecordNew = false;
2522 m_bLocked = false;
2523 }
2524
2525 Reference< XColumnsSupplier > xFormColumns( xForm, UNO_QUERY );
2526 m_pColumnInfoCache.reset( xFormColumns.is() ? new ColumnInfoCache( xFormColumns ) : nullptr );
2527
2528 updateAllDispatchers();
2529}
2530
2531
2532void FormController::updateAllDispatchers() const
2533{
2534 ::std::for_each(
2535 m_aFeatureDispatchers.begin(),
2536 m_aFeatureDispatchers.end(),
2537 [] (const DispatcherContainer::value_type& dispatcher) {
2538 UpdateAllListeners()(dispatcher.second);
2539 });
2540}
2541
2542
2543IMPL_LINK_NOARG(FormController, OnLoad, void*, void)void FormController::LinkStubOnLoad(void * instance, void* data
) { return static_cast<FormController *>(instance)->
OnLoad(data); } void FormController::OnLoad(__attribute__ ((unused
)) void*)
2544{
2545 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2545" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
2546 m_bLocked = determineLockState();
2547
2548 setLocks();
2549
2550 if (!m_bLocked)
2551 startListening();
2552
2553 // just one exception toggle the auto values
2554 if (m_bCurrentRecordNew)
2555 toggleAutoFields(true);
2556}
2557
2558
2559void FormController::unloaded(const EventObject& /*rEvent*/)
2560{
2561 ::osl::MutexGuard aGuard( m_aMutex );
2562 impl_checkDisposed_throw();
2563
2564 updateAllDispatchers();
2565}
2566
2567
2568void FormController::reloading(const EventObject& /*aEvent*/)
2569{
2570 ::osl::MutexGuard aGuard( m_aMutex );
2571 impl_checkDisposed_throw();
2572
2573 // do the same like in unloading
2574 // just one exception toggle the auto values
2575 m_aToggleEvent.CancelPendingCall();
2576 unload();
2577}
2578
2579
2580void FormController::reloaded(const EventObject& aEvent)
2581{
2582 ::osl::MutexGuard aGuard( m_aMutex );
2583 impl_checkDisposed_throw();
2584
2585 loaded(aEvent);
2586}
2587
2588
2589void FormController::unloading(const EventObject& /*aEvent*/)
2590{
2591 ::osl::MutexGuard aGuard( m_aMutex );
2592 impl_checkDisposed_throw();
2593
2594 unload();
2595}
2596
2597
2598void FormController::unload()
2599{
2600 ::osl::MutexGuard aGuard( m_aMutex );
2601 impl_checkDisposed_throw();
2602
2603 m_aLoadEvent.CancelPendingCall();
2604
2605 // be sure not to have autofields
2606 if (m_bCurrentRecordNew)
2607 toggleAutoFields(false);
2608
2609 // remove bound field listing again
2610 removeBoundFieldListener();
2611
2612 if (m_bDBConnection && isListeningForChanges())
2613 stopListening();
2614
2615 Reference< XPropertySet > xSet( m_xModelAsIndex, UNO_QUERY );
2616 if ( m_bDBConnection && xSet.is() )
2617 stopFormListening( xSet, false );
2618
2619 m_bDBConnection = false;
2620 m_bCanInsert = m_bCanUpdate = m_bCycle = false;
2621 m_bCurrentRecordModified = m_bCurrentRecordNew = m_bLocked = false;
2622
2623 m_pColumnInfoCache.reset();
2624}
2625
2626
2627void FormController::removeBoundFieldListener()
2628{
2629 for ( const Reference< XControl >& rControl : std::as_const(m_aControls) )
2630 {
2631 Reference< XPropertySet > xProp( rControl, UNO_QUERY );
2632 if ( xProp.is() )
2633 xProp->removePropertyChangeListener( FM_PROP_BOUNDFIELD"BoundField", this );
2634 }
2635}
2636
2637
2638void FormController::startFormListening( const Reference< XPropertySet >& _rxForm, bool _bPropertiesOnly )
2639{
2640 try
2641 {
2642 if ( m_bCanInsert || m_bCanUpdate ) // form can be modified
2643 {
2644 _rxForm->addPropertyChangeListener( FM_PROP_ISNEW"IsNew", this );
2645 _rxForm->addPropertyChangeListener( FM_PROP_ISMODIFIED"IsModified", this );
2646
2647 if ( !_bPropertiesOnly )
2648 {
2649 // set the Listener for UI interaction
2650 Reference< XRowSetApproveBroadcaster > xApprove( _rxForm, UNO_QUERY );
2651 if ( xApprove.is() )
2652 xApprove->addRowSetApproveListener( this );
2653
2654 // listener for row set changes
2655 Reference< XRowSet > xRowSet( _rxForm, UNO_QUERY );
2656 if ( xRowSet.is() )
2657 xRowSet->addRowSetListener( this );
2658 }
2659 }
2660
2661 Reference< XPropertySetInfo > xInfo = _rxForm->getPropertySetInfo();
2662 if ( xInfo.is() && xInfo->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER"DynamicControlBorder" ) )
2663 _rxForm->addPropertyChangeListener( FM_PROP_DYNAMIC_CONTROL_BORDER"DynamicControlBorder", this );
2664 }
2665 catch( const Exception& )
2666 {
2667 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2667" ": ", "svx" );
;
2668 }
2669}
2670
2671
2672void FormController::stopFormListening( const Reference< XPropertySet >& _rxForm, bool _bPropertiesOnly )
2673{
2674 try
2675 {
2676 if ( m_bCanInsert || m_bCanUpdate )
2677 {
2678 _rxForm->removePropertyChangeListener( FM_PROP_ISNEW"IsNew", this );
2679 _rxForm->removePropertyChangeListener( FM_PROP_ISMODIFIED"IsModified", this );
2680
2681 if ( !_bPropertiesOnly )
2682 {
2683 Reference< XRowSetApproveBroadcaster > xApprove( _rxForm, UNO_QUERY );
2684 if (xApprove.is())
2685 xApprove->removeRowSetApproveListener(this);
2686
2687 Reference< XRowSet > xRowSet( _rxForm, UNO_QUERY );
2688 if ( xRowSet.is() )
2689 xRowSet->removeRowSetListener( this );
2690 }
2691 }
2692
2693 Reference< XPropertySetInfo > xInfo = _rxForm->getPropertySetInfo();
2694 if ( xInfo.is() && xInfo->hasPropertyByName( FM_PROP_DYNAMIC_CONTROL_BORDER"DynamicControlBorder" ) )
2695 _rxForm->removePropertyChangeListener( FM_PROP_DYNAMIC_CONTROL_BORDER"DynamicControlBorder", this );
2696 }
2697 catch( const Exception& )
2698 {
2699 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2699" ": ", "svx" );
;
2700 }
2701}
2702
2703// css::sdbc::XRowSetListener
2704
2705void FormController::cursorMoved(const EventObject& /*event*/)
2706{
2707 ::osl::MutexGuard aGuard( m_aMutex );
2708 impl_checkDisposed_throw();
2709
2710 // toggle the locking ?
2711 if (m_bLocked != determineLockState())
2712 {
2713 m_bLocked = !m_bLocked;
2714 setLocks();
2715 if (isListeningForChanges())
2716 startListening();
2717 else
2718 stopListening();
2719 }
2720
2721 // neither the current control nor the current record are modified anymore
2722 m_bCurrentRecordModified = m_bModified = false;
2723}
2724
2725
2726void FormController::rowChanged(const EventObject& /*event*/)
2727{
2728 // not interested in ...
2729}
2730
2731void FormController::rowSetChanged(const EventObject& /*event*/)
2732{
2733 // not interested in ...
2734}
2735
2736
2737// XContainerListener
2738
2739void SAL_CALL FormController::elementInserted(const ContainerEvent& evt)
2740{
2741 ::osl::MutexGuard aGuard( m_aMutex );
2742 impl_checkDisposed_throw();
2743
2744 Reference< XControl > xControl( evt.Element, UNO_QUERY );
2745 if ( !xControl.is() )
2746 return;
2747
2748 Reference< XFormComponent > xModel(xControl->getModel(), UNO_QUERY);
2749 if (xModel.is() && m_xModelAsIndex == xModel->getParent())
2750 {
2751 insertControl(xControl);
2752
2753 if ( m_aTabActivationIdle.IsActive() )
2754 m_aTabActivationIdle.Stop();
2755
2756 m_aTabActivationIdle.Start();
2757 }
2758 // are we in filtermode and a XModeSelector has inserted an element
2759 else if (m_bFiltering && Reference< XModeSelector > (evt.Source, UNO_QUERY).is())
2760 {
2761 xModel.set(evt.Source, UNO_QUERY);
2762 if (xModel.is() && m_xModelAsIndex == xModel->getParent())
2763 {
2764 Reference< XPropertySet > xSet(xControl->getModel(), UNO_QUERY);
2765 if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD"BoundField", xSet))
2766 {
2767 // does the model use a bound field ?
2768 Reference< XPropertySet > xField;
2769 xSet->getPropertyValue(FM_PROP_BOUNDFIELD"BoundField") >>= xField;
2770
2771 Reference< XTextComponent > xText(xControl, UNO_QUERY);
2772 // may we filter the field?
2773 if (xText.is() && xField.is() && ::comphelper::hasProperty(FM_PROP_SEARCHABLE"IsSearchable", xField) &&
2774 ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_SEARCHABLE"IsSearchable")))
2775 {
2776 m_aFilterComponents.push_back( xText );
2777 xText->addTextListener( this );
2778 }
2779 }
2780 }
2781 }
2782}
2783
2784
2785void SAL_CALL FormController::elementReplaced(const ContainerEvent& evt)
2786{
2787 // simulate an elementRemoved
2788 ContainerEvent aRemoveEvent( evt );
2789 aRemoveEvent.Element = evt.ReplacedElement;
2790 aRemoveEvent.ReplacedElement = Any();
2791 elementRemoved( aRemoveEvent );
2792
2793 // simulate an elementInserted
2794 ContainerEvent aInsertEvent( evt );
2795 aInsertEvent.ReplacedElement = Any();
2796 elementInserted( aInsertEvent );
2797}
2798
2799
2800void SAL_CALL FormController::elementRemoved(const ContainerEvent& evt)
2801{
2802 ::osl::MutexGuard aGuard( m_aMutex );
2803 impl_checkDisposed_throw();
2804
2805 Reference< XControl > xControl;
2806 evt.Element >>= xControl;
2807 if (!xControl.is())
2808 return;
2809
2810 Reference< XFormComponent > xModel(xControl->getModel(), UNO_QUERY);
2811 if (xModel.is() && m_xModelAsIndex == xModel->getParent())
2812 {
2813 removeControl(xControl);
2814 // Do not recalculate TabOrder, because it must already work internally!
2815 }
2816 // are we in filtermode and a XModeSelector has inserted an element
2817 else if (m_bFiltering && Reference< XModeSelector > (evt.Source, UNO_QUERY).is())
2818 {
2819 FilterComponents::iterator componentPos = ::std::find(
2820 m_aFilterComponents.begin(), m_aFilterComponents.end(), xControl );
2821 if ( componentPos != m_aFilterComponents.end() )
2822 m_aFilterComponents.erase( componentPos );
2823 }
2824}
2825
2826
2827Reference< XControl > FormController::isInList(const Reference< XWindowPeer > & xPeer) const
2828{
2829 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2829" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
2830 const Reference< XControl >* pControls = m_aControls.getConstArray();
2831
2832 sal_uInt32 nCtrls = m_aControls.getLength();
2833 for ( sal_uInt32 n = 0; n < nCtrls && xPeer.is(); ++n, ++pControls )
2834 {
2835 if ( pControls->is() )
2836 {
2837 Reference< XVclWindowPeer > xCtrlPeer( (*pControls)->getPeer(), UNO_QUERY);
2838 if ( ( xCtrlPeer.get() == xPeer.get() ) || xCtrlPeer->isChild( xPeer ) )
2839 return *pControls;
2840 }
2841 }
2842 return Reference< XControl > ();
2843}
2844
2845
2846void FormController::activateFirst()
2847{
2848 ::osl::MutexGuard aGuard( m_aMutex );
2849 impl_checkDisposed_throw();
2850
2851 DBG_ASSERT(m_xTabController.is(), "FormController::activateFirst : invalid aggregate !")do { if (true && (!(m_xTabController.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2851" ": "), "%s", "FormController::activateFirst : invalid aggregate !"
); } } while (false)
;
2852 if (m_xTabController.is())
2853 m_xTabController->activateFirst();
2854}
2855
2856
2857void FormController::activateLast()
2858{
2859 ::osl::MutexGuard aGuard( m_aMutex );
2860 impl_checkDisposed_throw();
2861
2862 DBG_ASSERT(m_xTabController.is(), "FormController::activateLast : invalid aggregate !")do { if (true && (!(m_xTabController.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2862" ": "), "%s", "FormController::activateLast : invalid aggregate !"
); } } while (false)
;
2863 if (m_xTabController.is())
2864 m_xTabController->activateLast();
2865}
2866
2867// XFormController
2868
2869Reference< XFormOperations > SAL_CALL FormController::getFormOperations()
2870{
2871 ::osl::MutexGuard aGuard( m_aMutex );
2872 impl_checkDisposed_throw();
2873
2874 return m_xFormOperations;
2875}
2876
2877
2878Reference< XControl> SAL_CALL FormController::getCurrentControl()
2879{
2880 ::osl::MutexGuard aGuard( m_aMutex );
2881 impl_checkDisposed_throw();
2882 return m_xCurrentControl;
2883}
2884
2885
2886void SAL_CALL FormController::addActivateListener(const Reference< XFormControllerListener > & l)
2887{
2888 ::osl::MutexGuard aGuard( m_aMutex );
2889 impl_checkDisposed_throw();
2890 m_aActivateListeners.addInterface(l);
2891}
2892
2893void SAL_CALL FormController::removeActivateListener(const Reference< XFormControllerListener > & l)
2894{
2895 ::osl::MutexGuard aGuard( m_aMutex );
2896 impl_checkDisposed_throw();
2897 m_aActivateListeners.removeInterface(l);
2898}
2899
2900
2901void SAL_CALL FormController::addChildController( const Reference< XFormController >& ChildController )
2902{
2903 ::osl::MutexGuard aGuard( m_aMutex );
2904 impl_checkDisposed_throw();
2905
2906 if ( !ChildController.is() )
2907 throw IllegalArgumentException( OUString(), *this, 1 );
2908 // TODO: (localized) error message
2909
2910 // the parent of our (to-be-)child must be our own model
2911 Reference< XFormComponent > xFormOfChild( ChildController->getModel(), UNO_QUERY );
2912 if ( !xFormOfChild.is() )
2913 throw IllegalArgumentException( OUString(), *this, 1 );
2914 // TODO: (localized) error message
2915
2916 if ( xFormOfChild->getParent() != m_xModelAsIndex )
2917 throw IllegalArgumentException( OUString(), *this, 1 );
2918 // TODO: (localized) error message
2919
2920 m_aChildren.push_back( ChildController );
2921 ChildController->setParent( *this );
2922
2923 // search the position of the model within the form
2924 sal_uInt32 nPos = m_xModelAsIndex->getCount();
2925 Reference< XFormComponent > xTemp;
2926 for( ; nPos; )
2927 {
2928 m_xModelAsIndex->getByIndex(--nPos) >>= xTemp;
2929 if ( xFormOfChild == xTemp )
2930 {
2931 m_xModelAsManager->attach( nPos, Reference<XInterface>( ChildController, UNO_QUERY ), makeAny( ChildController) );
2932 break;
2933 }
2934 }
2935}
2936
2937
2938Reference< XFormControllerContext > SAL_CALL FormController::getContext()
2939{
2940 ::osl::MutexGuard aGuard( m_aMutex );
2941 impl_checkDisposed_throw();
2942 return m_xFormControllerContext;
2943}
2944
2945
2946void SAL_CALL FormController::setContext( const Reference< XFormControllerContext >& _context )
2947{
2948 ::osl::MutexGuard aGuard( m_aMutex );
2949 impl_checkDisposed_throw();
2950 m_xFormControllerContext = _context;
2951}
2952
2953
2954Reference< XInteractionHandler > SAL_CALL FormController::getInteractionHandler()
2955{
2956 ::osl::MutexGuard aGuard( m_aMutex );
2957 impl_checkDisposed_throw();
2958 return m_xInteractionHandler;
2959}
2960
2961
2962void SAL_CALL FormController::setInteractionHandler( const Reference< XInteractionHandler >& _interactionHandler )
2963{
2964 ::osl::MutexGuard aGuard( m_aMutex );
2965 impl_checkDisposed_throw();
2966 m_xInteractionHandler = _interactionHandler;
2967}
2968
2969
2970void FormController::setFilter(::std::vector<FmFieldInfo>& rFieldInfos)
2971{
2972 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2972" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
2973 // create the composer
2974 Reference< XRowSet > xForm(m_xModelAsIndex, UNO_QUERY);
2975 Reference< XConnection > xConnection(getConnection(xForm));
2976 if (xForm.is())
2977 {
2978 try
2979 {
2980 Reference< XMultiServiceFactory > xFactory( xConnection, UNO_QUERY_THROW );
2981 m_xComposer.set(
2982 xFactory->createInstance("com.sun.star.sdb.SingleSelectQueryComposer"),
2983 UNO_QUERY_THROW );
2984
2985 Reference< XPropertySet > xSet( xForm, UNO_QUERY );
2986 OUString sStatement = ::comphelper::getString( xSet->getPropertyValue( FM_PROP_ACTIVECOMMAND"ActiveCommand" ) );
2987 OUString sFilter = ::comphelper::getString( xSet->getPropertyValue( FM_PROP_FILTER"Filter" ) );
2988 m_xComposer->setElementaryQuery( sStatement );
2989 m_xComposer->setFilter( sFilter );
2990 }
2991 catch( const Exception& )
2992 {
2993 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "2993" ": ", "svx" );
;
2994 }
2995 }
2996
2997 if (m_xComposer.is())
2998 {
2999 const Sequence< Sequence < PropertyValue > > aFilterRows = m_xComposer->getStructuredFilter();
3000
3001 // ok, we receive the list of filters as sequence of fieldnames, value
3002 // now we have to transform the fieldname into UI names, that could be a label of the field or
3003 // an aliasname or the fieldname itself
3004
3005 // first adjust the field names if necessary
3006 Reference< XNameAccess > xQueryColumns =
3007 Reference< XColumnsSupplier >( m_xComposer, UNO_QUERY_THROW )->getColumns();
3008
3009 for (auto& rFieldInfo : rFieldInfos)
3010 {
3011 if ( xQueryColumns->hasByName(rFieldInfo.aFieldName) )
3012 {
3013 if ( (xQueryColumns->getByName(rFieldInfo.aFieldName) >>= rFieldInfo.xField) && rFieldInfo.xField.is() )
3014 rFieldInfo.xField->getPropertyValue(FM_PROP_REALNAME"RealName") >>= rFieldInfo.aFieldName;
3015 }
3016 }
3017
3018 Reference< XDatabaseMetaData> xMetaData(xConnection->getMetaData());
3019 // now transfer the filters into Value/TextComponent pairs
3020 ::comphelper::UStringMixEqual aCompare(xMetaData->storesMixedCaseQuotedIdentifiers());
3021
3022 // need to parse criteria localized
3023 Reference< XNumberFormatsSupplier> xFormatSupplier( getNumberFormats(xConnection, true));
3024 Reference< XNumberFormatter> xFormatter = NumberFormatter::create(m_xComponentContext);
3025 xFormatter->attachNumberFormatsSupplier(xFormatSupplier);
3026 Locale aAppLocale = Application::GetSettings().GetUILanguageTag().getLocale();
3027 const LocaleDataWrapper& rLocaleWrapper( Application::GetSettings().GetUILocaleDataWrapper() );
3028 OUString strDecimalSeparator = rLocaleWrapper.getNumDecimalSep();
3029
3030 // retrieving the filter
3031 for (const Sequence < PropertyValue >& rRow : aFilterRows)
3032 {
3033 FmFilterRow aRow;
3034
3035 // search a field for the given name
3036 for (const PropertyValue& rRefValue : rRow)
3037 {
3038 // look for the text component
3039 Reference< XPropertySet > xField;
3040 try
3041 {
3042 Reference< XPropertySet > xSet;
3043 OUString aRealName;
3044
3045 // first look with the given name
3046 if (xQueryColumns->hasByName(rRefValue.Name))
3047 {
3048 xQueryColumns->getByName(rRefValue.Name) >>= xSet;
3049
3050 // get the RealName
3051 xSet->getPropertyValue("RealName") >>= aRealName;
3052
3053 // compare the condition field name and the RealName
3054 if (aCompare(aRealName, rRefValue.Name))
3055 xField = xSet;
3056 }
3057 if (!xField.is())
3058 {
3059 // no we have to check every column to find the realname
3060 Reference< XIndexAccess > xColumnsByIndex(xQueryColumns, UNO_QUERY);
3061 for (sal_Int32 n = 0, nCount = xColumnsByIndex->getCount(); n < nCount; n++)
3062 {
3063 xColumnsByIndex->getByIndex(n) >>= xSet;
3064 xSet->getPropertyValue("RealName") >>= aRealName;
3065 if (aCompare(aRealName, rRefValue.Name))
3066 {
3067 // get the column by its alias
3068 xField = xSet;
3069 break;
3070 }
3071 }
3072 }
3073 if (!xField.is())
3074 continue;
3075 }
3076 catch (const Exception&)
3077 {
3078 continue;
3079 }
3080
3081 // find the text component
3082 for (const auto& rFieldInfo : rFieldInfos)
3083 {
3084 // we found the field so insert a new entry to the filter row
3085 if (rFieldInfo.xField == xField)
3086 {
3087 // do we already have the control ?
3088 if (aRow.find(rFieldInfo.xText) != aRow.end())
3089 {
3090 OString aVal = m_pParser->getContext().getIntlKeywordAscii(IParseContext::InternationalKeyCode::And);
3091 OUString aCompText = aRow[rFieldInfo.xText] + " " +
3092 OUString(aVal.getStr(),aVal.getLength(),RTL_TEXTENCODING_ASCII_US(((rtl_TextEncoding) 11))) + " " +
3093 ::comphelper::getString(rRefValue.Value);
3094 aRow[rFieldInfo.xText] = aCompText;
3095 }
3096 else
3097 {
3098 OUString sPredicate,sErrorMsg;
3099 rRefValue.Value >>= sPredicate;
3100 std::unique_ptr< OSQLParseNode > pParseNode = predicateTree(sErrorMsg, sPredicate, xFormatter, xField);
3101 if ( pParseNode != nullptr )
3102 {
3103 OUString sCriteria;
3104 switch (rRefValue.Handle)
3105 {
3106 case css::sdb::SQLFilterOperator::EQUAL:
3107 sCriteria += "=";
3108 break;
3109 case css::sdb::SQLFilterOperator::NOT_EQUAL:
3110 sCriteria += "!=";
3111 break;
3112 case css::sdb::SQLFilterOperator::LESS:
3113 sCriteria += "<";
3114 break;
3115 case css::sdb::SQLFilterOperator::GREATER:
3116 sCriteria += ">";
3117 break;
3118 case css::sdb::SQLFilterOperator::LESS_EQUAL:
3119 sCriteria += "<=";
3120 break;
3121 case css::sdb::SQLFilterOperator::GREATER_EQUAL:
3122 sCriteria += ">=";
3123 break;
3124 case css::sdb::SQLFilterOperator::LIKE:
3125 sCriteria += "LIKE ";
3126 break;
3127 case css::sdb::SQLFilterOperator::NOT_LIKE:
3128 sCriteria += "NOT LIKE ";
3129 break;
3130 case css::sdb::SQLFilterOperator::SQLNULL:
3131 sCriteria += "IS NULL";
3132 break;
3133 case css::sdb::SQLFilterOperator::NOT_SQLNULL:
3134 sCriteria += "IS NOT NULL";
3135 break;
3136 }
3137 pParseNode->parseNodeToPredicateStr( sCriteria
3138 ,xConnection
3139 ,xFormatter
3140 ,xField
3141 ,OUString()
3142 ,aAppLocale
3143 ,strDecimalSeparator
3144 ,getParseContext());
3145 aRow[rFieldInfo.xText] = sCriteria;
3146 }
3147 }
3148 }
3149 }
3150 }
3151
3152 if (aRow.empty())
3153 continue;
3154
3155 impl_addFilterRow( aRow );
3156 }
3157 }
3158
3159 // now set the filter controls
3160 for (const auto& rFieldInfo : rFieldInfos)
3161 {
3162 m_aFilterComponents.push_back( rFieldInfo.xText );
3163 }
3164}
3165
3166
3167void FormController::startFiltering()
3168{
3169 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3169" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
3170
3171 Reference< XConnection > xConnection( getConnection( Reference< XRowSet >( m_xModelAsIndex, UNO_QUERY ) ) );
3172 if ( !xConnection.is() )
3173 // nothing to do - can't filter a form which is not connected
3174 return;
3175
3176 // stop listening for controls
3177 if (isListeningForChanges())
3178 stopListening();
3179
3180 m_bFiltering = true;
3181
3182 // as we don't want new controls to be attached to the scripting environment
3183 // we change attach flags
3184 m_bAttachEvents = false;
3185
3186 // exchanging the controls for the current form
3187 Sequence< Reference< XControl > > aControlsCopy( m_aControls );
3188 const Reference< XControl >* pControls = aControlsCopy.getConstArray();
3189 sal_Int32 nControlCount = aControlsCopy.getLength();
3190
3191 // the control we have to activate after replacement
3192 Reference< XNumberFormatsSupplier > xFormatSupplier = getNumberFormats(xConnection, true);
3193 Reference< XNumberFormatter > xFormatter = NumberFormatter::create(m_xComponentContext);
3194 xFormatter->attachNumberFormatsSupplier(xFormatSupplier);
3195
3196 // structure for storing the field info
3197 ::std::vector<FmFieldInfo> aFieldInfos;
3198
3199 for (sal_Int32 i = nControlCount; i > 0;)
3200 {
3201 Reference< XControl > xControl = pControls[--i];
3202 if (xControl.is())
3203 {
3204 // no events for the control anymore
3205 removeFromEventAttacher(xControl);
3206
3207 // do we have a mode selector
3208 Reference< XModeSelector > xSelector(xControl, UNO_QUERY);
3209 if (xSelector.is())
3210 {
3211 xSelector->setMode( "FilterMode" );
3212
3213 // listening for new controls of the selector
3214 Reference< XContainer > xContainer(xSelector, UNO_QUERY);
3215 if (xContainer.is())
3216 xContainer->addContainerListener(this);
3217
3218 Reference< XEnumerationAccess > xElementAccess(xSelector, UNO_QUERY);
3219 if (xElementAccess.is())
3220 {
3221 Reference< XEnumeration > xEnumeration(xElementAccess->createEnumeration());
3222 Reference< XControl > xSubControl;
3223 while (xEnumeration->hasMoreElements())
3224 {
3225 xEnumeration->nextElement() >>= xSubControl;
3226 if (xSubControl.is())
3227 {
3228 Reference< XPropertySet > xSet(xSubControl->getModel(), UNO_QUERY);
3229 if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD"BoundField", xSet))
3230 {
3231 // does the model use a bound field ?
3232 Reference< XPropertySet > xField;
3233 xSet->getPropertyValue(FM_PROP_BOUNDFIELD"BoundField") >>= xField;
3234
3235 Reference< XTextComponent > xText(xSubControl, UNO_QUERY);
3236 // may we filter the field?
3237 if (xText.is() && xField.is() && ::comphelper::hasProperty(FM_PROP_SEARCHABLE"IsSearchable", xField) &&
3238 ::comphelper::getBOOL(xField->getPropertyValue(FM_PROP_SEARCHABLE"IsSearchable")))
3239 {
3240 aFieldInfos.emplace_back(xField, xText);
3241 xText->addTextListener(this);
3242 }
3243 }
3244 }
3245 }
3246 }
3247 continue;
3248 }
3249
3250 Reference< XPropertySet > xModel( xControl->getModel(), UNO_QUERY );
3251 if (xModel.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD"BoundField", xModel))
3252 {
3253 // does the model use a bound field ?
3254 Any aVal = xModel->getPropertyValue(FM_PROP_BOUNDFIELD"BoundField");
3255 Reference< XPropertySet > xField;
3256 aVal >>= xField;
3257
3258 // may we filter the field?
3259
3260 if ( xField.is()
3261 && ::comphelper::hasProperty( FM_PROP_SEARCHABLE"IsSearchable", xField )
3262 && ::comphelper::getBOOL( xField->getPropertyValue( FM_PROP_SEARCHABLE"IsSearchable" ) )
3263 )
3264 {
3265 // create a filter control
3266 Reference< XControl > xFilterControl = form::control::FilterControl::createWithFormat(
3267 m_xComponentContext,
3268 VCLUnoHelper::GetInterface( getDialogParentWindow() ),
3269 xFormatter,
3270 xModel);
3271
3272 if ( replaceControl( xControl, xFilterControl ) )
3273 {
3274 Reference< XTextComponent > xFilterText( xFilterControl, UNO_QUERY );
3275 aFieldInfos.emplace_back( xField, xFilterText );
3276 xFilterText->addTextListener(this);
3277 }
3278 }
3279 }
3280 else
3281 {
3282 // unsubscribe from EventManager
3283 }
3284 }
3285 }
3286
3287 // we have all filter controls now, so the next step is to read the filters from the form
3288 // resolve all aliases and set the current filter to the according structure
3289 setFilter(aFieldInfos);
3290
3291 Reference< XPropertySet > xSet( m_xModelAsIndex, UNO_QUERY );
3292 if ( xSet.is() )
3293 stopFormListening( xSet, true );
3294
3295 impl_setTextOnAllFilter_throw();
3296
3297 // lock all controls which are not used for filtering
3298 m_bLocked = determineLockState();
3299 setLocks();
3300 m_bAttachEvents = true;
3301}
3302
3303
3304void FormController::stopFiltering()
3305{
3306 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3306" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
3307 if ( !m_bFiltering ) // #104693# OJ
3308 { // nothing to do
3309 return;
3310 }
3311
3312 m_bFiltering = false;
3313 m_bDetachEvents = false;
3314
3315 ::comphelper::disposeComponent(m_xComposer);
3316
3317 // exchanging the controls for the current form
3318 Sequence< Reference< XControl > > aControlsCopy( m_aControls );
3319 const Reference< XControl > * pControls = aControlsCopy.getConstArray();
3320 sal_Int32 nControlCount = aControlsCopy.getLength();
3321
3322 // clear the filter control map
3323 ::std::for_each( m_aFilterComponents.begin(), m_aFilterComponents.end(), RemoveComponentTextListener( this ) );
3324 m_aFilterComponents.clear();
3325
3326 for ( sal_Int32 i = nControlCount; i > 0; )
3327 {
3328 Reference< XControl > xControl = pControls[--i];
3329 if (xControl.is())
3330 {
3331 // now enable event handling again
3332 addToEventAttacher(xControl);
3333
3334 Reference< XModeSelector > xSelector(xControl, UNO_QUERY);
3335 if (xSelector.is())
3336 {
3337 xSelector->setMode( "DataMode" );
3338
3339 // listening for new controls of the selector
3340 Reference< XContainer > xContainer(xSelector, UNO_QUERY);
3341 if (xContainer.is())
3342 xContainer->removeContainerListener(this);
3343 continue;
3344 }
3345
3346 Reference< XPropertySet > xSet(xControl->getModel(), UNO_QUERY);
3347 if (xSet.is() && ::comphelper::hasProperty(FM_PROP_BOUNDFIELD"BoundField", xSet))
3348 {
3349 // does the model use a bound field ?
3350 Reference< XPropertySet > xField;
3351 xSet->getPropertyValue(FM_PROP_BOUNDFIELD"BoundField") >>= xField;
3352
3353 // may we filter the field?
3354 if ( xField.is()
3355 && ::comphelper::hasProperty( FM_PROP_SEARCHABLE"IsSearchable", xField )
3356 && ::comphelper::getBOOL( xField->getPropertyValue( FM_PROP_SEARCHABLE"IsSearchable" ) )
3357 )
3358 {
3359 OUString sServiceName;
3360 OSL_VERIFY( xSet->getPropertyValue( FM_PROP_DEFAULTCONTROL ) >>= sServiceName )do { if (!(xSet->getPropertyValue( "DefaultControl" ) >>=
sServiceName)) do { if (true && (!(0))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3360" ": "), "OSL_ASSERT: %s", "0"); } } while (false);
} while (0)
;
3361 Reference< XControl > xNewControl( m_xComponentContext->getServiceManager()->createInstanceWithContext( sServiceName, m_xComponentContext ), UNO_QUERY );
3362 replaceControl( xControl, xNewControl );
3363 }
3364 }
3365 }
3366 }
3367
3368 Reference< XPropertySet > xSet( m_xModelAsIndex, UNO_QUERY );
3369 if ( xSet.is() )
3370 startFormListening( xSet, true );
3371
3372 m_bDetachEvents = true;
3373
3374 m_aFilterRows.clear();
3375 m_nCurrentFilterPosition = -1;
3376
3377 // release the locks if possible
3378 // lock all controls which are not used for filtering
3379 m_bLocked = determineLockState();
3380 setLocks();
3381
3382 // restart listening for control modifications
3383 if (isListeningForChanges())
3384 startListening();
3385}
3386
3387// XModeSelector
3388
3389void FormController::setMode(const OUString& Mode)
3390{
3391 ::osl::MutexGuard aGuard( m_aMutex );
3392 impl_checkDisposed_throw();
3393
3394 if (!supportsMode(Mode))
3395 throw NoSupportException();
3396
3397 if (Mode == m_aMode)
3398 return;
3399
3400 m_aMode = Mode;
3401
3402 if ( Mode == "FilterMode" )
3403 startFiltering();
3404 else
3405 stopFiltering();
3406
3407 for (const auto& rChild : m_aChildren)
3408 {
3409 Reference< XModeSelector > xMode(rChild, UNO_QUERY);
3410 if ( xMode.is() )
3411 xMode->setMode(Mode);
3412 }
3413}
3414
3415
3416OUString SAL_CALL FormController::getMode()
3417{
3418 ::osl::MutexGuard aGuard( m_aMutex );
3419 impl_checkDisposed_throw();
3420
3421 return m_aMode;
3422}
3423
3424
3425Sequence< OUString > SAL_CALL FormController::getSupportedModes()
3426{
3427 ::osl::MutexGuard aGuard( m_aMutex );
3428 impl_checkDisposed_throw();
3429
3430 static Sequence< OUString > const aModes
3431 {
3432 "DataMode",
3433 "FilterMode"
3434 };
3435 return aModes;
3436}
3437
3438
3439sal_Bool SAL_CALL FormController::supportsMode(const OUString& Mode)
3440{
3441 ::osl::MutexGuard aGuard( m_aMutex );
3442 impl_checkDisposed_throw();
3443
3444 Sequence< OUString > aModes(getSupportedModes());
3445 return comphelper::findValue(aModes, Mode) != -1;
3446}
3447
3448
3449vcl::Window* FormController::getDialogParentWindow()
3450{
3451 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3451" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
3
Assuming the condition is true
4
Taking false branch
5
Loop condition is false. Exiting loop
3452 vcl::Window* pParentWindow = nullptr;
3453 try
3454 {
3455 Reference< XControl > xContainerControl( getContainer(), UNO_QUERY_THROW );
3456 Reference< XWindowPeer > xContainerPeer( xContainerControl->getPeer(), UNO_SET_THROW );
3457 pParentWindow = VCLUnoHelper::GetWindow( xContainerPeer ).get();
6
Calling implicit destructor for 'VclPtr<vcl::Window>'
7
Calling '~Reference'
15
Returning from '~Reference'
16
Returning from destructor for 'VclPtr<vcl::Window>'
3458 }
3459 catch( const Exception& )
3460 {
3461 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3461" ": ", "svx" );
;
3462 }
3463 return pParentWindow;
17
Use of memory after it is freed
3464}
3465
3466bool FormController::checkFormComponentValidity( OUString& /* [out] */ _rFirstInvalidityExplanation, Reference< XControlModel >& /* [out] */ _rxFirstInvalidModel )
3467{
3468 try
3469 {
3470 Reference< XEnumerationAccess > xControlEnumAcc( getModel(), UNO_QUERY );
3471 Reference< XEnumeration > xControlEnumeration;
3472 if ( xControlEnumAcc.is() )
3473 xControlEnumeration = xControlEnumAcc->createEnumeration();
3474 OSL_ENSURE( xControlEnumeration.is(), "FormController::checkFormComponentValidity: cannot enumerate the controls!" )do { if (true && (!(xControlEnumeration.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3474" ": "), "%s", "FormController::checkFormComponentValidity: cannot enumerate the controls!"
); } } while (false)
;
3475 if ( !xControlEnumeration.is() )
3476 // assume all valid
3477 return true;
3478
3479 Reference< XValidatableFormComponent > xValidatable;
3480 while ( xControlEnumeration->hasMoreElements() )
3481 {
3482 if ( !( xControlEnumeration->nextElement() >>= xValidatable ) )
3483 // control does not support validation
3484 continue;
3485
3486 if ( xValidatable->isValid() )
3487 continue;
3488
3489 Reference< XValidator > xValidator( xValidatable->getValidator() );
3490 OSL_ENSURE( xValidator.is(), "FormController::checkFormComponentValidity: invalid, but no validator?" )do { if (true && (!(xValidator.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3490" ": "), "%s", "FormController::checkFormComponentValidity: invalid, but no validator?"
); } } while (false)
;
3491 if ( !xValidator.is() )
3492 // this violates the interface definition of css.form.validation.XValidatableFormComponent ...
3493 continue;
3494
3495 _rFirstInvalidityExplanation = xValidator->explainInvalid( xValidatable->getCurrentValue() );
3496 _rxFirstInvalidModel.set(xValidatable, css::uno::UNO_QUERY);
3497 return false;
3498 }
3499 }
3500 catch( const Exception& )
3501 {
3502 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3502" ": ", "svx" );
;
3503 }
3504 return true;
3505}
3506
3507
3508Reference< XControl > FormController::locateControl( const Reference< XControlModel >& _rxModel )
3509{
3510 try
3511 {
3512 const Sequence< Reference< XControl > > aControls( getControls() );
3513
3514 for ( auto const & control : aControls )
3515 {
3516 OSL_ENSURE( control.is(), "FormController::locateControl: NULL-control?" )do { if (true && (!(control.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3516" ": "), "%s", "FormController::locateControl: NULL-control?"
); } } while (false)
;
3517 if ( control.is() )
3518 {
3519 if ( control->getModel() == _rxModel )
3520 return control;
3521 }
3522 }
3523 OSL_FAIL( "FormController::locateControl: did not find a control for this model!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3523" ": "), "%s", "FormController::locateControl: did not find a control for this model!"
); } } while (false)
;
3524 }
3525 catch( const Exception& )
3526 {
3527 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3527" ": ", "svx" );
;
3528 }
3529 return nullptr;
3530}
3531
3532
3533namespace
3534{
3535 void displayErrorSetFocus( const OUString& _rMessage, const Reference< XControl >& _rxFocusControl, vcl::Window* _pDialogParent )
3536 {
3537 SQLContext aError;
3538 aError.Message = SvxResId(RID_STR_WRITEERRORreinterpret_cast<char const *>("RID_STR_WRITEERROR" "\004"
u8"Error writing data to database")
);
3539 aError.Details = _rMessage;
3540 displayException( aError, _pDialogParent );
3541
3542 if ( _rxFocusControl.is() )
3543 {
3544 Reference< XWindow > xControlWindow( _rxFocusControl, UNO_QUERY );
3545 OSL_ENSURE( xControlWindow.is(), "displayErrorSetFocus: invalid control!" )do { if (true && (!(xControlWindow.is()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3545" ": "), "%s", "displayErrorSetFocus: invalid control!"
); } } while (false)
;
3546 if ( xControlWindow.is() )
3547 xControlWindow->setFocus();
3548 }
3549 }
3550
3551 bool lcl_shouldValidateRequiredFields_nothrow( const Reference< XInterface >& _rxForm )
3552 {
3553 try
3554 {
3555 static const char s_sFormsCheckRequiredFields[] = "FormsCheckRequiredFields";
3556
3557 // first, check whether the form has a property telling us the answer
3558 // this allows people to use the XPropertyContainer interface of a form to control
3559 // the behaviour on a per-form basis.
3560 Reference< XPropertySet > xFormProps( _rxForm, UNO_QUERY_THROW );
3561 Reference< XPropertySetInfo > xPSI( xFormProps->getPropertySetInfo() );
3562 if ( xPSI->hasPropertyByName( s_sFormsCheckRequiredFields ) )
3563 {
3564 bool bShouldValidate = true;
3565 OSL_VERIFY( xFormProps->getPropertyValue( s_sFormsCheckRequiredFields ) >>= bShouldValidate )do { if (!(xFormProps->getPropertyValue( s_sFormsCheckRequiredFields
) >>= bShouldValidate)) do { if (true && (!(0)
)) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3565" ": "), "OSL_ASSERT: %s", "0"); } } while (false);
} while (0)
;
3566 return bShouldValidate;
3567 }
3568
3569 // next, check the data source which created the connection
3570 Reference< XChild > xConnectionAsChild( xFormProps->getPropertyValue( FM_PROP_ACTIVE_CONNECTION"ActiveConnection" ), UNO_QUERY_THROW );
3571 Reference< XPropertySet > xDataSource( xConnectionAsChild->getParent(), UNO_QUERY );
3572 if ( !xDataSource.is() )
3573 // seldom (but possible): this is not a connection created by a data source
3574 return true;
3575
3576 Reference< XPropertySet > xDataSourceSettings(
3577 xDataSource->getPropertyValue("Settings"),
3578 UNO_QUERY_THROW );
3579
3580 bool bShouldValidate = true;
3581 OSL_VERIFY( xDataSourceSettings->getPropertyValue( s_sFormsCheckRequiredFields ) >>= bShouldValidate )do { if (!(xDataSourceSettings->getPropertyValue( s_sFormsCheckRequiredFields
) >>= bShouldValidate)) do { if (true && (!(0)
)) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3581" ": "), "OSL_ASSERT: %s", "0"); } } while (false);
} while (0)
;
3582 return bShouldValidate;
3583 }
3584 catch( const Exception& )
3585 {
3586 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3586" ": ", "svx" );
;
3587 }
3588
3589 return true;
3590 }
3591}
3592
3593// XRowSetApproveListener
3594
3595sal_Bool SAL_CALL FormController::approveRowChange(const RowChangeEvent& _rEvent)
3596{
3597 ::osl::ClearableMutexGuard aGuard( m_aMutex );
3598 impl_checkDisposed_throw();
3599
3600 ::comphelper::OInterfaceIteratorHelper2 aIter(m_aRowSetApproveListeners);
3601 bool bValid = true;
3602 if (aIter.hasMoreElements())
3603 {
3604 RowChangeEvent aEvt( _rEvent );
3605 aEvt.Source = *this;
3606 bValid = static_cast<XRowSetApproveListener*>(aIter.next())->approveRowChange(aEvt);
3607 }
3608
3609 if ( !bValid )
3610 return bValid;
3611
3612 if ( ( _rEvent.Action != RowChangeAction::INSERT )
3613 && ( _rEvent.Action != RowChangeAction::UPDATE )
3614 )
3615 return bValid;
3616
3617 // if some of the control models are bound to validators, check them
3618 OUString sInvalidityExplanation;
3619 Reference< XControlModel > xInvalidModel;
3620 if ( !checkFormComponentValidity( sInvalidityExplanation, xInvalidModel ) )
3621 {
3622 Reference< XControl > xControl( locateControl( xInvalidModel ) );
3623 aGuard.clear();
3624 displayErrorSetFocus( sInvalidityExplanation, xControl, getDialogParentWindow() );
3625 return false;
3626 }
3627
3628 // check values on NULL and required flag
3629 if ( !lcl_shouldValidateRequiredFields_nothrow( _rEvent.Source ) )
3630 return true;
3631
3632 OSL_ENSURE(m_pColumnInfoCache, "FormController::approveRowChange: no column infos!")do { if (true && (!(m_pColumnInfoCache))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3632" ": "), "%s", "FormController::approveRowChange: no column infos!"
); } } while (false)
;
3633 if (!m_pColumnInfoCache)
3634 return true;
3635
3636 try
3637 {
3638 if ( !m_pColumnInfoCache->controlsInitialized() )
3639 m_pColumnInfoCache->initializeControls( getControls() );
3640
3641 size_t colCount = m_pColumnInfoCache->getColumnCount();
3642 for ( size_t col = 0; col < colCount; ++col )
3643 {
3644 const ColumnInfo& rColInfo = m_pColumnInfoCache->getColumnInfo( col );
3645
3646 if ( rColInfo.bAutoIncrement )
3647 continue;
3648
3649 if ( rColInfo.bReadOnly )
3650 continue;
3651
3652 if ( !rColInfo.xFirstControlWithInputRequired.is() && !rColInfo.xFirstGridWithInputRequiredColumn.is() )
3653 {
3654 continue;
3655 }
3656
3657 // TODO: in case of binary fields, this "getString" below is extremely expensive
3658 if ( !rColInfo.xColumn->wasNull() || !rColInfo.xColumn->getString().isEmpty() )
3659 continue;
3660
3661 OUString sMessage( SvxResId( RID_ERR_FIELDREQUIREDreinterpret_cast<char const *>("RID_ERR_FIELDREQUIRED" "\004"
u8"Input required in field '#'. Please enter a value.")
) );
3662 sMessage = sMessage.replaceFirst( "#", rColInfo.sName );
3663
3664 // the control to focus
3665 Reference< XControl > xControl( rColInfo.xFirstControlWithInputRequired );
3666 if ( !xControl.is() )
3667 xControl.set( rColInfo.xFirstGridWithInputRequiredColumn, UNO_QUERY );
3668
3669 aGuard.clear();
3670 displayErrorSetFocus( sMessage, rColInfo.xFirstControlWithInputRequired, getDialogParentWindow() );
3671 return false;
3672 }
3673 }
3674 catch( const Exception& )
3675 {
3676 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3676" ": ", "svx" );
;
3677 }
3678
3679 return true;
3680}
3681
3682
3683sal_Bool SAL_CALL FormController::approveCursorMove(const EventObject& event)
3684{
3685 ::osl::MutexGuard aGuard( m_aMutex );
3686 impl_checkDisposed_throw();
3687
3688 ::comphelper::OInterfaceIteratorHelper2 aIter(m_aRowSetApproveListeners);
3689 if (aIter.hasMoreElements())
3690 {
3691 EventObject aEvt(event);
3692 aEvt.Source = *this;
3693 return static_cast<XRowSetApproveListener*>(aIter.next())->approveCursorMove(aEvt);
3694 }
3695
3696 return true;
3697}
3698
3699
3700sal_Bool SAL_CALL FormController::approveRowSetChange(const EventObject& event)
3701{
3702 ::osl::MutexGuard aGuard( m_aMutex );
3703 impl_checkDisposed_throw();
3704
3705 ::comphelper::OInterfaceIteratorHelper2 aIter(m_aRowSetApproveListeners);
3706 if (aIter.hasMoreElements())
3707 {
3708 EventObject aEvt(event);
3709 aEvt.Source = *this;
3710 return static_cast<XRowSetApproveListener*>(aIter.next())->approveRowSetChange(aEvt);
3711 }
3712
3713 return true;
3714}
3715
3716// XRowSetApproveBroadcaster
3717
3718void SAL_CALL FormController::addRowSetApproveListener(const Reference< XRowSetApproveListener > & _rxListener)
3719{
3720 ::osl::MutexGuard aGuard( m_aMutex );
3721 impl_checkDisposed_throw();
3722
3723 m_aRowSetApproveListeners.addInterface(_rxListener);
3724}
3725
3726
3727void SAL_CALL FormController::removeRowSetApproveListener(const Reference< XRowSetApproveListener > & _rxListener)
3728{
3729 ::osl::MutexGuard aGuard( m_aMutex );
3730 impl_checkDisposed_throw();
3731
3732 m_aRowSetApproveListeners.removeInterface(_rxListener);
3733}
3734
3735// XErrorListener
3736
3737void SAL_CALL FormController::errorOccured(const SQLErrorEvent& aEvent)
3738{
3739 ::osl::ClearableMutexGuard aGuard( m_aMutex );
3740 impl_checkDisposed_throw();
3741
3742 ::comphelper::OInterfaceIteratorHelper2 aIter(m_aErrorListeners);
3743 if (aIter.hasMoreElements())
1
Taking false branch
3744 {
3745 SQLErrorEvent aEvt(aEvent);
3746 aEvt.Source = *this;
3747 static_cast<XSQLErrorListener*>(aIter.next())->errorOccured(aEvt);
3748 }
3749 else
3750 {
3751 aGuard.clear();
3752 displayException(aEvent, getDialogParentWindow());
2
Calling 'FormController::getDialogParentWindow'
3753 }
3754}
3755
3756// XErrorBroadcaster
3757
3758void SAL_CALL FormController::addSQLErrorListener(const Reference< XSQLErrorListener > & aListener)
3759{
3760 ::osl::MutexGuard aGuard( m_aMutex );
3761 impl_checkDisposed_throw();
3762
3763 m_aErrorListeners.addInterface(aListener);
3764}
3765
3766
3767void SAL_CALL FormController::removeSQLErrorListener(const Reference< XSQLErrorListener > & aListener)
3768{
3769 ::osl::MutexGuard aGuard( m_aMutex );
3770 impl_checkDisposed_throw();
3771
3772 m_aErrorListeners.removeInterface(aListener);
3773}
3774
3775// XDatabaseParameterBroadcaster2
3776
3777void SAL_CALL FormController::addDatabaseParameterListener(const Reference< XDatabaseParameterListener > & aListener)
3778{
3779 ::osl::MutexGuard aGuard( m_aMutex );
3780 impl_checkDisposed_throw();
3781
3782 m_aParameterListeners.addInterface(aListener);
3783}
3784
3785
3786void SAL_CALL FormController::removeDatabaseParameterListener(const Reference< XDatabaseParameterListener > & aListener)
3787{
3788 ::osl::MutexGuard aGuard( m_aMutex );
3789 impl_checkDisposed_throw();
3790
3791 m_aParameterListeners.removeInterface(aListener);
3792}
3793
3794// XDatabaseParameterBroadcaster
3795
3796void SAL_CALL FormController::addParameterListener(const Reference< XDatabaseParameterListener > & aListener)
3797{
3798 FormController::addDatabaseParameterListener( aListener );
3799}
3800
3801
3802void SAL_CALL FormController::removeParameterListener(const Reference< XDatabaseParameterListener > & aListener)
3803{
3804 FormController::removeDatabaseParameterListener( aListener );
3805}
3806
3807// XDatabaseParameterListener
3808
3809sal_Bool SAL_CALL FormController::approveParameter(const DatabaseParameterEvent& aEvent)
3810{
3811 SolarMutexGuard aSolarGuard;
3812 ::osl::MutexGuard aGuard( m_aMutex );
3813 impl_checkDisposed_throw();
3814
3815 ::comphelper::OInterfaceIteratorHelper2 aIter(m_aParameterListeners);
3816 if (aIter.hasMoreElements())
3817 {
3818 DatabaseParameterEvent aEvt(aEvent);
3819 aEvt.Source = *this;
3820 return static_cast<XDatabaseParameterListener*>(aIter.next())->approveParameter(aEvt);
3821 }
3822 else
3823 {
3824 // default handling: instantiate an interaction handler and let it handle the parameter request
3825 try
3826 {
3827 if ( !ensureInteractionHandler() )
3828 return false;
3829
3830 // two continuations allowed: OK and Cancel
3831 OParameterContinuation* pParamValues = new OParameterContinuation;
3832 OInteractionAbort* pAbort = new OInteractionAbort;
3833 // the request
3834 ParametersRequest aRequest;
3835 aRequest.Parameters = aEvent.Parameters;
3836 aRequest.Connection = getConnection(Reference< XRowSet >(aEvent.Source, UNO_QUERY));
3837 OInteractionRequest* pParamRequest = new OInteractionRequest(makeAny(aRequest));
3838 Reference< XInteractionRequest > xParamRequest(pParamRequest);
3839 // some knittings
3840 pParamRequest->addContinuation(pParamValues);
3841 pParamRequest->addContinuation(pAbort);
3842
3843 // handle the request
3844 m_xInteractionHandler->handle(xParamRequest);
3845
3846 if (!pParamValues->wasSelected())
3847 // canceled
3848 return false;
3849
3850 // transfer the values into the parameter supplier
3851 Sequence< PropertyValue > aFinalValues = pParamValues->getValues();
3852 if (aFinalValues.getLength() != aRequest.Parameters->getCount())
3853 {
3854 OSL_FAIL("FormController::approveParameter: the InteractionHandler returned nonsense!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3854" ": "), "%s", "FormController::approveParameter: the InteractionHandler returned nonsense!"
); } } while (false)
;
3855 return false;
3856 }
3857 const PropertyValue* pFinalValues = aFinalValues.getConstArray();
3858 for (sal_Int32 i=0; i<aFinalValues.getLength(); ++i, ++pFinalValues)
3859 {
3860 Reference< XPropertySet > xParam(
3861 aRequest.Parameters->getByIndex(i), css::uno::UNO_QUERY);
3862 if (xParam.is())
3863 {
3864#ifdef DBG_UTIL
3865 OUString sName;
3866 xParam->getPropertyValue(FM_PROP_NAME"Name") >>= sName;
3867 DBG_ASSERT(sName == pFinalValues->Name, "FormController::approveParameter: suspicious value names!")do { if (true && (!(sName == pFinalValues->Name)))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.tools"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3867" ": "), "%s", "FormController::approveParameter: suspicious value names!"
); } } while (false)
;
3868#endif
3869 try { xParam->setPropertyValue(FM_PROP_VALUE"Value", pFinalValues->Value); }
3870 catch(Exception&)
3871 {
3872 OSL_FAIL("FormController::approveParameter: setting one of the properties failed!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3872" ": "), "%s", "FormController::approveParameter: setting one of the properties failed!"
); } } while (false)
;
3873 }
3874 }
3875 }
3876 }
3877 catch(Exception&)
3878 {
3879 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3879" ": ", "svx" );
;
3880 }
3881 }
3882 return true;
3883}
3884
3885// XConfirmDeleteBroadcaster
3886
3887void SAL_CALL FormController::addConfirmDeleteListener(const Reference< XConfirmDeleteListener > & aListener)
3888{
3889 ::osl::MutexGuard aGuard( m_aMutex );
3890 impl_checkDisposed_throw();
3891
3892 m_aDeleteListeners.addInterface(aListener);
3893}
3894
3895
3896void SAL_CALL FormController::removeConfirmDeleteListener(const Reference< XConfirmDeleteListener > & aListener)
3897{
3898 ::osl::MutexGuard aGuard( m_aMutex );
3899 impl_checkDisposed_throw();
3900
3901 m_aDeleteListeners.removeInterface(aListener);
3902}
3903
3904// XConfirmDeleteListener
3905
3906sal_Bool SAL_CALL FormController::confirmDelete(const RowChangeEvent& aEvent)
3907{
3908 ::osl::MutexGuard aGuard( m_aMutex );
3909 impl_checkDisposed_throw();
3910
3911 ::comphelper::OInterfaceIteratorHelper2 aIter(m_aDeleteListeners);
3912 if (aIter.hasMoreElements())
3913 {
3914 RowChangeEvent aEvt(aEvent);
3915 aEvt.Source = *this;
3916 return static_cast<XConfirmDeleteListener*>(aIter.next())->confirmDelete(aEvt);
3917 }
3918 // default handling: instantiate an interaction handler and let it handle the request
3919
3920 OUString sTitle;
3921 sal_Int32 nLength = aEvent.Rows;
3922 if ( nLength > 1 )
3923 {
3924 sTitle = SvxResId( RID_STR_DELETECONFIRM_RECORDSreinterpret_cast<char const *>("RID_STR_DELETECONFIRM_RECORDS"
"\004" u8"# records will be deleted.")
);
3925 sTitle = sTitle.replaceFirst( "#", OUString::number(nLength) );
3926 }
3927 else
3928 sTitle = SvxResId( RID_STR_DELETECONFIRM_RECORDreinterpret_cast<char const *>("RID_STR_DELETECONFIRM_RECORD"
"\004" u8"You intend to delete 1 record.")
);
3929
3930 try
3931 {
3932 if ( !ensureInteractionHandler() )
3933 return false;
3934
3935 // two continuations allowed: Yes and No
3936 OInteractionApprove* pApprove = new OInteractionApprove;
3937 OInteractionDisapprove* pDisapprove = new OInteractionDisapprove;
3938
3939 // the request
3940 SQLWarning aWarning;
3941 aWarning.Message = sTitle;
3942 SQLWarning aDetails;
3943 aDetails.Message = SvxResId(RID_STR_DELETECONFIRMreinterpret_cast<char const *>("RID_STR_DELETECONFIRM" "\004"
u8"If you click Yes, you won't be able to undo this operation.\nDo you want to continue anyway?"
)
);
3944 aWarning.NextException <<= aDetails;
3945
3946 OInteractionRequest* pRequest = new OInteractionRequest( makeAny( aWarning ) );
3947 Reference< XInteractionRequest > xRequest( pRequest );
3948
3949 // some knittings
3950 pRequest->addContinuation( pApprove );
3951 pRequest->addContinuation( pDisapprove );
3952
3953 // handle the request
3954 m_xInteractionHandler->handle( xRequest );
3955
3956 if ( pApprove->wasSelected() )
3957 return true;
3958 }
3959 catch( const Exception& )
3960 {
3961 DBG_UNHANDLED_EXCEPTION("svx")DbgUnhandledException( DbgGetCaughtException(), __func__, "/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3961" ": ", "svx" );
;
3962 }
3963
3964 return false;
3965}
3966
3967
3968void SAL_CALL FormController::invalidateFeatures( const Sequence< ::sal_Int16 >& Features )
3969{
3970 ::osl::MutexGuard aGuard( m_aMutex );
3971 // for now, just copy the ids of the features, because...
3972 m_aInvalidFeatures.insert( Features.begin(), Features.end() );
3973
3974 // ... we will do the real invalidation asynchronously
3975 if ( !m_aFeatureInvalidationTimer.IsActive() )
3976 m_aFeatureInvalidationTimer.Start();
3977}
3978
3979
3980void SAL_CALL FormController::invalidateAllFeatures( )
3981{
3982 ::osl::ClearableMutexGuard aGuard( m_aMutex );
3983
3984 Sequence< sal_Int16 > aInterceptedFeatures( comphelper::mapKeysToSequence(m_aFeatureDispatchers) );
3985
3986 aGuard.clear();
3987 if ( aInterceptedFeatures.hasElements() )
3988 invalidateFeatures( aInterceptedFeatures );
3989}
3990
3991
3992Reference< XDispatch >
3993FormController::interceptedQueryDispatch( const URL& aURL,
3994 const OUString& /*aTargetFrameName*/, sal_Int32 /*nSearchFlags*/)
3995{
3996 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "3996" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
3997 Reference< XDispatch > xReturn;
3998 // dispatches handled by ourself
3999 if ( ( aURL.Complete == FMURL_CONFIRM_DELETION".uno:FormSlots/ConfirmDeletion" )
4000 || ( ( aURL.Complete == "private:/InteractionHandler" )
4001 && ensureInteractionHandler()
4002 )
4003 )
4004 xReturn = static_cast< XDispatch* >( this );
4005
4006 // dispatches of FormSlot-URLs we have to translate
4007 if ( !xReturn.is() && m_xFormOperations.is() )
4008 {
4009 // find the slot id which corresponds to the URL
4010 sal_Int32 nFeatureSlotId = svx::FeatureSlotTranslation::getControllerFeatureSlotIdForURL( aURL.Main );
4011 sal_Int16 nFormFeature = ( nFeatureSlotId != -1 ) ? svx::FeatureSlotTranslation::getFormFeatureForSlotId( nFeatureSlotId ) : -1;
4012 if ( nFormFeature > 0 )
4013 {
4014 // get the dispatcher for this feature, create if necessary
4015 DispatcherContainer::const_iterator aDispatcherPos = m_aFeatureDispatchers.find( nFormFeature );
4016 if ( aDispatcherPos == m_aFeatureDispatchers.end() )
4017 {
4018 aDispatcherPos = m_aFeatureDispatchers.emplace(
4019 nFormFeature, new svx::OSingleFeatureDispatcher( aURL, nFormFeature, m_xFormOperations, m_aMutex )
4020 ).first;
4021 }
4022
4023 OSL_ENSURE( aDispatcherPos->second.is(), "FormController::interceptedQueryDispatch: should have a dispatcher by now!" )do { if (true && (!(aDispatcherPos->second.is())))
{ sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "4023" ": "), "%s", "FormController::interceptedQueryDispatch: should have a dispatcher by now!"
); } } while (false)
;
4024 return aDispatcherPos->second;
4025 }
4026 }
4027
4028 // no more to offer
4029 return xReturn;
4030}
4031
4032
4033void SAL_CALL FormController::dispatch( const URL& _rURL, const Sequence< PropertyValue >& _rArgs )
4034{
4035 if ( _rArgs.getLength() != 1 )
4036 {
4037 OSL_FAIL( "FormController::dispatch: no arguments -> no dispatch!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "4037" ": "), "%s", "FormController::dispatch: no arguments -> no dispatch!"
); } } while (false)
;
4038 return;
4039 }
4040
4041 if ( _rURL.Complete == "private:/InteractionHandler" )
4042 {
4043 Reference< XInteractionRequest > xRequest;
4044 OSL_VERIFY( _rArgs[0].Value >>= xRequest )do { if (!(_rArgs[0].Value >>= xRequest)) do { if (true
&& (!(0))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN
), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "4044" ": "), "OSL_ASSERT: %s", "0"); } } while (false);
} while (0)
;
4045 if ( xRequest.is() )
4046 handle( xRequest );
4047 return;
4048 }
4049
4050 if ( _rURL.Complete == FMURL_CONFIRM_DELETION".uno:FormSlots/ConfirmDeletion" )
4051 {
4052 OSL_FAIL( "FormController::dispatch: How do you expect me to return something via this call?" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "4052" ": "), "%s", "FormController::dispatch: How do you expect me to return something via this call?"
); } } while (false)
;
4053 // confirmDelete has a return value - dispatch hasn't
4054 return;
4055 }
4056
4057 OSL_FAIL( "FormController::dispatch: unknown URL!" )do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "4057" ": "), "%s", "FormController::dispatch: unknown URL!"
); } } while (false)
;
4058}
4059
4060
4061void SAL_CALL FormController::addStatusListener( const Reference< XStatusListener >& _rxListener, const URL& _rURL )
4062{
4063 if (_rURL.Complete == FMURL_CONFIRM_DELETION".uno:FormSlots/ConfirmDeletion")
4064 {
4065 if (_rxListener.is())
4066 { // send an initial statusChanged event
4067 FeatureStateEvent aEvent;
4068 aEvent.FeatureURL = _rURL;
4069 aEvent.IsEnabled = true;
4070 _rxListener->statusChanged(aEvent);
4071 // and don't add the listener at all (the status will never change)
4072 }
4073 }
4074 else
4075 OSL_FAIL("FormController::addStatusListener: invalid (unsupported) URL!")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "4075" ": "), "%s", "FormController::addStatusListener: invalid (unsupported) URL!"
); } } while (false)
;
4076}
4077
4078
4079Reference< XInterface > SAL_CALL FormController::getParent()
4080{
4081 return m_xParent;
4082}
4083
4084
4085void SAL_CALL FormController::setParent( const Reference< XInterface >& Parent)
4086{
4087 m_xParent = Parent;
4088}
4089
4090
4091void SAL_CALL FormController::removeStatusListener( const Reference< XStatusListener >& /*_rxListener*/, const URL& _rURL )
4092{
4093 OSL_ENSURE(_rURL.Complete == FMURL_CONFIRM_DELETION, "FormController::removeStatusListener: invalid (unsupported) URL!")do { if (true && (!(_rURL.Complete == ".uno:FormSlots/ConfirmDeletion"
))) { sal_detail_logFormat((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"
), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "4093" ": "), "%s", "FormController::removeStatusListener: invalid (unsupported) URL!"
); } } while (false)
;
4094 // we never really added the listener, so we don't need to remove it
4095}
4096
4097
4098Reference< XDispatchProviderInterceptor > FormController::createInterceptor(const Reference< XDispatchProviderInterception > & _xInterception)
4099{
4100 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "4100" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
4101#ifdef DBG_UTIL
4102 // check if we already have an interceptor for the given object
4103 for ( const auto & it : m_aControlDispatchInterceptors )
4104 {
4105 if (it->getIntercepted() == _xInterception)
4106 OSL_FAIL("FormController::createInterceptor : we already do intercept this objects dispatches !")do { if (true && (((sal_Bool)1))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "4106" ": "), "%s", "FormController::createInterceptor : we already do intercept this objects dispatches !"
); } } while (false)
;
4107 }
4108#endif
4109
4110 rtl::Reference<DispatchInterceptionMultiplexer> pInterceptor(new DispatchInterceptionMultiplexer( _xInterception, this ));
4111 m_aControlDispatchInterceptors.push_back( pInterceptor );
4112
4113 return pInterceptor.get();
4114}
4115
4116
4117bool FormController::ensureInteractionHandler()
4118{
4119 if ( m_xInteractionHandler.is() )
4120 return true;
4121 if ( m_bAttemptedHandlerCreation )
4122 return false;
4123 m_bAttemptedHandlerCreation = true;
4124
4125 m_xInteractionHandler = InteractionHandler::createWithParent(m_xComponentContext,
4126 VCLUnoHelper::GetInterface(getDialogParentWindow()));
4127 return m_xInteractionHandler.is();
4128}
4129
4130
4131void SAL_CALL FormController::handle( const Reference< XInteractionRequest >& _rRequest )
4132{
4133 if ( !ensureInteractionHandler() )
4134 return;
4135 m_xInteractionHandler->handle( _rRequest );
4136}
4137
4138
4139void FormController::deleteInterceptor(const Reference< XDispatchProviderInterception > & _xInterception)
4140{
4141 OSL_ENSURE( !impl_isDisposed_nofail(), "FormController: already disposed!" )do { if (true && (!(!impl_isDisposed_nofail()))) { sal_detail_logFormat
((SAL_DETAIL_LOG_LEVEL_WARN), ("legacy.osl"), ("/home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx"
":" "4141" ": "), "%s", "FormController: already disposed!")
; } } while (false)
;
4142 // search the interceptor responsible for the given object
4143 auto aIter = std::find_if(m_aControlDispatchInterceptors.begin(), m_aControlDispatchInterceptors.end(),
4144 [&_xInterception](const rtl::Reference<DispatchInterceptionMultiplexer>& rpInterceptor) {
4145 return rpInterceptor->getIntercepted() == _xInterception;
4146 });
4147 if (aIter != m_aControlDispatchInterceptors.end())
4148 {
4149 // log off the interception from its interception object
4150 (*aIter)->dispose();
4151 // remove the interceptor from our array
4152 m_aControlDispatchInterceptors.erase(aIter);
4153 }
4154}
4155
4156
4157void FormController::implInvalidateCurrentControlDependentFeatures()
4158{
4159 Sequence< sal_Int16 > aCurrentControlDependentFeatures(4);
4160
4161 aCurrentControlDependentFeatures[0] = FormFeature::SortAscending;
4162 aCurrentControlDependentFeatures[1] = FormFeature::SortDescending;
4163 aCurrentControlDependentFeatures[2] = FormFeature::AutoFilter;
4164 aCurrentControlDependentFeatures[3] = FormFeature::RefreshCurrentControl;
4165
4166 invalidateFeatures( aCurrentControlDependentFeatures );
4167}
4168
4169
4170void SAL_CALL FormController::columnChanged( const EventObject& /*_event*/ )
4171{
4172 implInvalidateCurrentControlDependentFeatures();
4173}
4174
4175}
4176
4177/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

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#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody)
8
Assuming field 'm_pBody' is non-null
9
Taking true branch
113 m_pBody->release();
10
Calling 'VclReferenceBase::release'
14
Returning; memory was released
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody)
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

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#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
11
Assuming the condition is true
12
Taking true branch
40 delete this;
13
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif