Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include "Edit.hxx"
22 :
23 : #include <com/sun/star/uno/Type.hxx>
24 : #include <com/sun/star/awt/XWindow.hpp>
25 : #include <com/sun/star/container/XIndexAccess.hpp>
26 : #include <com/sun/star/form/XSubmit.hpp>
27 : #include <com/sun/star/util/NumberFormat.hpp>
28 : #include <com/sun/star/sdbc/DataType.hpp>
29 : #include <com/sun/star/awt/XVclWindowPeer.hpp>
30 :
31 : #include <vcl/svapp.hxx>
32 : #include <tools/wintypes.hxx>
33 :
34 : #include <connectivity/dbtools.hxx>
35 : #include <connectivity/formattedcolumnvalue.hxx>
36 : #include <connectivity/dbconversion.hxx>
37 :
38 : #include <tools/diagnose_ex.h>
39 : #include <tools/debug.hxx>
40 :
41 : #include <comphelper/container.hxx>
42 : #include <comphelper/numbers.hxx>
43 : #include <comphelper/processfactory.hxx>
44 :
45 : using namespace dbtools;
46 :
47 : //.........................................................................
48 : namespace frm
49 : {
50 : using namespace ::com::sun::star::uno;
51 : using namespace ::com::sun::star::sdb;
52 : using namespace ::com::sun::star::sdbc;
53 : using namespace ::com::sun::star::sdbcx;
54 : using namespace ::com::sun::star::beans;
55 : using namespace ::com::sun::star::container;
56 : using namespace ::com::sun::star::form;
57 : using namespace ::com::sun::star::awt;
58 : using namespace ::com::sun::star::io;
59 : using namespace ::com::sun::star::lang;
60 : using namespace ::com::sun::star::util;
61 : using namespace ::com::sun::star::form::binding;
62 :
63 : //------------------------------------------------------------------
64 57 : InterfaceRef SAL_CALL OEditControl_CreateInstance(const Reference< XMultiServiceFactory > & _rxFactory)
65 : {
66 57 : return *(new OEditControl( comphelper::getComponentContext(_rxFactory) ));
67 : }
68 :
69 : //------------------------------------------------------------------------------
70 0 : Sequence<Type> OEditControl::_getTypes()
71 : {
72 0 : static Sequence<Type> aTypes;
73 0 : if (!aTypes.getLength())
74 : {
75 : // my two base classes
76 0 : aTypes = concatSequences(OBoundControl::_getTypes(), OEditControl_BASE::getTypes());
77 : }
78 0 : return aTypes;
79 : }
80 :
81 : //------------------------------------------------------------------------------
82 2125 : Any SAL_CALL OEditControl::queryAggregation(const Type& _rType) throw (RuntimeException)
83 : {
84 2125 : Any aReturn = OBoundControl::queryAggregation(_rType);
85 2125 : if (!aReturn.hasValue())
86 113 : aReturn = OEditControl_BASE::queryInterface(_rType);
87 :
88 2125 : return aReturn;
89 : }
90 :
91 : DBG_NAME(OEditControl);
92 : //------------------------------------------------------------------------------
93 57 : OEditControl::OEditControl(const Reference<XComponentContext>& _rxFactory)
94 : :OBoundControl( _rxFactory, FRM_SUN_CONTROL_RICHTEXTCONTROL )
95 : ,m_aChangeListeners(m_aMutex)
96 57 : ,m_nKeyEvent( 0 )
97 : {
98 : DBG_CTOR(OEditControl,NULL);
99 :
100 57 : increment(m_refCount);
101 : {
102 57 : Reference<XWindow> xComp;
103 57 : if (query_aggregation(m_xAggregate, xComp))
104 : {
105 57 : xComp->addFocusListener(this);
106 57 : xComp->addKeyListener(this);
107 57 : }
108 : }
109 57 : decrement(m_refCount);
110 57 : }
111 :
112 : //------------------------------------------------------------------------------
113 120 : OEditControl::~OEditControl()
114 : {
115 40 : if( m_nKeyEvent )
116 0 : Application::RemoveUserEvent( m_nKeyEvent );
117 :
118 40 : if (!OComponentHelper::rBHelper.bDisposed)
119 : {
120 0 : acquire();
121 0 : dispose();
122 : }
123 :
124 : DBG_DTOR(OEditControl,NULL);
125 80 : }
126 :
127 : // XChangeBroadcaster
128 : //------------------------------------------------------------------------------
129 0 : void OEditControl::addChangeListener(const Reference<XChangeListener>& l) throw ( ::com::sun::star::uno::RuntimeException)
130 : {
131 0 : m_aChangeListeners.addInterface( l );
132 0 : }
133 :
134 : //------------------------------------------------------------------------------
135 0 : void OEditControl::removeChangeListener(const Reference<XChangeListener>& l) throw ( ::com::sun::star::uno::RuntimeException)
136 : {
137 0 : m_aChangeListeners.removeInterface( l );
138 0 : }
139 :
140 : // OComponentHelper
141 : //------------------------------------------------------------------------------
142 40 : void OEditControl::disposing()
143 : {
144 40 : OBoundControl::disposing();
145 :
146 40 : EventObject aEvt(static_cast<XWeak*>(this));
147 40 : m_aChangeListeners.disposeAndClear(aEvt);
148 40 : }
149 :
150 : // XServiceInfo
151 : //------------------------------------------------------------------------------
152 0 : StringSequence OEditControl::getSupportedServiceNames() throw()
153 : {
154 0 : StringSequence aSupported = OBoundControl::getSupportedServiceNames();
155 0 : aSupported.realloc(aSupported.getLength() + 1);
156 :
157 0 : OUString*pArray = aSupported.getArray();
158 0 : pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_TEXTFIELD;
159 0 : return aSupported;
160 : }
161 :
162 : // XEventListener
163 : //------------------------------------------------------------------------------
164 133 : void OEditControl::disposing(const EventObject& Source) throw( RuntimeException )
165 : {
166 133 : OBoundControl::disposing(Source);
167 133 : }
168 :
169 : // XFocusListener
170 : //------------------------------------------------------------------------------
171 0 : void OEditControl::focusGained( const FocusEvent& /*e*/ ) throw ( ::com::sun::star::uno::RuntimeException)
172 : {
173 0 : Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
174 0 : if (xSet.is())
175 0 : xSet->getPropertyValue( PROPERTY_TEXT ) >>= m_aHtmlChangeValue;
176 0 : }
177 :
178 : //------------------------------------------------------------------------------
179 0 : void OEditControl::focusLost( const FocusEvent& /*e*/ ) throw ( ::com::sun::star::uno::RuntimeException)
180 : {
181 0 : Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
182 0 : if (xSet.is())
183 : {
184 0 : OUString sNewHtmlChangeValue;
185 0 : xSet->getPropertyValue( PROPERTY_TEXT ) >>= sNewHtmlChangeValue;
186 0 : if( sNewHtmlChangeValue != m_aHtmlChangeValue )
187 : {
188 0 : EventObject aEvt( *this );
189 0 : m_aChangeListeners.notifyEach( &XChangeListener::changed, aEvt );
190 0 : }
191 0 : }
192 0 : }
193 :
194 : // XKeyListener
195 : //------------------------------------------------------------------------------
196 0 : void OEditControl::keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException)
197 : {
198 0 : if( e.KeyCode != KEY_RETURN || e.Modifiers != 0 )
199 0 : return;
200 :
201 : // Is the Control in a form with a submit URL?
202 0 : Reference<XPropertySet> xSet(getModel(), UNO_QUERY);
203 0 : if( !xSet.is() )
204 0 : return;
205 :
206 : // Not for multiline edits
207 0 : Any aTmp( xSet->getPropertyValue(PROPERTY_MULTILINE));
208 0 : if ((aTmp.getValueType().equals(::getBooleanCppuType())) && getBOOL(aTmp))
209 0 : return;
210 :
211 0 : Reference<XFormComponent> xFComp(xSet, UNO_QUERY);
212 0 : InterfaceRef xParent = xFComp->getParent();
213 0 : if( !xParent.is() )
214 0 : return;
215 :
216 0 : Reference<XPropertySet> xFormSet(xParent, UNO_QUERY);
217 0 : if( !xFormSet.is() )
218 0 : return;
219 :
220 0 : aTmp = xFormSet->getPropertyValue( PROPERTY_TARGET_URL );
221 0 : if (!aTmp.getValueType().equals(::getCppuType((const OUString*)NULL)) ||
222 0 : getString(aTmp).isEmpty() )
223 0 : return;
224 :
225 0 : Reference<XIndexAccess> xElements(xParent, UNO_QUERY);
226 0 : sal_Int32 nCount = xElements->getCount();
227 0 : if( nCount > 1 )
228 : {
229 0 : Reference<XPropertySet> xFCSet;
230 0 : for( sal_Int32 nIndex=0; nIndex < nCount; nIndex++ )
231 : {
232 : // Any aElement(xElements->getByIndex(nIndex));
233 0 : xElements->getByIndex(nIndex) >>= xFCSet;
234 : OSL_ENSURE(xFCSet.is(),"OEditControl::keyPressed: No XPropertySet!");
235 :
236 0 : if (hasProperty(PROPERTY_CLASSID, xFCSet) &&
237 0 : getINT16(xFCSet->getPropertyValue(PROPERTY_CLASSID)) == FormComponentType::TEXTFIELD)
238 : {
239 : // Found another Edit -> then do not submit!
240 0 : if (xFCSet != xSet)
241 0 : return;
242 : }
243 0 : }
244 : }
245 :
246 : // Because we're still in the header, trigger submit asynchronously
247 0 : if( m_nKeyEvent )
248 0 : Application::RemoveUserEvent( m_nKeyEvent );
249 0 : m_nKeyEvent = Application::PostUserEvent( LINK(this, OEditControl,OnKeyPressed) );
250 : }
251 :
252 : //------------------------------------------------------------------------------
253 0 : void OEditControl::keyReleased(const ::com::sun::star::awt::KeyEvent& /*e*/) throw ( ::com::sun::star::uno::RuntimeException)
254 : {
255 0 : }
256 :
257 : //------------------------------------------------------------------------------
258 0 : IMPL_LINK(OEditControl, OnKeyPressed, void*, /*EMPTYARG*/)
259 : {
260 0 : m_nKeyEvent = 0;
261 :
262 0 : Reference<XFormComponent> xFComp(getModel(), UNO_QUERY);
263 0 : InterfaceRef xParent = xFComp->getParent();
264 0 : Reference<XSubmit> xSubmit(xParent, UNO_QUERY);
265 0 : if (xSubmit.is())
266 0 : xSubmit->submit( Reference<XControl>(), ::com::sun::star::awt::MouseEvent() );
267 0 : return 0L;
268 : }
269 :
270 : //------------------------------------------------------------------
271 83 : void SAL_CALL OEditControl::createPeer( const Reference< XToolkit>& _rxToolkit, const Reference< XWindowPeer>& _rxParent ) throw ( RuntimeException )
272 : {
273 83 : OBoundControl::createPeer(_rxToolkit, _rxParent);
274 83 : }
275 :
276 : /*************************************************************************/
277 : //------------------------------------------------------------------
278 87 : InterfaceRef SAL_CALL OEditModel_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory)
279 : {
280 87 : return *(new OEditModel( comphelper::getComponentContext(_rxFactory) ));
281 : }
282 :
283 : //------------------------------------------------------------------------------
284 2 : Sequence<Type> OEditModel::_getTypes()
285 : {
286 2 : return OEditBaseModel::_getTypes();
287 : }
288 :
289 :
290 : DBG_NAME(OEditModel);
291 : //------------------------------------------------------------------
292 103 : OEditModel::OEditModel(const Reference<XComponentContext>& _rxFactory)
293 : :OEditBaseModel( _rxFactory, FRM_SUN_COMPONENT_RICHTEXTCONTROL, FRM_SUN_CONTROL_TEXTFIELD, sal_True, sal_True )
294 : ,m_bMaxTextLenModified(sal_False)
295 103 : ,m_bWritingFormattedFake(sal_False)
296 : {
297 : DBG_CTOR(OEditModel,NULL);
298 :
299 103 : m_nClassId = FormComponentType::TEXTFIELD;
300 103 : initValueProperty( PROPERTY_TEXT, PROPERTY_ID_TEXT );
301 103 : }
302 :
303 : //------------------------------------------------------------------
304 2 : OEditModel::OEditModel( const OEditModel* _pOriginal, const Reference<XComponentContext>& _rxFactory )
305 : :OEditBaseModel( _pOriginal, _rxFactory )
306 : ,m_bMaxTextLenModified(sal_False)
307 2 : ,m_bWritingFormattedFake(sal_False)
308 : {
309 : DBG_CTOR( OEditModel, NULL );
310 :
311 : // Note that most of the properties are not clone from the original object:
312 : // Things as the format key, it's type, and such, depend on the field being part of a loaded form
313 : // (they're initialized in onConnectedDbColumn). Even if the original object _is_ part of such a form, we ourself
314 : // certainly aren't, so these members are defaulted. If we're inserted into a form which is already loaded,
315 : // they will be set to new values, anyway ....
316 2 : }
317 :
318 : //------------------------------------------------------------------
319 291 : OEditModel::~OEditModel()
320 : {
321 97 : if (!OComponentHelper::rBHelper.bDisposed)
322 : {
323 0 : acquire();
324 0 : dispose();
325 : }
326 :
327 : DBG_DTOR(OEditModel,NULL);
328 194 : }
329 :
330 : //------------------------------------------------------------------------------
331 2 : IMPLEMENT_DEFAULT_CLONING( OEditModel )
332 :
333 : //------------------------------------------------------------------------------
334 97 : void OEditModel::disposing()
335 : {
336 97 : OEditBaseModel::disposing();
337 97 : m_pValueFormatter.reset();
338 97 : }
339 :
340 : // XPersistObject
341 : //------------------------------------------------------------------------------
342 1 : OUString SAL_CALL OEditModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException)
343 : {
344 1 : return OUString(FRM_COMPONENT_EDIT); // old (non-sun) name for compatibility !
345 : }
346 :
347 : // XServiceInfo
348 : //------------------------------------------------------------------------------
349 52 : StringSequence SAL_CALL OEditModel::getSupportedServiceNames() throw()
350 : {
351 52 : StringSequence aSupported = OBoundControlModel::getSupportedServiceNames();
352 :
353 52 : sal_Int32 nOldLen = aSupported.getLength();
354 52 : aSupported.realloc( nOldLen + 8 );
355 52 : OUString* pStoreTo = aSupported.getArray() + nOldLen;
356 :
357 52 : *pStoreTo++ = BINDABLE_CONTROL_MODEL;
358 52 : *pStoreTo++ = DATA_AWARE_CONTROL_MODEL;
359 52 : *pStoreTo++ = VALIDATABLE_CONTROL_MODEL;
360 :
361 52 : *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL;
362 52 : *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL;
363 :
364 52 : *pStoreTo++ = FRM_SUN_COMPONENT_TEXTFIELD;
365 52 : *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_TEXTFIELD;
366 52 : *pStoreTo++ = BINDABLE_DATABASE_TEXT_FIELD;
367 :
368 52 : return aSupported;
369 : }
370 :
371 : // XPropertySet
372 13244 : void SAL_CALL OEditModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle ) const
373 : {
374 13244 : if ( PROPERTY_ID_PERSISTENCE_MAXTEXTLENGTH == nHandle )
375 : {
376 88 : if ( m_bMaxTextLenModified )
377 0 : rValue <<= sal_Int16(0);
378 88 : else if ( m_xAggregateSet.is() )
379 88 : rValue = m_xAggregateSet->getPropertyValue(PROPERTY_MAXTEXTLEN);
380 : }
381 : else
382 : {
383 13156 : OEditBaseModel::getFastPropertyValue(rValue, nHandle );
384 : }
385 13244 : }
386 :
387 : //------------------------------------------------------------------------------
388 106 : void OEditModel::describeFixedProperties( Sequence< Property >& _rProps ) const
389 : {
390 106 : BEGIN_DESCRIBE_PROPERTIES( 5, OEditBaseModel )
391 106 : DECL_PROP2(PERSISTENCE_MAXTEXTLENGTH,sal_Int16, READONLY, TRANSIENT);
392 106 : DECL_PROP2(DEFAULT_TEXT, OUString, BOUND, MAYBEDEFAULT);
393 106 : DECL_BOOL_PROP1(EMPTY_IS_NULL, BOUND);
394 106 : DECL_PROP1(TABINDEX, sal_Int16, BOUND);
395 106 : DECL_BOOL_PROP2(FILTERPROPOSAL, BOUND, MAYBEDEFAULT);
396 : END_DESCRIBE_PROPERTIES();
397 106 : }
398 :
399 : //------------------------------------------------------------------------------
400 106 : void OEditModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const
401 : {
402 106 : OEditBaseModel::describeAggregateProperties( _rAggregateProps );
403 :
404 : // our aggregate is a rich text model, which also derives from OControlModel, as
405 : // do we, so we need to remove some duplicate properties
406 106 : RemoveProperty( _rAggregateProps, PROPERTY_TABINDEX );
407 106 : RemoveProperty( _rAggregateProps, PROPERTY_CLASSID );
408 106 : RemoveProperty( _rAggregateProps, PROPERTY_NAME );
409 106 : RemoveProperty( _rAggregateProps, PROPERTY_TAG );
410 106 : RemoveProperty( _rAggregateProps, PROPERTY_NATIVE_LOOK );
411 :
412 106 : }
413 :
414 : //------------------------------------------------------------------------------
415 22 : bool OEditModel::implActsAsRichText( ) const
416 : {
417 22 : sal_Bool bActAsRichText = sal_False;
418 22 : if ( m_xAggregateSet.is() )
419 : {
420 22 : OSL_VERIFY( m_xAggregateSet->getPropertyValue( PROPERTY_RICH_TEXT ) >>= bActAsRichText );
421 : }
422 22 : return bActAsRichText;
423 : }
424 :
425 : //------------------------------------------------------------------------------
426 5 : void SAL_CALL OEditModel::reset( ) throw(RuntimeException)
427 : {
428 : // no reset if we currently act as rich text control
429 5 : if ( implActsAsRichText() )
430 5 : return;
431 :
432 5 : OEditBaseModel::reset();
433 : }
434 :
435 : //------------------------------------------------------------------------------
436 : namespace
437 : {
438 4 : void lcl_transferProperties( const Reference< XPropertySet >& _rxSource, const Reference< XPropertySet >& _rxDest )
439 : {
440 : try
441 : {
442 4 : Reference< XPropertySetInfo > xSourceInfo;
443 4 : if ( _rxSource.is() )
444 4 : xSourceInfo = _rxSource->getPropertySetInfo();
445 :
446 8 : Reference< XPropertySetInfo > xDestInfo;
447 4 : if ( _rxDest.is() )
448 4 : xDestInfo = _rxDest->getPropertySetInfo();
449 :
450 4 : if ( !xSourceInfo.is() || !xDestInfo.is() )
451 : {
452 : OSL_FAIL( "lcl_transferProperties: invalid property set(s)!" );
453 4 : return;
454 : }
455 :
456 8 : Sequence< Property > aSourceProps( xSourceInfo->getProperties() );
457 4 : const Property* pSourceProps = aSourceProps.getConstArray();
458 4 : const Property* pSourcePropsEnd = aSourceProps.getConstArray() + aSourceProps.getLength();
459 336 : while ( pSourceProps != pSourcePropsEnd )
460 : {
461 328 : if ( !xDestInfo->hasPropertyByName( pSourceProps->Name ) )
462 : {
463 148 : ++pSourceProps;
464 296 : continue;
465 : }
466 :
467 180 : Property aDestProp( xDestInfo->getPropertyByName( pSourceProps->Name ) );
468 180 : if ( 0 != ( aDestProp.Attributes & PropertyAttribute::READONLY ) )
469 : {
470 0 : ++pSourceProps;
471 0 : continue;
472 : }
473 :
474 : try
475 : {
476 180 : _rxDest->setPropertyValue( pSourceProps->Name, _rxSource->getPropertyValue( pSourceProps->Name ) );
477 : }
478 0 : catch(const IllegalArgumentException& e)
479 : {
480 : #if OSL_DEBUG_LEVEL > 0
481 : OString sMessage( "could not transfer the property named '" );
482 : sMessage += OString( pSourceProps->Name.getStr(), pSourceProps->Name.getLength(), RTL_TEXTENCODING_ASCII_US );
483 : sMessage += OString( "'." );
484 : if ( !e.Message.isEmpty() )
485 : {
486 : sMessage += OString( "\n\nMessage:\n" );
487 : sMessage += OString( e.Message.getStr(), e.Message.getLength(), RTL_TEXTENCODING_ASCII_US );
488 : }
489 : OSL_FAIL( sMessage.getStr() );
490 : #else
491 : (void)e;
492 : #endif
493 : }
494 :
495 180 : ++pSourceProps;
496 184 : }
497 : }
498 0 : catch( const Exception& )
499 : {
500 : DBG_UNHANDLED_EXCEPTION();
501 : }
502 : }
503 : }
504 :
505 : //------------------------------------------------------------------------------
506 2 : void OEditModel::writeAggregate( const Reference< XObjectOutputStream >& _rxOutStream ) const
507 : {
508 : // we need to fake the writing of our aggregate. Since #i24387#, we have another aggregate,
509 : // but for compatibility, we need to use an "old" aggregate for writing and reading
510 :
511 : Reference< XPropertySet > xFakedAggregate(
512 4 : getContext()->getServiceManager()->createInstanceWithContext( (OUString)VCL_CONTROLMODEL_EDIT, getContext() ),
513 : UNO_QUERY
514 2 : );
515 : OSL_ENSURE( xFakedAggregate.is(), "OEditModel::writeAggregate: could not create an old EditControlModel!" );
516 2 : if ( !xFakedAggregate.is() )
517 2 : return;
518 :
519 2 : lcl_transferProperties( m_xAggregateSet, xFakedAggregate );
520 :
521 4 : Reference< XPersistObject > xFakedPersist( xFakedAggregate, UNO_QUERY );
522 : OSL_ENSURE( xFakedPersist.is(), "OEditModel::writeAggregate: no XPersistObject!" );
523 2 : if ( xFakedPersist.is() )
524 4 : xFakedPersist->write( _rxOutStream );
525 : }
526 :
527 : //------------------------------------------------------------------------------
528 2 : void OEditModel::readAggregate( const Reference< XObjectInputStream >& _rxInStream )
529 : {
530 : // we need to fake the reading of our aggregate. Since #i24387#, we have another aggregate,
531 : // but for compatibility, we need to use an "old" aggregate for writing and reading
532 :
533 : Reference< XPropertySet > xFakedAggregate(
534 4 : getContext()->getServiceManager()->createInstanceWithContext( (OUString)VCL_CONTROLMODEL_EDIT, getContext() ),
535 : UNO_QUERY
536 2 : );
537 4 : Reference< XPersistObject > xFakedPersist( xFakedAggregate, UNO_QUERY );
538 : OSL_ENSURE( xFakedPersist.is(), "OEditModel::readAggregate: no XPersistObject, or no faked aggregate at all!" );
539 2 : if ( xFakedPersist.is() )
540 : {
541 2 : xFakedPersist->read( _rxInStream );
542 2 : lcl_transferProperties( xFakedAggregate, m_xAggregateSet );
543 2 : }
544 2 : }
545 :
546 : //------------------------------------------------------------------------------
547 2 : void OEditModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
548 : {
549 2 : Any aCurrentText;
550 2 : sal_Int16 nOldTextLen = 0;
551 : // Am I loaded at the moment and did I switch MaxTextLen temporarily?
552 2 : if ( m_bMaxTextLenModified )
553 : { // -> for the duration of saving, make my aggregated model believe the old TextLen
554 :
555 : // before doing this we have to save the current text value of the aggregate, as this may be affected by resetting the text len
556 0 : aCurrentText = m_xAggregateSet->getPropertyValue(PROPERTY_TEXT);
557 :
558 0 : m_xAggregateSet->getPropertyValue(PROPERTY_MAXTEXTLEN) >>= nOldTextLen;
559 0 : m_xAggregateSet->setPropertyValue(PROPERTY_MAXTEXTLEN, makeAny((sal_Int16)0));
560 : }
561 :
562 2 : OEditBaseModel::write(_rxOutStream);
563 :
564 2 : if ( m_bMaxTextLenModified )
565 : { // Reset again
566 0 : m_xAggregateSet->setPropertyValue(PROPERTY_MAXTEXTLEN, makeAny(nOldTextLen));
567 : // and reset the text
568 : // First we set it to an empty string : Without this the second setPropertyValue would not do anything as it thinks
569 : // we aren't changing the prop (it didn't notify the - implicite - change of the text prop while setting the max text len)
570 : // This seems to be a bug with in toolkit's EditControl-implementation.
571 0 : m_xAggregateSet->setPropertyValue(PROPERTY_TEXT, makeAny(OUString()));
572 0 : m_xAggregateSet->setPropertyValue(PROPERTY_TEXT, aCurrentText);
573 2 : }
574 2 : }
575 :
576 : //------------------------------------------------------------------------------
577 2 : void OEditModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
578 : {
579 2 : OEditBaseModel::read(_rxInStream);
580 :
581 : // Some versions (5.1 'til about 552) wrote a wrong DefaultControl-property value which is unknown
582 : // to older versions (5.0).
583 : // correct this ...
584 2 : if (m_xAggregateSet.is())
585 : {
586 2 : Any aDefaultControl = m_xAggregateSet->getPropertyValue(PROPERTY_DEFAULTCONTROL);
587 6 : if ( (aDefaultControl.getValueType().getTypeClass() == TypeClass_STRING)
588 8 : && (getString(aDefaultControl) == STARDIV_ONE_FORM_CONTROL_TEXTFIELD )
589 : )
590 : {
591 0 : m_xAggregateSet->setPropertyValue( PROPERTY_DEFAULTCONTROL, makeAny( (OUString)STARDIV_ONE_FORM_CONTROL_EDIT ) );
592 : // Older as well as current versions should understand this : the former knew only the STARDIV_ONE_FORM_CONTROL_EDIT,
593 : // the latter are registered for both STARDIV_ONE_FORM_CONTROL_EDIT and STARDIV_ONE_FORM_CONTROL_TEXTFIELD.
594 2 : }
595 : }
596 2 : }
597 :
598 : //------------------------------------------------------------------------------
599 2 : sal_uInt16 OEditModel::getPersistenceFlags() const
600 : {
601 2 : sal_uInt16 nFlags = OEditBaseModel::getPersistenceFlags();
602 :
603 2 : if (m_bWritingFormattedFake)
604 0 : nFlags |= PF_FAKE_FORMATTED_FIELD;
605 :
606 2 : return nFlags;
607 : }
608 :
609 : //------------------------------------------------------------------------------
610 17 : void OEditModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm )
611 : {
612 17 : Reference< XPropertySet > xField = getField();
613 17 : if ( xField.is() )
614 : {
615 17 : m_pValueFormatter.reset( new ::dbtools::FormattedColumnValue( getContext(), Reference< XRowSet >( _rxForm, UNO_QUERY ), xField ) );
616 :
617 17 : if ( m_pValueFormatter->getKeyType() != NumberFormat::SCIENTIFIC )
618 : {
619 17 : m_bMaxTextLenModified = getINT16(m_xAggregateSet->getPropertyValue(PROPERTY_MAXTEXTLEN)) != 0;
620 17 : if ( !m_bMaxTextLenModified )
621 : {
622 17 : sal_Int32 nFieldLen = 0;
623 17 : xField->getPropertyValue("Precision") >>= nFieldLen;
624 :
625 17 : if (nFieldLen && nFieldLen <= USHRT_MAX)
626 : {
627 0 : Any aVal;
628 0 : aVal <<= (sal_Int16)nFieldLen;
629 0 : m_xAggregateSet->setPropertyValue(PROPERTY_MAXTEXTLEN, aVal);
630 :
631 0 : m_bMaxTextLenModified = sal_True;
632 : }
633 : }
634 : else
635 0 : m_bMaxTextLenModified = sal_False; // to get sure that the text len won't be set in unloaded
636 : }
637 17 : }
638 17 : }
639 :
640 : //------------------------------------------------------------------------------
641 17 : void OEditModel::onDisconnectedDbColumn()
642 : {
643 17 : OEditBaseModel::onDisconnectedDbColumn();
644 :
645 17 : m_pValueFormatter.reset();
646 :
647 17 : if ( hasField() && m_bMaxTextLenModified )
648 : {
649 0 : Any aVal;
650 0 : aVal <<= (sal_Int16)0; // Only if it was 0, I switched it in onConnectedDbColumn
651 0 : m_xAggregateSet->setPropertyValue(PROPERTY_MAXTEXTLEN, aVal);
652 0 : m_bMaxTextLenModified = sal_False;
653 : }
654 17 : }
655 :
656 : //------------------------------------------------------------------------------
657 17 : sal_Bool OEditModel::approveDbColumnType( sal_Int32 _nColumnType )
658 : {
659 : // if we act as rich text currently, we do not allow binding to a database column
660 17 : if ( implActsAsRichText() )
661 0 : return sal_False;
662 :
663 17 : return OEditBaseModel::approveDbColumnType( _nColumnType );
664 : }
665 :
666 : //------------------------------------------------------------------------------
667 15 : void OEditModel::resetNoBroadcast()
668 : {
669 15 : OEditBaseModel::resetNoBroadcast();
670 15 : }
671 :
672 : //------------------------------------------------------------------------------
673 0 : sal_Bool OEditModel::commitControlValueToDbColumn( bool /*_bPostReset*/ )
674 : {
675 0 : Any aNewValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) );
676 :
677 0 : OUString sNewValue;
678 0 : aNewValue >>= sNewValue;
679 :
680 0 : if ( !aNewValue.hasValue()
681 0 : || ( sNewValue.isEmpty() // an empty string
682 0 : && m_bEmptyIsNull // which should be interpreted as NULL
683 : )
684 : )
685 : {
686 0 : m_xColumnUpdate->updateNull();
687 : }
688 : else
689 : {
690 : OSL_PRECOND( m_pValueFormatter.get(), "OEditModel::commitControlValueToDbColumn: no value formatter!" );
691 : try
692 : {
693 0 : if ( m_pValueFormatter.get() )
694 : {
695 0 : if ( !m_pValueFormatter->setFormattedValue( sNewValue ) )
696 0 : return sal_False;
697 : }
698 : else
699 0 : m_xColumnUpdate->updateString( sNewValue );
700 : }
701 0 : catch ( const Exception& )
702 : {
703 0 : return sal_False;
704 : }
705 : }
706 :
707 0 : return sal_True;
708 : }
709 :
710 : //------------------------------------------------------------------------------
711 34 : Any OEditModel::translateDbColumnToControlValue()
712 : {
713 : OSL_PRECOND( m_pValueFormatter.get(), "OEditModel::translateDbColumnToControlValue: no value formatter!" );
714 34 : Any aRet;
715 34 : if ( m_pValueFormatter.get() )
716 : {
717 34 : OUString sValue( m_pValueFormatter->getFormattedValue() );
718 68 : if ( sValue.isEmpty()
719 26 : && m_pValueFormatter->getColumn().is()
720 60 : && m_pValueFormatter->getColumn()->wasNull()
721 : )
722 : {
723 : }
724 : else
725 : {
726 : // #i2817# OJ
727 34 : sal_uInt16 nMaxTextLen = getINT16( m_xAggregateSet->getPropertyValue( PROPERTY_MAXTEXTLEN ) );
728 34 : if ( nMaxTextLen && sValue.getLength() > nMaxTextLen )
729 : {
730 0 : sal_Int32 nDiff = sValue.getLength() - nMaxTextLen;
731 0 : sValue = sValue.replaceAt( nMaxTextLen, nDiff, OUString() );
732 : }
733 :
734 34 : aRet <<= sValue;
735 34 : }
736 : }
737 :
738 34 : return aRet.hasValue() ? aRet : makeAny( OUString() );
739 : }
740 :
741 : //------------------------------------------------------------------------------
742 15 : Any OEditModel::getDefaultForReset() const
743 : {
744 15 : return makeAny( m_aDefaultText );
745 : }
746 :
747 : //.........................................................................
748 72 : }
749 : //.........................................................................
750 :
751 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|