File: | home/maarten/src/libreoffice/core/svx/source/form/formcontroller.cxx |
Warning: | line 3463, column 5 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
93 | using namespace ::com::sun::star; | |||
94 | using namespace ::comphelper; | |||
95 | using namespace ::connectivity; | |||
96 | using namespace ::dbtools; | |||
97 | ||||
98 | ||||
99 | css::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 | ||||
105 | namespace 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 | ||||
203 | namespace { | |||
204 | ||||
205 | struct 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 | ||||
242 | class ColumnInfoCache | |||
243 | { | |||
244 | public: | |||
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 | ||||
254 | private: | |||
255 | typedef ::std::vector< ColumnInfo > ColumnInfos; | |||
256 | ColumnInfos m_aColumns; | |||
257 | bool m_bControlsInitialized; | |||
258 | }; | |||
259 | ||||
260 | ||||
261 | ColumnInfoCache::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 | ||||
295 | namespace | |||
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 | ||||
319 | void ColumnInfoCache::deinitializeControls() | |||
320 | { | |||
321 | for (auto& rCol : m_aColumns) | |||
322 | { | |||
323 | lcl_resetColumnControlInfo( rCol ); | |||
324 | } | |||
325 | m_bControlsInitialized = false; | |||
326 | } | |||
327 | ||||
328 | ||||
329 | void 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 | ||||
408 | const ColumnInfo& ColumnInfoCache::getColumnInfo( size_t _pos ) | |||
409 | { | |||
410 | if ( _pos >= m_aColumns.size() ) | |||
411 | throw IndexOutOfBoundsException(); | |||
412 | ||||
413 | return m_aColumns[ _pos ]; | |||
414 | } | |||
415 | ||||
416 | namespace { | |||
417 | ||||
418 | class OParameterContinuation : public OInteraction< XInteractionSupplyParameters > | |||
419 | { | |||
420 | Sequence< PropertyValue > m_aValues; | |||
421 | ||||
422 | public: | |||
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 | ||||
433 | void SAL_CALL OParameterContinuation::setParameters( const Sequence< PropertyValue >& _rValues ) | |||
434 | { | |||
435 | m_aValues = _rValues; | |||
436 | } | |||
437 | ||||
438 | ||||
439 | // FmXAutoControl | |||
440 | ||||
441 | struct 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 | ||||
453 | namespace { | |||
454 | ||||
455 | class FmXAutoControl: public UnoControl | |||
456 | ||||
457 | { | |||
458 | public: | |||
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 | ||||
466 | protected: | |||
467 | virtual void ImplSetPeerProperty( const OUString& rPropName, const Any& rVal ) override; | |||
468 | }; | |||
469 | ||||
470 | } | |||
471 | ||||
472 | void 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 | ||||
485 | void 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 | ||||
495 | IMPL_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 | ||||
500 | namespace { | |||
501 | ||||
502 | struct 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 | ||||
514 | IMPL_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 | ||||
529 | FormController::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 | ||||
581 | FormController::~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 | ||||
613 | void SAL_CALL FormController::acquire() throw () | |||
614 | { | |||
615 | FormController_BASE::acquire(); | |||
616 | } | |||
617 | ||||
618 | ||||
619 | void SAL_CALL FormController::release() throw () | |||
620 | { | |||
621 | FormController_BASE::release(); | |||
622 | } | |||
623 | ||||
624 | ||||
625 | Any 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 | ||||
636 | Sequence< sal_Int8 > SAL_CALL FormController::getImplementationId() | |||
637 | { | |||
638 | return css::uno::Sequence<sal_Int8>(); | |||
639 | } | |||
640 | ||||
641 | Sequence< Type > SAL_CALL FormController::getTypes( ) | |||
642 | { | |||
643 | return comphelper::concatSequences( | |||
644 | FormController_BASE::getTypes(), | |||
645 | ::cppu::OPropertySetHelper::getTypes() | |||
646 | ); | |||
647 | } | |||
648 | ||||
649 | // XServiceInfo | |||
650 | sal_Bool SAL_CALL FormController::supportsService(const OUString& ServiceName) | |||
651 | { | |||
652 | return cppu::supportsService(this, ServiceName); | |||
653 | } | |||
654 | ||||
655 | OUString SAL_CALL FormController::getImplementationName() | |||
656 | { | |||
657 | return "org.openoffice.comp.svx.FormController"; | |||
658 | } | |||
659 | ||||
660 | Sequence< 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 | ||||
672 | sal_Bool SAL_CALL FormController::approveReset(const EventObject& /*rEvent*/) | |||
673 | { | |||
674 | return true; | |||
675 | } | |||
676 | ||||
677 | ||||
678 | void 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 | ||||
686 | Sequence< 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 | ||||
697 | namespace | |||
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 | ||||
725 | void 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 | ||||
755 | sal_Bool FormController::convertFastPropertyValue( Any & /*rConvertedValue*/, Any & /*rOldValue*/, | |||
756 | sal_Int32 /*nHandle*/, const Any& /*rValue*/ ) | |||
757 | { | |||
758 | return false; | |||
759 | } | |||
760 | ||||
761 | ||||
762 | void FormController::setFastPropertyValue_NoBroadcast( sal_Int32 /*nHandle*/, const Any& /*rValue*/ ) | |||
763 | { | |||
764 | } | |||
765 | ||||
766 | ||||
767 | void 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 | ||||
841 | Reference< XPropertySetInfo > FormController::getPropertySetInfo() | |||
842 | { | |||
843 | static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); | |||
844 | return xInfo; | |||
845 | } | |||
846 | ||||
847 | ||||
848 | void 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 | ||||
873 | void SAL_CALL FormController::addFilterControllerListener( const Reference< XFilterControllerListener >& Listener ) | |||
874 | { | |||
875 | m_aFilterListeners.addInterface( Listener ); | |||
876 | } | |||
877 | ||||
878 | ||||
879 | void 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 | ||||
903 | void 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 | ||||
922 | Reference< 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 | ||||
934 | Sequence< 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 | ||||
961 | void 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 | ||||
1002 | void 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 | ||||
1022 | void 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 | ||||
1039 | sal_Bool SAL_CALL FormController::hasElements() | |||
1040 | { | |||
1041 | ::osl::MutexGuard aGuard( m_aMutex ); | |||
1042 | return !m_aChildren.empty(); | |||
1043 | } | |||
1044 | ||||
1045 | ||||
1046 | Type SAL_CALL FormController::getElementType() | |||
1047 | { | |||
1048 | return cppu::UnoType<XFormController>::get(); | |||
1049 | ||||
1050 | } | |||
1051 | ||||
1052 | // XEnumerationAccess | |||
1053 | ||||
1054 | Reference< XEnumeration > SAL_CALL FormController::createEnumeration() | |||
1055 | { | |||
1056 | ::osl::MutexGuard aGuard( m_aMutex ); | |||
1057 | return new ::comphelper::OEnumerationByIndex(this); | |||
1058 | } | |||
1059 | ||||
1060 | // XIndexAccess | |||
1061 | ||||
1062 | sal_Int32 SAL_CALL FormController::getCount() | |||
1063 | { | |||
1064 | ::osl::MutexGuard aGuard( m_aMutex ); | |||
1065 | return m_aChildren.size(); | |||
1066 | } | |||
1067 | ||||
1068 | ||||
1069 | Any 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 | ||||
1081 | void 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 | ||||
1104 | void 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 | ||||
1121 | void 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 | ||||
1191 | namespace | |||
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 | ||||
1206 | void 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 | ||||
1273 | bool 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 | ||||
1331 | void 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 | ||||
1404 | IMPL_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 | |||
1412 | void 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 | |||
1468 | void 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 | |||
1475 | void 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 | ||||
1482 | void 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 | |||
1490 | void 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 | ||||
1516 | void FormController::impl_checkDisposed_throw() const | |||
1517 | { | |||
1518 | if ( impl_isDisposed_nofail() ) | |||
1519 | throw DisposedException( OUString(), *const_cast< FormController* >( this ) ); | |||
1520 | } | |||
1521 | ||||
1522 | void 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 | ||||
1536 | void 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 | ||||
1547 | void 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 | ||||
1561 | bool 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 | |||
1577 | void 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 | ||||
1712 | IMPL_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 | ||||
1719 | IMPL_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 | ||||
1726 | void 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 | ||||
1744 | void SAL_CALL FormController::mousePressed( const awt::MouseEvent& /*_rEvent*/ ) | |||
1745 | { | |||
1746 | // not interested in | |||
1747 | } | |||
1748 | ||||
1749 | void SAL_CALL FormController::mouseReleased( const awt::MouseEvent& /*_rEvent*/ ) | |||
1750 | { | |||
1751 | // not interested in | |||
1752 | } | |||
1753 | ||||
1754 | void SAL_CALL FormController::mouseEntered( const awt::MouseEvent& _rEvent ) | |||
1755 | { | |||
1756 | m_aControlBorderManager.mouseEntered( _rEvent.Source ); | |||
1757 | } | |||
1758 | ||||
1759 | void SAL_CALL FormController::mouseExited( const awt::MouseEvent& _rEvent ) | |||
1760 | { | |||
1761 | m_aControlBorderManager.mouseExited( _rEvent.Source ); | |||
1762 | } | |||
1763 | ||||
1764 | void 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 | ||||
1776 | void 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 | ||||
1889 | Reference< 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 | ||||
1901 | void 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 | ||||
1928 | void 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 | ||||
1955 | void 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 | ||||
2037 | Reference< 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 | ||||
2049 | Sequence< 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 | ||||
2088 | void 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 | ||||
2099 | void 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 | ||||
2110 | void 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 | ||||
2165 | void 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 | ||||
2174 | namespace | |||
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 | ||||
2204 | void 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 | ||||
2253 | void 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 | ||||
2301 | void 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 | ||||
2312 | void 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 | ||||
2323 | Reference< 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 | ||||
2347 | void 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 | ||||
2386 | void 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 | ||||
2417 | void 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 | ||||
2434 | void 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 | ||||
2454 | void 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 | ||||
2477 | void 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 | ||||
2532 | void 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 | ||||
2543 | IMPL_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 | ||||
2559 | void FormController::unloaded(const EventObject& /*rEvent*/) | |||
2560 | { | |||
2561 | ::osl::MutexGuard aGuard( m_aMutex ); | |||
2562 | impl_checkDisposed_throw(); | |||
2563 | ||||
2564 | updateAllDispatchers(); | |||
2565 | } | |||
2566 | ||||
2567 | ||||
2568 | void 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 | ||||
2580 | void FormController::reloaded(const EventObject& aEvent) | |||
2581 | { | |||
2582 | ::osl::MutexGuard aGuard( m_aMutex ); | |||
2583 | impl_checkDisposed_throw(); | |||
2584 | ||||
2585 | loaded(aEvent); | |||
2586 | } | |||
2587 | ||||
2588 | ||||
2589 | void FormController::unloading(const EventObject& /*aEvent*/) | |||
2590 | { | |||
2591 | ::osl::MutexGuard aGuard( m_aMutex ); | |||
2592 | impl_checkDisposed_throw(); | |||
2593 | ||||
2594 | unload(); | |||
2595 | } | |||
2596 | ||||
2597 | ||||
2598 | void 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 | ||||
2627 | void 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 | ||||
2638 | void 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 | ||||
2672 | void 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 | ||||
2705 | void 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 | ||||
2726 | void FormController::rowChanged(const EventObject& /*event*/) | |||
2727 | { | |||
2728 | // not interested in ... | |||
2729 | } | |||
2730 | ||||
2731 | void FormController::rowSetChanged(const EventObject& /*event*/) | |||
2732 | { | |||
2733 | // not interested in ... | |||
2734 | } | |||
2735 | ||||
2736 | ||||
2737 | // XContainerListener | |||
2738 | ||||
2739 | void 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 | ||||
2785 | void 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 | ||||
2800 | void 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 | ||||
2827 | Reference< 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 | ||||
2846 | void 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 | ||||
2857 | void 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 | ||||
2869 | Reference< XFormOperations > SAL_CALL FormController::getFormOperations() | |||
2870 | { | |||
2871 | ::osl::MutexGuard aGuard( m_aMutex ); | |||
2872 | impl_checkDisposed_throw(); | |||
2873 | ||||
2874 | return m_xFormOperations; | |||
2875 | } | |||
2876 | ||||
2877 | ||||
2878 | Reference< XControl> SAL_CALL FormController::getCurrentControl() | |||
2879 | { | |||
2880 | ::osl::MutexGuard aGuard( m_aMutex ); | |||
2881 | impl_checkDisposed_throw(); | |||
2882 | return m_xCurrentControl; | |||
2883 | } | |||
2884 | ||||
2885 | ||||
2886 | void 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 | ||||
2893 | void 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 | ||||
2901 | void 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 | ||||
2938 | Reference< XFormControllerContext > SAL_CALL FormController::getContext() | |||
2939 | { | |||
2940 | ::osl::MutexGuard aGuard( m_aMutex ); | |||
2941 | impl_checkDisposed_throw(); | |||
2942 | return m_xFormControllerContext; | |||
2943 | } | |||
2944 | ||||
2945 | ||||
2946 | void 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 | ||||
2954 | Reference< XInteractionHandler > SAL_CALL FormController::getInteractionHandler() | |||
2955 | { | |||
2956 | ::osl::MutexGuard aGuard( m_aMutex ); | |||
2957 | impl_checkDisposed_throw(); | |||
2958 | return m_xInteractionHandler; | |||
2959 | } | |||
2960 | ||||
2961 | ||||
2962 | void 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 | ||||
2970 | void 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 | ||||
3167 | void 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 | ||||
3304 | void 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 | ||||
3389 | void 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 | ||||
3416 | OUString SAL_CALL FormController::getMode() | |||
3417 | { | |||
3418 | ::osl::MutexGuard aGuard( m_aMutex ); | |||
3419 | impl_checkDisposed_throw(); | |||
3420 | ||||
3421 | return m_aMode; | |||
3422 | } | |||
3423 | ||||
3424 | ||||
3425 | Sequence< 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 | ||||
3439 | sal_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 | ||||
3449 | vcl::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); | |||
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(); | |||
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; | |||
| ||||
3464 | } | |||
3465 | ||||
3466 | bool 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 | ||||
3508 | Reference< 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 | ||||
3533 | namespace | |||
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 | ||||
3595 | sal_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 | ||||
3683 | sal_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 | ||||
3700 | sal_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 | ||||
3718 | void 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 | ||||
3727 | void 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 | ||||
3737 | void 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()) | |||
| ||||
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()); | |||
3753 | } | |||
3754 | } | |||
3755 | ||||
3756 | // XErrorBroadcaster | |||
3757 | ||||
3758 | void 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 | ||||
3767 | void 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 | ||||
3777 | void 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 | ||||
3786 | void 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 | ||||
3796 | void SAL_CALL FormController::addParameterListener(const Reference< XDatabaseParameterListener > & aListener) | |||
3797 | { | |||
3798 | FormController::addDatabaseParameterListener( aListener ); | |||
3799 | } | |||
3800 | ||||
3801 | ||||
3802 | void SAL_CALL FormController::removeParameterListener(const Reference< XDatabaseParameterListener > & aListener) | |||
3803 | { | |||
3804 | FormController::removeDatabaseParameterListener( aListener ); | |||
3805 | } | |||
3806 | ||||
3807 | // XDatabaseParameterListener | |||
3808 | ||||
3809 | sal_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 | ||||
3887 | void 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 | ||||
3896 | void 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 | ||||
3906 | sal_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 | ||||
3968 | void 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 | ||||
3980 | void 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 | ||||
3992 | Reference< XDispatch > | |||
3993 | FormController::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 | ||||
4033 | void 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 | ||||
4061 | void 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 | ||||
4079 | Reference< XInterface > SAL_CALL FormController::getParent() | |||
4080 | { | |||
4081 | return m_xParent; | |||
4082 | } | |||
4083 | ||||
4084 | ||||
4085 | void SAL_CALL FormController::setParent( const Reference< XInterface >& Parent) | |||
4086 | { | |||
4087 | m_xParent = Parent; | |||
4088 | } | |||
4089 | ||||
4090 | ||||
4091 | void 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 | ||||
4098 | Reference< 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 | ||||
4117 | bool 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 | ||||
4131 | void SAL_CALL FormController::handle( const Reference< XInteractionRequest >& _rRequest ) | |||
4132 | { | |||
4133 | if ( !ensureInteractionHandler() ) | |||
4134 | return; | |||
4135 | m_xInteractionHandler->handle( _rRequest ); | |||
4136 | } | |||
4137 | ||||
4138 | ||||
4139 | void 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 | ||||
4157 | void 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 | ||||
4170 | void SAL_CALL FormController::columnChanged( const EventObject& /*_event*/ ) | |||
4171 | { | |||
4172 | implInvalidateCurrentControlDependentFeatures(); | |||
4173 | } | |||
4174 | ||||
4175 | } | |||
4176 | ||||
4177 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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 | |
34 | namespace rtl |
35 | { |
36 | |
37 | /** Template reference class for reference type. |
38 | */ |
39 | template <class reference_type> |
40 | class Reference |
41 | { |
42 | /** The <b>reference_type</b> body pointer. |
43 | */ |
44 | reference_type * m_pBody; |
45 | |
46 | |
47 | public: |
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) |
113 | m_pBody->release(); |
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 |
277 | namespace 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 | */ |
286 | template<typename T> |
287 | struct 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: */ |
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 | |
25 | class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase |
26 | { |
27 | mutable oslInterlockedCount mnRefCnt; |
28 | |
29 | template<typename T> friend class VclPtr; |
30 | |
31 | public: |
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) |
40 | delete this; |
41 | } |
42 | #ifdef DBG_UTIL |
43 | #ifndef _WIN32 |
44 | sal_Int32 getRefCount() const { return mnRefCnt; } |
45 | #endif |
46 | #endif |
47 | |
48 | |
49 | private: |
50 | VclReferenceBase(const VclReferenceBase&) = delete; |
51 | VclReferenceBase& operator=(const VclReferenceBase&) = delete; |
52 | |
53 | bool mbDisposed : 1; |
54 | |
55 | protected: |
56 | VclReferenceBase(); |
57 | protected: |
58 | virtual ~VclReferenceBase(); |
59 | |
60 | protected: |
61 | virtual void dispose(); |
62 | |
63 | public: |
64 | void disposeOnce(); |
65 | bool isDisposed() const { return mbDisposed; } |
66 | |
67 | }; |
68 | #endif |