bump product version to 4.1.6.2
[LibreOffice.git] / forms / source / component / FormattedField.cxx
blobca314256620570987b47a640900749a7fffd34e7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "FormattedField.hxx"
22 #include "services.hxx"
23 #include "property.hrc"
24 #include "property.hxx"
25 #include "frm_resource.hxx"
26 #include "frm_resource.hrc"
27 #include "propertybaghelper.hxx"
28 #include <comphelper/sequence.hxx>
29 #include <comphelper/numbers.hxx>
30 #include <connectivity/dbtools.hxx>
31 #include <connectivity/dbconversion.hxx>
32 #include <svl/zforlist.hxx>
33 #include <svl/numuno.hxx>
34 #include <vcl/svapp.hxx>
35 #include <tools/debug.hxx>
36 #include <tools/wintypes.hxx>
37 #include <i18nlangtag/languagetag.hxx>
38 #include <rtl/textenc.h>
39 #include <com/sun/star/sdbc/DataType.hpp>
40 #include <com/sun/star/util/NumberFormat.hpp>
41 #include <com/sun/star/util/Date.hpp>
42 #include <com/sun/star/util/Time.hpp>
43 #include <com/sun/star/awt/MouseEvent.hpp>
44 #include <com/sun/star/form/XSubmit.hpp>
45 #include <com/sun/star/awt/XWindow.hpp>
46 #include <com/sun/star/awt/XKeyListener.hpp>
47 #include <com/sun/star/form/FormComponentType.hpp>
48 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
49 #include <com/sun/star/util/XNumberFormatTypes.hpp>
50 #include <com/sun/star/form/XForm.hpp>
51 #include <com/sun/star/container/XIndexAccess.hpp>
52 #include <osl/mutex.hxx>
53 // needed as long as we use the SolarMutex
54 #include <comphelper/streamsection.hxx>
55 #include <cppuhelper/weakref.hxx>
56 #include <unotools/desktopterminationobserver.hxx>
58 #include <list>
59 #include <algorithm>
61 using namespace dbtools;
62 using namespace ::com::sun::star::uno;
63 using namespace ::com::sun::star::sdb;
64 using namespace ::com::sun::star::sdbc;
65 using namespace ::com::sun::star::sdbcx;
66 using namespace ::com::sun::star::beans;
67 using namespace ::com::sun::star::container;
68 using namespace ::com::sun::star::form;
69 using namespace ::com::sun::star::awt;
70 using namespace ::com::sun::star::io;
71 using namespace ::com::sun::star::lang;
72 using namespace ::com::sun::star::util;
73 using namespace ::com::sun::star::form::binding;
75 namespace
77 typedef com::sun::star::util::Date UNODate;
78 typedef com::sun::star::util::Time UNOTime;
79 typedef com::sun::star::util::DateTime UNODateTime;
82 //.........................................................................
83 namespace frm
86 /*************************************************************************/
88 class StandardFormatsSupplier : protected SvNumberFormatsSupplierObj, public ::utl::ITerminationListener
90 protected:
91 SvNumberFormatter* m_pMyPrivateFormatter;
92 static WeakReference< XNumberFormatsSupplier > s_xDefaultFormatsSupplier;
94 public:
95 static Reference< XNumberFormatsSupplier > get( const Reference< XComponentContext >& _rxORB );
97 using SvNumberFormatsSupplierObj::operator new;
98 using SvNumberFormatsSupplierObj::operator delete;
100 protected:
101 StandardFormatsSupplier(const Reference< XComponentContext >& _rxFactory,LanguageType _eSysLanguage);
102 ~StandardFormatsSupplier();
104 protected:
105 virtual bool queryTermination() const;
106 virtual void notifyTermination();
109 //------------------------------------------------------------------
110 WeakReference< XNumberFormatsSupplier > StandardFormatsSupplier::s_xDefaultFormatsSupplier;
112 //------------------------------------------------------------------
113 StandardFormatsSupplier::StandardFormatsSupplier(const Reference< XComponentContext > & _rxContext,LanguageType _eSysLanguage)
114 :SvNumberFormatsSupplierObj()
115 ,m_pMyPrivateFormatter(new SvNumberFormatter(_rxContext, _eSysLanguage))
117 SetNumberFormatter(m_pMyPrivateFormatter);
119 // #i29147#
120 ::utl::DesktopTerminationObserver::registerTerminationListener( this );
123 //------------------------------------------------------------------
124 StandardFormatsSupplier::~StandardFormatsSupplier()
126 ::utl::DesktopTerminationObserver::revokeTerminationListener( this );
128 DELETEZ( m_pMyPrivateFormatter );
131 //------------------------------------------------------------------
132 Reference< XNumberFormatsSupplier > StandardFormatsSupplier::get( const Reference< XComponentContext >& _rxORB )
134 LanguageType eSysLanguage = LANGUAGE_SYSTEM;
136 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
137 Reference< XNumberFormatsSupplier > xSupplier = s_xDefaultFormatsSupplier;
138 if ( xSupplier.is() )
139 return xSupplier;
141 // get the Office's locale
142 eSysLanguage = SvtSysLocale().GetLanguageTag().getLanguageType( false);
145 StandardFormatsSupplier* pSupplier = new StandardFormatsSupplier( _rxORB, eSysLanguage );
146 Reference< XNumberFormatsSupplier > xNewlyCreatedSupplier( pSupplier );
149 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
150 Reference< XNumberFormatsSupplier > xSupplier = s_xDefaultFormatsSupplier;
151 if ( xSupplier.is() )
152 // somebody used the small time frame where the mutex was not locked to create and set
153 // the supplier
154 return xSupplier;
156 s_xDefaultFormatsSupplier = xNewlyCreatedSupplier;
159 return xNewlyCreatedSupplier;
162 //------------------------------------------------------------------
163 bool StandardFormatsSupplier::queryTermination() const
165 return true;
168 //------------------------------------------------------------------
169 void StandardFormatsSupplier::notifyTermination()
171 Reference< XNumberFormatsSupplier > xKeepAlive = this;
172 // when the application is terminating, release our static reference so that we are cleared/destructed
173 // earlier than upon unloading the library
174 // #i29147#
175 s_xDefaultFormatsSupplier = WeakReference< XNumberFormatsSupplier >( );
177 SetNumberFormatter( NULL );
178 DELETEZ( m_pMyPrivateFormatter );
181 /*************************************************************************/
182 //------------------------------------------------------------------
183 InterfaceRef SAL_CALL OFormattedControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory)
185 return *(new OFormattedControl(_rxFactory));
188 //------------------------------------------------------------------
189 Sequence<Type> OFormattedControl::_getTypes()
191 return ::comphelper::concatSequences(
192 OFormattedControl_BASE::getTypes(),
193 OBoundControl::_getTypes()
197 //------------------------------------------------------------------
198 Any SAL_CALL OFormattedControl::queryAggregation(const Type& _rType) throw (RuntimeException)
200 Any aReturn = OBoundControl::queryAggregation(_rType);
201 if (!aReturn.hasValue())
202 aReturn = OFormattedControl_BASE::queryInterface(_rType);
203 return aReturn;
207 DBG_NAME(OFormattedControl);
208 //------------------------------------------------------------------------------
209 OFormattedControl::OFormattedControl(const Reference<XMultiServiceFactory>& _rxFactory)
210 :OBoundControl(_rxFactory, VCL_CONTROL_FORMATTEDFIELD)
211 ,m_nKeyEvent(0)
213 DBG_CTOR(OFormattedControl,NULL);
215 increment(m_refCount);
217 Reference<XWindow> xComp;
218 if (query_aggregation(m_xAggregate, xComp))
220 xComp->addKeyListener(this);
223 decrement(m_refCount);
226 //------------------------------------------------------------------------------
227 OFormattedControl::~OFormattedControl()
229 if( m_nKeyEvent )
230 Application::RemoveUserEvent( m_nKeyEvent );
232 if (!OComponentHelper::rBHelper.bDisposed)
234 acquire();
235 dispose();
238 DBG_DTOR(OFormattedControl,NULL);
241 // XKeyListener
242 //------------------------------------------------------------------------------
243 void OFormattedControl::disposing(const EventObject& _rSource) throw(RuntimeException)
245 OBoundControl::disposing(_rSource);
248 //------------------------------------------------------------------------------
249 void OFormattedControl::keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException)
251 if( e.KeyCode != KEY_RETURN || e.Modifiers != 0 )
252 return;
254 // Steht das Control in einem Formular mit einer Submit-URL?
255 Reference<com::sun::star::beans::XPropertySet> xSet(getModel(), UNO_QUERY);
256 if( !xSet.is() )
257 return;
259 Reference<XFormComponent> xFComp(xSet, UNO_QUERY);
260 InterfaceRef xParent = xFComp->getParent();
261 if( !xParent.is() )
262 return;
264 Reference<com::sun::star::beans::XPropertySet> xFormSet(xParent, UNO_QUERY);
265 if( !xFormSet.is() )
266 return;
268 Any aTmp(xFormSet->getPropertyValue( PROPERTY_TARGET_URL ));
269 if (!isA(aTmp, static_cast< OUString* >(NULL)) ||
270 getString(aTmp).isEmpty() )
271 return;
273 Reference<XIndexAccess> xElements(xParent, UNO_QUERY);
274 sal_Int32 nCount = xElements->getCount();
275 if( nCount > 1 )
278 Reference<com::sun::star::beans::XPropertySet> xFCSet;
279 for( sal_Int32 nIndex=0; nIndex < nCount; nIndex++ )
281 // Any aElement(xElements->getByIndex(nIndex));
282 xElements->getByIndex(nIndex) >>= xFCSet;
284 if (hasProperty(PROPERTY_CLASSID, xFCSet) &&
285 getINT16(xFCSet->getPropertyValue(PROPERTY_CLASSID)) == FormComponentType::TEXTFIELD)
287 // Noch ein weiteres Edit gefunden ==> dann nicht submitten
288 if (xFCSet != xSet)
289 return;
294 // Da wir noch im Haender stehen, submit asynchron ausloesen
295 if( m_nKeyEvent )
296 Application::RemoveUserEvent( m_nKeyEvent );
297 m_nKeyEvent = Application::PostUserEvent( LINK(this, OFormattedControl,
298 OnKeyPressed) );
301 //------------------------------------------------------------------------------
302 void OFormattedControl::keyReleased(const ::com::sun::star::awt::KeyEvent& /*e*/) throw ( ::com::sun::star::uno::RuntimeException)
306 //------------------------------------------------------------------------------
307 IMPL_LINK(OFormattedControl, OnKeyPressed, void*, /*EMPTYARG*/)
309 m_nKeyEvent = 0;
311 Reference<XFormComponent> xFComp(getModel(), UNO_QUERY);
312 InterfaceRef xParent = xFComp->getParent();
313 Reference<XSubmit> xSubmit(xParent, UNO_QUERY);
314 if (xSubmit.is())
315 xSubmit->submit( Reference<XControl> (), ::com::sun::star::awt::MouseEvent() );
316 return 0L;
319 //------------------------------------------------------------------------------
320 StringSequence OFormattedControl::getSupportedServiceNames() throw()
322 StringSequence aSupported = OBoundControl::getSupportedServiceNames();
323 aSupported.realloc(aSupported.getLength() + 1);
325 OUString*pArray = aSupported.getArray();
326 pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_FORMATTEDFIELD;
327 return aSupported;
330 //------------------------------------------------------------------------------
331 void OFormattedControl::setDesignMode(sal_Bool bOn) throw ( ::com::sun::star::uno::RuntimeException)
333 OBoundControl::setDesignMode(bOn);
336 /*************************************************************************/
337 DBG_NAME(OFormattedModel)
338 //------------------------------------------------------------------
339 void OFormattedModel::implConstruct()
341 // members
342 m_bOriginalNumeric = sal_False;
343 m_bNumeric = sal_False;
344 m_xOriginalFormatter = NULL;
345 m_nKeyType = NumberFormat::UNDEFINED;
346 m_aNullDate = DBTypeConversion::getStandardDate();
347 m_nFieldType = DataType::OTHER;
349 // default our formats supplier
350 increment(m_refCount);
351 setPropertyToDefaultByHandle(PROPERTY_ID_FORMATSSUPPLIER);
352 decrement(m_refCount);
354 startAggregatePropertyListening( PROPERTY_FORMATKEY );
355 startAggregatePropertyListening( PROPERTY_FORMATSSUPPLIER );
358 //------------------------------------------------------------------
359 OFormattedModel::OFormattedModel(const Reference<XMultiServiceFactory>& _rxFactory)
360 :OEditBaseModel(_rxFactory, VCL_CONTROLMODEL_FORMATTEDFIELD, FRM_SUN_CONTROL_FORMATTEDFIELD, sal_True, sal_True )
361 // use the old control name for compytibility reasons
362 ,OErrorBroadcaster( OComponentHelper::rBHelper )
364 DBG_CTOR(OFormattedModel, NULL);
366 implConstruct();
368 m_nClassId = FormComponentType::TEXTFIELD;
369 initValueProperty( PROPERTY_EFFECTIVE_VALUE, PROPERTY_ID_EFFECTIVE_VALUE );
372 //------------------------------------------------------------------
373 OFormattedModel::OFormattedModel( const OFormattedModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory )
374 :OEditBaseModel( _pOriginal, _rxFactory )
375 ,OErrorBroadcaster( OComponentHelper::rBHelper )
377 DBG_CTOR(OFormattedModel, NULL);
379 implConstruct();
382 //------------------------------------------------------------------------------
383 OFormattedModel::~OFormattedModel()
385 DBG_DTOR(OFormattedModel, NULL);
388 // XCloneable
389 //------------------------------------------------------------------------------
390 IMPLEMENT_DEFAULT_CLONING( OFormattedModel )
392 //------------------------------------------------------------------------------
393 void SAL_CALL OFormattedModel::disposing()
395 OErrorBroadcaster::disposing();
396 OEditBaseModel::disposing();
399 // XServiceInfo
400 //------------------------------------------------------------------------------
401 StringSequence OFormattedModel::getSupportedServiceNames() throw()
403 StringSequence aSupported = OEditBaseModel::getSupportedServiceNames();
405 sal_Int32 nOldLen = aSupported.getLength();
406 aSupported.realloc( nOldLen + 8 );
407 OUString* pStoreTo = aSupported.getArray() + nOldLen;
409 *pStoreTo++ = BINDABLE_CONTROL_MODEL;
410 *pStoreTo++ = DATA_AWARE_CONTROL_MODEL;
411 *pStoreTo++ = VALIDATABLE_CONTROL_MODEL;
413 *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL;
414 *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL;
416 *pStoreTo++ = FRM_SUN_COMPONENT_FORMATTEDFIELD;
417 *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_FORMATTEDFIELD;
418 *pStoreTo++ = BINDABLE_DATABASE_FORMATTED_FIELD;
420 return aSupported;
423 // XAggregation
424 //------------------------------------------------------------------------------
425 Any SAL_CALL OFormattedModel::queryAggregation(const Type& _rType) throw(RuntimeException)
427 Any aReturn = OEditBaseModel::queryAggregation( _rType );
428 return aReturn.hasValue() ? aReturn : OErrorBroadcaster::queryInterface( _rType );
431 // XTypeProvider
432 //------------------------------------------------------------------------------
433 Sequence< Type > OFormattedModel::_getTypes()
435 return ::comphelper::concatSequences(
436 OEditBaseModel::_getTypes(),
437 OErrorBroadcaster::getTypes()
441 // XPersistObject
442 //------------------------------------------------------------------------------
443 OUString SAL_CALL OFormattedModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException)
445 return OUString(FRM_COMPONENT_EDIT);
448 // XPropertySet
449 //------------------------------------------------------------------------------
450 void OFormattedModel::describeFixedProperties( Sequence< Property >& _rProps ) const
452 BEGIN_DESCRIBE_PROPERTIES( 3, OEditBaseModel )
453 DECL_BOOL_PROP1(EMPTY_IS_NULL, BOUND);
454 DECL_PROP1(TABINDEX, sal_Int16, BOUND);
455 DECL_BOOL_PROP2(FILTERPROPOSAL, BOUND, MAYBEDEFAULT);
456 END_DESCRIBE_PROPERTIES();
459 //------------------------------------------------------------------------------
460 void OFormattedModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const
462 OEditBaseModel::describeAggregateProperties( _rAggregateProps );
464 // TreatAsNumeric nicht transient : wir wollen es an der UI anbinden (ist noetig, um dem EffectiveDefault
465 // - der kann Text oder Zahl sein - einen Sinn zu geben)
466 ModifyPropertyAttributes(_rAggregateProps, PROPERTY_TREATASNUMERIC, 0, PropertyAttribute::TRANSIENT);
467 // same for FormatKey
468 // (though the paragraph above for the TreatAsNumeric does not hold anymore - we do not have an UI for this.
469 // But we have for the format key ...)
470 ModifyPropertyAttributes(_rAggregateProps, PROPERTY_FORMATKEY, 0, PropertyAttribute::TRANSIENT);
472 RemoveProperty(_rAggregateProps, PROPERTY_STRICTFORMAT);
473 // no strict format property for formatted fields: it does not make sense, 'cause
474 // there is no general way to decide which characters/sub strings are allowed during the input of an
475 // arbitraryly formatted control
478 //------------------------------------------------------------------------------
479 void OFormattedModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const
481 OEditBaseModel::getFastPropertyValue(rValue, nHandle);
484 //------------------------------------------------------------------------------
485 void OFormattedModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( ::com::sun::star::uno::Exception)
487 OEditBaseModel::setFastPropertyValue_NoBroadcast(nHandle, rValue);
490 //------------------------------------------------------------------------------
491 sal_Bool OFormattedModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue)
492 throw( IllegalArgumentException )
494 return OEditBaseModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue);
497 //------------------------------------------------------------------------------
498 void OFormattedModel::setPropertyToDefaultByHandle(sal_Int32 nHandle)
500 if (nHandle == PROPERTY_ID_FORMATSSUPPLIER)
502 Reference<XNumberFormatsSupplier> xSupplier = calcDefaultFormatsSupplier();
503 DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::setPropertyToDefaultByHandle(FORMATSSUPPLIER) : have no aggregate !");
504 if (m_xAggregateSet.is())
505 m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(xSupplier));
507 else
508 OEditBaseModel::setPropertyToDefaultByHandle(nHandle);
511 //------------------------------------------------------------------------------
512 void OFormattedModel::setPropertyToDefault(const OUString& aPropertyName) throw( com::sun::star::beans::UnknownPropertyException, RuntimeException )
514 OPropertyArrayAggregationHelper& rPH = m_aPropertyBagHelper.getInfoHelper();
515 sal_Int32 nHandle = rPH.getHandleByName( aPropertyName );
517 if (nHandle == PROPERTY_ID_FORMATSSUPPLIER)
518 setPropertyToDefaultByHandle(PROPERTY_ID_FORMATSSUPPLIER);
519 else
520 OEditBaseModel::setPropertyToDefault(aPropertyName);
523 //------------------------------------------------------------------------------
524 Any OFormattedModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const
526 if (nHandle == PROPERTY_ID_FORMATSSUPPLIER)
528 Reference<XNumberFormatsSupplier> xSupplier = calcDefaultFormatsSupplier();
529 return makeAny(xSupplier);
531 else
532 return OEditBaseModel::getPropertyDefaultByHandle(nHandle);
535 //------------------------------------------------------------------------------
536 Any SAL_CALL OFormattedModel::getPropertyDefault( const OUString& aPropertyName ) throw( com::sun::star::beans::UnknownPropertyException, RuntimeException )
538 OPropertyArrayAggregationHelper& rPH = m_aPropertyBagHelper.getInfoHelper();
539 sal_Int32 nHandle = rPH.getHandleByName( aPropertyName );
541 if (nHandle == PROPERTY_ID_FORMATSSUPPLIER)
542 return getPropertyDefaultByHandle(PROPERTY_ID_FORMATSSUPPLIER);
543 else
544 return OEditBaseModel::getPropertyDefault(aPropertyName);
547 //------------------------------------------------------------------------------
548 void OFormattedModel::_propertyChanged( const com::sun::star::beans::PropertyChangeEvent& evt ) throw(RuntimeException)
550 // TODO: check how this works with external bindings
552 OSL_ENSURE( evt.Source == m_xAggregateSet, "OFormattedModel::_propertyChanged: where did this come from?" );
553 if ( evt.Source == m_xAggregateSet )
555 Reference< XPropertySet > xSourceSet( evt.Source, UNO_QUERY );
556 if ( evt.PropertyName.equals( PROPERTY_FORMATKEY ) )
558 if ( evt.NewValue.getValueType().getTypeClass() == TypeClass_LONG )
562 ::osl::MutexGuard aGuard( m_aMutex );
564 Reference<XNumberFormatsSupplier> xSupplier( calcFormatsSupplier() );
565 m_nKeyType = getNumberFormatType(xSupplier->getNumberFormats(), getINT32( evt.NewValue ) );
567 // as m_aSaveValue (which is used by commitControlValueToDbColumn) is format dependent we have
568 // to recalc it, which is done by translateDbColumnToControlValue
569 if ( m_xColumn.is() && m_xAggregateFastSet.is() && !m_xCursor->isBeforeFirst() && !m_xCursor->isAfterLast())
571 setControlValue( translateDbColumnToControlValue(), eOther );
574 // if we're connected to an external value binding, then re-calculate the type
575 // used to exchange the value - it depends on the format, too
576 if ( hasExternalValueBinding() )
578 calculateExternalValueType();
581 catch(const Exception&)
585 return;
588 if ( evt.PropertyName.equals( PROPERTY_FORMATSSUPPLIER ) )
590 updateFormatterNullDate();
591 return;
594 OBoundControlModel::_propertyChanged( evt );
598 //------------------------------------------------------------------------------
599 void OFormattedModel::updateFormatterNullDate()
601 // calc the current NULL date
602 Reference< XNumberFormatsSupplier > xSupplier( calcFormatsSupplier() );
603 if ( xSupplier.is() )
604 xSupplier->getNumberFormatSettings()->getPropertyValue( OUString( "NullDate" ) ) >>= m_aNullDate;
607 //------------------------------------------------------------------------------
608 Reference< XNumberFormatsSupplier > OFormattedModel::calcFormatsSupplier() const
610 Reference<XNumberFormatsSupplier> xSupplier;
612 DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::calcFormatsSupplier : have no aggregate !");
613 // hat mein aggregiertes Model einen FormatSupplier ?
614 if( m_xAggregateSet.is() )
615 m_xAggregateSet->getPropertyValue(PROPERTY_FORMATSSUPPLIER) >>= xSupplier;
617 if (!xSupplier.is())
618 // check if my parent form has a supplier
619 xSupplier = calcFormFormatsSupplier();
621 if (!xSupplier.is())
622 xSupplier = calcDefaultFormatsSupplier();
624 DBG_ASSERT(xSupplier.is(), "OFormattedModel::calcFormatsSupplier : no supplier !");
625 // jetzt sollte aber einer da sein
626 return xSupplier;
629 //------------------------------------------------------------------------------
630 Reference<XNumberFormatsSupplier> OFormattedModel::calcFormFormatsSupplier() const
632 Reference<XChild> xMe;
633 query_interface(static_cast<XWeak*>(const_cast<OFormattedModel*>(this)), xMe);
634 // damit stellen wir sicher, dass wir auch fuer den Fall der Aggregation das richtige
635 // Objekt bekommen
636 DBG_ASSERT(xMe.is(), "OFormattedModel::calcFormFormatsSupplier : I should have a content interface !");
638 // jetzt durchhangeln nach oben, bis wir auf eine starform treffen (angefangen mit meinem eigenen Parent)
639 Reference<XChild> xParent(xMe->getParent(), UNO_QUERY);
640 Reference<XForm> xNextParentForm(xParent, UNO_QUERY);
641 while (!xNextParentForm.is() && xParent.is())
643 xParent = xParent.query( xParent->getParent() );
644 xNextParentForm = xNextParentForm.query( xParent );
647 if (!xNextParentForm.is())
649 OSL_FAIL("OFormattedModel::calcFormFormatsSupplier : have no ancestor which is a form !");
650 return NULL;
653 // den FormatSupplier von meinem Vorfahren (falls der einen hat)
654 Reference< XRowSet > xRowSet( xNextParentForm, UNO_QUERY );
655 Reference< XNumberFormatsSupplier > xSupplier;
656 if (xRowSet.is())
657 xSupplier = getNumberFormats( getConnection(xRowSet), sal_True, getContext().getUNOContext() );
658 return xSupplier;
661 //------------------------------------------------------------------------------
662 Reference< XNumberFormatsSupplier > OFormattedModel::calcDefaultFormatsSupplier() const
664 return StandardFormatsSupplier::get( getContext().getUNOContext() );
667 // XBoundComponent
668 //------------------------------------------------------------------------------
669 void OFormattedModel::loaded(const EventObject& rEvent) throw ( ::com::sun::star::uno::RuntimeException)
671 // HACK : our onConnectedDbColumn accesses our NumberFormatter which locks the solar mutex (as it doesn't have
672 // an own one). To prevent deadlocks with other threads which may request a property from us in an
673 // UI-triggered action (e.g. an tooltip) we lock the solar mutex _here_ before our base class locks
674 // it's own muext (which is used for property requests)
675 // alternative a): we use two mutexes, one which is passed to the OPropertysetHelper and used for
676 // property requests and one for our own code. This would need a lot of code rewriting
677 // alternative b): The NumberFormatter has to be really threadsafe (with an own mutex), which is
678 // the only "clean" solution for me.
680 SolarMutexGuard aGuard;
681 OEditBaseModel::loaded(rEvent);
684 //------------------------------------------------------------------------------
685 void OFormattedModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm )
687 m_xOriginalFormatter = NULL;
689 // get some properties of the field
690 m_nFieldType = DataType::OTHER;
691 Reference<XPropertySet> xField = getField();
692 if ( xField.is() )
693 xField->getPropertyValue( PROPERTY_FIELDTYPE ) >>= m_nFieldType;
695 sal_Int32 nFormatKey = 0;
697 DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::onConnectedDbColumn : have no aggregate !");
698 if (m_xAggregateSet.is())
699 { // all the following doesn't make any sense if we have no aggregate ...
700 Any aSupplier = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATSSUPPLIER);
701 DBG_ASSERT( aSupplier.hasValue(), "OFormattedModel::onConnectedDbColumn : invalid property value !" );
702 // das sollte im Constructor oder im read auf was richtiges gesetzt worden sein
704 Any aFmtKey = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATKEY);
705 if ( !(aFmtKey >>= nFormatKey ) )
706 { // nobody gave us a format to use. So we examine the field we're bound to for a
707 // format key, and use it ourself, too
708 sal_Int32 nType = DataType::VARCHAR;
709 if (xField.is())
711 aFmtKey = xField->getPropertyValue(PROPERTY_FORMATKEY);
712 xField->getPropertyValue(PROPERTY_FIELDTYPE) >>= nType ;
715 Reference<XNumberFormatsSupplier> xSupplier = calcFormFormatsSupplier();
716 DBG_ASSERT(xSupplier.is(), "OFormattedModel::onConnectedDbColumn : bound to a field but no parent with a formatter ? how this ?");
717 if (xSupplier.is())
719 m_bOriginalNumeric = getBOOL(getPropertyValue(PROPERTY_TREATASNUMERIC));
721 if (!aFmtKey.hasValue())
722 { // we aren't bound to a field (or this field's format is invalid)
723 // -> determine the standard text (or numeric) format of the supplier
724 Reference<XNumberFormatTypes> xTypes(xSupplier->getNumberFormats(), UNO_QUERY);
725 if (xTypes.is())
727 Locale aApplicationLocale = Application::GetSettings().GetUILanguageTag().getLocale();
729 if (m_bOriginalNumeric)
730 aFmtKey <<= (sal_Int32)xTypes->getStandardFormat(NumberFormat::NUMBER, aApplicationLocale);
731 else
732 aFmtKey <<= (sal_Int32)xTypes->getStandardFormat(NumberFormat::TEXT, aApplicationLocale);
736 aSupplier >>= m_xOriginalFormatter;
737 m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(xSupplier));
738 m_xAggregateSet->setPropertyValue(PROPERTY_FORMATKEY, aFmtKey);
740 // das Numeric-Flag an mein gebundenes Feld anpassen
741 if (xField.is())
743 m_bNumeric = sal_False;
744 switch (nType)
746 case DataType::BIT:
747 case DataType::BOOLEAN:
748 case DataType::TINYINT:
749 case DataType::SMALLINT:
750 case DataType::INTEGER:
751 case DataType::BIGINT:
752 case DataType::FLOAT:
753 case DataType::REAL:
754 case DataType::DOUBLE:
755 case DataType::NUMERIC:
756 case DataType::DECIMAL:
757 case DataType::DATE:
758 case DataType::TIME:
759 case DataType::TIMESTAMP:
760 m_bNumeric = sal_True;
761 break;
764 else
765 m_bNumeric = m_bOriginalNumeric;
767 setPropertyValue(PROPERTY_TREATASNUMERIC, makeAny((sal_Bool)m_bNumeric));
769 OSL_VERIFY( aFmtKey >>= nFormatKey );
774 Reference<XNumberFormatsSupplier> xSupplier = calcFormatsSupplier();
775 m_bNumeric = getBOOL( getPropertyValue( PROPERTY_TREATASNUMERIC ) );
776 m_nKeyType = getNumberFormatType( xSupplier->getNumberFormats(), nFormatKey );
777 xSupplier->getNumberFormatSettings()->getPropertyValue( OUString("NullDate") ) >>= m_aNullDate;
779 OEditBaseModel::onConnectedDbColumn( _rxForm );
782 //------------------------------------------------------------------------------
783 void OFormattedModel::onDisconnectedDbColumn()
785 OEditBaseModel::onDisconnectedDbColumn();
786 if (m_xOriginalFormatter.is())
787 { // unser aggregiertes Model hatte keinerlei Format-Informationen
788 m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(m_xOriginalFormatter));
789 m_xAggregateSet->setPropertyValue(PROPERTY_FORMATKEY, Any());
790 setPropertyValue(PROPERTY_TREATASNUMERIC, makeAny((sal_Bool)m_bOriginalNumeric));
791 m_xOriginalFormatter = NULL;
794 m_nFieldType = DataType::OTHER;
795 m_nKeyType = NumberFormat::UNDEFINED;
796 m_aNullDate = DBTypeConversion::getStandardDate();
799 //------------------------------------------------------------------------------
800 void OFormattedModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
802 OEditBaseModel::write(_rxOutStream);
803 _rxOutStream->writeShort(0x0003);
805 DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::write : have no aggregate !");
807 // mein Format (evtl. void) in ein persistentes Format bringen (der Supplier zusammen mit dem Key ist es zwar auch,
808 // aber deswegen muessen wir ja nicht gleich den ganzen Supplier speichern, das waere ein klein wenig Overhead ;)
810 Reference<XNumberFormatsSupplier> xSupplier;
811 Any aFmtKey;
812 sal_Bool bVoidKey = sal_True;
813 if (m_xAggregateSet.is())
815 Any aSupplier = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATSSUPPLIER);
816 if (aSupplier.getValueType().getTypeClass() != TypeClass_VOID)
818 OSL_VERIFY( aSupplier >>= xSupplier );
821 aFmtKey = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATKEY);
822 bVoidKey = (!xSupplier.is() || !aFmtKey.hasValue()) || (isLoaded() && m_xOriginalFormatter.is());
823 // (kein Fomatter und/oder Key) oder (loaded und faked Formatter)
826 _rxOutStream->writeBoolean(!bVoidKey);
827 if (!bVoidKey)
829 // aus dem FormatKey und dem Formatter persistente Angaben basteln
831 Any aKey = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATKEY);
832 sal_Int32 nKey = aKey.hasValue() ? getINT32(aKey) : 0;
834 Reference<XNumberFormats> xFormats = xSupplier->getNumberFormats();
836 OUString sFormatDescription;
837 LanguageType eFormatLanguage = LANGUAGE_DONTKNOW;
839 static const OUString s_aLocaleProp ("Locale");
840 Reference<com::sun::star::beans::XPropertySet> xFormat = xFormats->getByKey(nKey);
841 if (hasProperty(s_aLocaleProp, xFormat))
843 Any aLocale = xFormat->getPropertyValue(s_aLocaleProp);
844 DBG_ASSERT(isA(aLocale, static_cast<Locale*>(NULL)), "OFormattedModel::write : invalid language property !");
845 if (isA(aLocale, static_cast<Locale*>(NULL)))
847 Locale* pLocale = (Locale*)aLocale.getValue();
848 eFormatLanguage = LanguageTag( *pLocale ).getLanguageType( false);
852 static const OUString s_aFormatStringProp ("FormatString");
853 if (hasProperty(s_aFormatStringProp, xFormat))
854 xFormat->getPropertyValue(s_aFormatStringProp) >>= sFormatDescription;
856 _rxOutStream->writeUTF(sFormatDescription);
857 _rxOutStream->writeLong((sal_Int32)eFormatLanguage);
860 // version 2 : write the properties common to all OEditBaseModels
861 writeCommonEditProperties(_rxOutStream);
863 // version 3 : write the effective value property of the aggregate
864 // Due to a bug within the UnoControlFormattedFieldModel implementation (our default aggregate) this props value isn't correctly read
865 // and this can't be corrected without being incompatible.
866 // so we have our own handling.
868 // and to be a little bit more compatible we make the following section skippable
870 Reference< XDataOutputStream > xOut(_rxOutStream, UNO_QUERY);
871 OStreamSection aDownCompat(xOut);
873 // a sub version within the skippable block
874 _rxOutStream->writeShort(0x0000);
876 // version 0: the effective value of the aggregate
877 Any aEffectiveValue;
878 if (m_xAggregateSet.is())
880 try { aEffectiveValue = m_xAggregateSet->getPropertyValue(PROPERTY_EFFECTIVE_VALUE); } catch(const Exception&) { }
884 OStreamSection aDownCompat2(xOut);
885 switch (aEffectiveValue.getValueType().getTypeClass())
887 case TypeClass_STRING:
888 _rxOutStream->writeShort(0x0000);
889 _rxOutStream->writeUTF(::comphelper::getString(aEffectiveValue));
890 break;
891 case TypeClass_DOUBLE:
892 _rxOutStream->writeShort(0x0001);
893 _rxOutStream->writeDouble(::comphelper::getDouble(aEffectiveValue));
894 break;
895 default: // void and all unknown states
896 DBG_ASSERT(!aEffectiveValue.hasValue(), "FmXFormattedModel::write : unknown property value type !");
897 _rxOutStream->writeShort(0x0002);
898 break;
904 //------------------------------------------------------------------------------
905 void OFormattedModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
907 OEditBaseModel::read(_rxInStream);
908 sal_uInt16 nVersion = _rxInStream->readShort();
910 Reference<XNumberFormatsSupplier> xSupplier;
911 sal_Int32 nKey = -1;
912 switch (nVersion)
914 case 0x0001 :
915 case 0x0002 :
916 case 0x0003 :
918 sal_Bool bNonVoidKey = _rxInStream->readBoolean();
919 if (bNonVoidKey)
921 // den String und die Language lesen ....
922 OUString sFormatDescription = _rxInStream->readUTF();
923 LanguageType eDescriptionLanguage = (LanguageType)_rxInStream->readLong();
925 // und daraus von einem Formatter zu einem Key zusammenwuerfeln lassen ...
926 xSupplier = calcFormatsSupplier();
927 // calcFormatsSupplier nimmt erst den vom Model, dann einen von der starform, dann einen ganz neuen ....
928 Reference<XNumberFormats> xFormats = xSupplier->getNumberFormats();
930 if (xFormats.is())
932 Locale aDescriptionLanguage( LanguageTag(eDescriptionLanguage).getLocale());
934 nKey = xFormats->queryKey(sFormatDescription, aDescriptionLanguage, sal_False);
935 if (nKey == (sal_Int32)-1)
936 { // noch nicht vorhanden in meinem Formatter ...
937 nKey = xFormats->addNew(sFormatDescription, aDescriptionLanguage);
941 if ((nVersion == 0x0002) || (nVersion == 0x0003))
942 readCommonEditProperties(_rxInStream);
944 if (nVersion == 0x0003)
945 { // since version 3 there is a "skippable" block at this position
946 Reference< XDataInputStream > xIn(_rxInStream, UNO_QUERY);
947 OStreamSection aDownCompat(xIn);
949 sal_Int16 nSubVersion = _rxInStream->readShort();
950 (void)nSubVersion;
952 // version 0 and higher : the "effective value" property
953 Any aEffectiveValue;
955 OStreamSection aDownCompat2(xIn);
956 switch (_rxInStream->readShort())
958 case 0: // String
959 aEffectiveValue <<= _rxInStream->readUTF();
960 break;
961 case 1: // double
962 aEffectiveValue <<= (double)_rxInStream->readDouble();
963 break;
964 case 2:
965 break;
966 case 3:
967 OSL_FAIL("FmXFormattedModel::read : unknown effective value type !");
971 // this property is only to be set if we have no control source : in all other cases the base class did a
972 // reset after it's read and this set the effective value to a default value
973 if ( m_xAggregateSet.is() && getControlSource().isEmpty() )
977 m_xAggregateSet->setPropertyValue(PROPERTY_EFFECTIVE_VALUE, aEffectiveValue);
979 catch(const Exception&)
985 break;
986 default :
987 OSL_FAIL("OFormattedModel::read : unknown version !");
988 // dann bleibt das Format des aggregierten Sets, wie es bei der Erzeugung ist : void
989 defaultCommonEditProperties();
990 break;
993 if ((nKey != -1) && m_xAggregateSet.is())
995 m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(xSupplier));
996 m_xAggregateSet->setPropertyValue(PROPERTY_FORMATKEY, makeAny((sal_Int32)nKey));
998 else
1000 setPropertyToDefault(PROPERTY_FORMATSSUPPLIER);
1001 setPropertyToDefault(PROPERTY_FORMATKEY);
1005 //------------------------------------------------------------------------------
1006 sal_uInt16 OFormattedModel::getPersistenceFlags() const
1008 return (OEditBaseModel::getPersistenceFlags() & ~PF_HANDLE_COMMON_PROPS);
1009 // a) we do our own call to writeCommonEditProperties
1012 //------------------------------------------------------------------------------
1013 sal_Bool OFormattedModel::commitControlValueToDbColumn( bool /*_bPostReset*/ )
1015 Any aControlValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) );
1016 if ( aControlValue != m_aSaveValue )
1018 // Leerstring + EmptyIsNull = void
1019 if ( !aControlValue.hasValue()
1020 || ( ( aControlValue.getValueType().getTypeClass() == TypeClass_STRING )
1021 && getString( aControlValue ).isEmpty()
1022 && m_bEmptyIsNull
1025 m_xColumnUpdate->updateNull();
1026 else
1030 double f = 0.0;
1031 if ( aControlValue.getValueType().getTypeClass() == TypeClass_DOUBLE || (aControlValue >>= f)) // #i110323
1033 DBTypeConversion::setValue( m_xColumnUpdate, m_aNullDate, getDouble( aControlValue ), m_nKeyType );
1035 else
1037 DBG_ASSERT( aControlValue.getValueType().getTypeClass() == TypeClass_STRING, "OFormattedModel::commitControlValueToDbColumn: invalud value type !" );
1038 m_xColumnUpdate->updateString( getString( aControlValue ) );
1041 catch(const Exception&)
1043 return sal_False;
1046 m_aSaveValue = aControlValue;
1048 return sal_True;
1051 //------------------------------------------------------------------------------
1052 void OFormattedModel::onConnectedExternalValue( )
1054 OEditBaseModel::onConnectedExternalValue();
1055 updateFormatterNullDate();
1058 //------------------------------------------------------------------------------
1059 Any OFormattedModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const
1061 Any aControlValue;
1062 switch( _rExternalValue.getValueTypeClass() )
1064 case TypeClass_VOID:
1065 break;
1067 case TypeClass_STRING:
1068 aControlValue = _rExternalValue;
1069 break;
1071 case TypeClass_BOOLEAN:
1073 sal_Bool bExternalValue = sal_False;
1074 _rExternalValue >>= bExternalValue;
1075 aControlValue <<= (double)( bExternalValue ? 1 : 0 );
1077 break;
1079 default:
1081 if ( _rExternalValue.getValueType().equals( ::getCppuType( static_cast< UNODate* >( NULL ) ) ) )
1083 UNODate aDate;
1084 _rExternalValue >>= aDate;
1085 aControlValue <<= DBTypeConversion::toDouble( aDate, m_aNullDate );
1087 else if ( _rExternalValue.getValueType().equals( ::getCppuType( static_cast< UNOTime* >( NULL ) ) ) )
1089 UNOTime aTime;
1090 _rExternalValue >>= aTime;
1091 aControlValue <<= DBTypeConversion::toDouble( aTime );
1093 else if ( _rExternalValue.getValueType().equals( ::getCppuType( static_cast< UNODateTime* >( NULL ) ) ) )
1095 UNODateTime aDateTime;
1096 _rExternalValue >>= aDateTime;
1097 aControlValue <<= DBTypeConversion::toDouble( aDateTime, m_aNullDate );
1099 else
1101 OSL_ENSURE( _rExternalValue.getValueTypeClass() == TypeClass_DOUBLE,
1102 "OFormattedModel::translateExternalValueToControlValue: don't know how to translate this type!" );
1103 double fValue = 0;
1104 OSL_VERIFY( _rExternalValue >>= fValue );
1105 aControlValue <<= fValue;
1110 return aControlValue;
1113 //------------------------------------------------------------------------------
1114 Any OFormattedModel::translateControlValueToExternalValue( ) const
1116 OSL_PRECOND( hasExternalValueBinding(),
1117 "OFormattedModel::translateControlValueToExternalValue: precondition not met!" );
1119 Any aControlValue( getControlValue() );
1120 if ( !aControlValue.hasValue() )
1121 return aControlValue;
1123 Any aExternalValue;
1125 // translate into the external value type
1126 Type aExternalValueType( getExternalValueType() );
1127 switch ( aExternalValueType.getTypeClass() )
1129 case TypeClass_STRING:
1131 OUString sString;
1132 if ( aControlValue >>= sString )
1134 aExternalValue <<= sString;
1135 break;
1138 // NO break here!
1140 case TypeClass_BOOLEAN:
1142 double fValue = 0;
1143 OSL_VERIFY( aControlValue >>= fValue );
1144 // if this asserts ... well, the somebody set the TreatAsNumeric property to false,
1145 // and the control value is a string. This implies some weird misconfiguration
1146 // of the FormattedModel, so we won't care for it for the moment.
1147 aExternalValue <<= (sal_Bool)( fValue ? sal_True : sal_False );
1149 break;
1151 default:
1153 double fValue = 0;
1154 OSL_VERIFY( aControlValue >>= fValue );
1155 // if this asserts ... well, the somebody set the TreatAsNumeric property to false,
1156 // and the control value is a string. This implies some weird misconfiguration
1157 // of the FormattedModel, so we won't care for it for the moment.
1159 if ( aExternalValueType.equals( ::getCppuType( static_cast< UNODate* >( NULL ) ) ) )
1161 aExternalValue <<= DBTypeConversion::toDate( fValue, m_aNullDate );
1163 else if ( aExternalValueType.equals( ::getCppuType( static_cast< UNOTime* >( NULL ) ) ) )
1165 aExternalValue <<= DBTypeConversion::toTime( fValue );
1167 else if ( aExternalValueType.equals( ::getCppuType( static_cast< UNODateTime* >( NULL ) ) ) )
1169 aExternalValue <<= DBTypeConversion::toDateTime( fValue, m_aNullDate );
1171 else
1173 OSL_ENSURE( aExternalValueType.equals( ::getCppuType( static_cast< double* >( NULL ) ) ),
1174 "OFormattedModel::translateControlValueToExternalValue: don't know how to translate this type!" );
1175 aExternalValue <<= fValue;
1178 break;
1180 return aExternalValue;
1183 //------------------------------------------------------------------------------
1184 Any OFormattedModel::translateDbColumnToControlValue()
1186 if ( m_bNumeric )
1187 m_aSaveValue <<= DBTypeConversion::getValue( m_xColumn, m_aNullDate ); // #100056# OJ
1188 else
1189 m_aSaveValue <<= m_xColumn->getString();
1191 if ( m_xColumn->wasNull() )
1192 m_aSaveValue.clear();
1194 return m_aSaveValue;
1197 // -----------------------------------------------------------------------------
1198 Sequence< Type > OFormattedModel::getSupportedBindingTypes()
1200 ::std::list< Type > aTypes;
1201 aTypes.push_back( ::getCppuType( static_cast< double* >( NULL ) ) );
1203 switch ( m_nKeyType & ~NumberFormat::DEFINED )
1205 case NumberFormat::DATE:
1206 aTypes.push_front(::getCppuType( static_cast< UNODate* >( NULL ) ) );
1207 break;
1208 case NumberFormat::TIME:
1209 aTypes.push_front(::getCppuType( static_cast< UNOTime* >( NULL ) ) );
1210 break;
1211 case NumberFormat::DATETIME:
1212 aTypes.push_front(::getCppuType( static_cast< UNODateTime* >( NULL ) ) );
1213 break;
1214 case NumberFormat::TEXT:
1215 aTypes.push_front(::getCppuType( static_cast< OUString* >( NULL ) ) );
1216 break;
1217 case NumberFormat::LOGICAL:
1218 aTypes.push_front(::getCppuType( static_cast< sal_Bool* >( NULL ) ) );
1219 break;
1222 Sequence< Type > aTypesRet( aTypes.size() );
1223 ::std::copy( aTypes.begin(), aTypes.end(), aTypesRet.getArray() );
1224 return aTypesRet;
1227 //------------------------------------------------------------------------------
1228 Any OFormattedModel::getDefaultForReset() const
1230 return m_xAggregateSet->getPropertyValue( PROPERTY_EFFECTIVE_DEFAULT );
1233 //------------------------------------------------------------------------------
1234 void OFormattedModel::resetNoBroadcast()
1236 OEditBaseModel::resetNoBroadcast();
1237 m_aSaveValue.clear();
1240 //.........................................................................
1242 //.........................................................................
1244 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */