1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
20 #include "EditBase.hxx"
21 #include "property.hxx"
22 #include "property.hrc"
23 #include "services.hxx"
24 #include <tools/debug.hxx>
25 #include <comphelper/basicio.hxx>
26 #include <cppuhelper/queryinterface.hxx>
27 #include "frm_resource.hxx"
28 #include "frm_resource.hrc"
29 #include <tools/time.hxx>
30 #include <tools/date.hxx>
31 #include <com/sun/star/util/Time.hpp>
32 #include <com/sun/star/util/Date.hpp>
37 using namespace ::com::sun::star
;
38 using namespace ::com::sun::star::uno
;
39 using namespace ::com::sun::star::sdb
;
40 using namespace ::com::sun::star::sdbc
;
41 using namespace ::com::sun::star::sdbcx
;
42 using namespace ::com::sun::star::beans
;
43 using namespace ::com::sun::star::container
;
44 using namespace ::com::sun::star::form
;
45 using namespace ::com::sun::star::awt
;
46 using namespace ::com::sun::star::io
;
47 using namespace ::com::sun::star::lang
;
48 using namespace ::com::sun::star::util
;
52 const sal_uInt16 DEFAULT_LONG
= 0x0001;
53 const sal_uInt16 DEFAULT_DOUBLE
= 0x0002;
54 const sal_uInt16 FILTERPROPOSAL
= 0x0004;
55 const sal_uInt16 DEFAULT_TIME
= 0x0008;
56 const sal_uInt16 DEFAULT_DATE
= 0x0010;
60 OEditBaseModel::OEditBaseModel( const Reference
< XComponentContext
>& _rxFactory
, const OUString
& rUnoControlModelName
,
61 const OUString
& rDefault
, const bool _bSupportExternalBinding
, const bool _bSupportsValidation
)
62 :OBoundControlModel( _rxFactory
, rUnoControlModelName
, rDefault
, true, _bSupportExternalBinding
, _bSupportsValidation
)
63 ,m_nLastReadVersion(0)
65 ,m_bFilterProposal(false)
70 OEditBaseModel::OEditBaseModel( const OEditBaseModel
* _pOriginal
, const Reference
< XComponentContext
>& _rxFactory
)
71 :OBoundControlModel( _pOriginal
, _rxFactory
)
72 ,m_nLastReadVersion(0)
75 m_bFilterProposal
= _pOriginal
->m_bFilterProposal
;
76 m_bEmptyIsNull
= _pOriginal
->m_bEmptyIsNull
;
77 m_aDefault
= _pOriginal
->m_aDefault
;
78 m_aDefaultText
= _pOriginal
->m_aDefaultText
;
82 OEditBaseModel::~OEditBaseModel( )
88 void OEditBaseModel::write(const Reference
<XObjectOutputStream
>& _rxOutStream
) throw ( ::com::sun::star::io::IOException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
90 OBoundControlModel::write(_rxOutStream
);
93 sal_uInt16 nVersionId
= 0x0006;
94 DBG_ASSERT((getPersistenceFlags() & ~PF_SPECIAL_FLAGS
) == 0,
95 "OEditBaseModel::write : invalid special version flags !");
96 // please don't use other flags, older versions can't interpret them !
98 nVersionId
|= getPersistenceFlags();
99 _rxOutStream
->writeShort(nVersionId
);
102 _rxOutStream
->writeShort(0); // obsolete
103 _rxOutStream
<< m_aDefaultText
;
106 sal_uInt16 nAnyMask
= 0;
107 if (m_aDefault
.getValueType().getTypeClass() == TypeClass_LONG
)
108 nAnyMask
|= DEFAULT_LONG
;
109 else if (m_aDefault
.getValueType().getTypeClass() == TypeClass_DOUBLE
)
110 nAnyMask
|= DEFAULT_DOUBLE
;
111 else if (m_aDefault
.getValueType() == cppu::UnoType
<util::Time
>::get())
112 nAnyMask
|= DEFAULT_TIME
;
113 else if (m_aDefault
.getValueType() == cppu::UnoType
<util::Date
>::get())
114 nAnyMask
|= DEFAULT_DATE
;
116 if (m_bFilterProposal
) // Don't save a value, because it's boolean
117 nAnyMask
|= FILTERPROPOSAL
;
119 _rxOutStream
->writeBoolean(m_bEmptyIsNull
);
120 _rxOutStream
->writeShort(nAnyMask
);
122 if ((nAnyMask
& DEFAULT_LONG
) == DEFAULT_LONG
)
123 _rxOutStream
->writeLong(getINT32(m_aDefault
));
124 else if ((nAnyMask
& DEFAULT_DOUBLE
) == DEFAULT_DOUBLE
)
125 _rxOutStream
->writeDouble(getDouble(m_aDefault
));
126 else if ((nAnyMask
& DEFAULT_TIME
) == DEFAULT_TIME
)
129 OSL_VERIFY(m_aDefault
>>= aTime
);
130 _rxOutStream
->writeHyper(::tools::Time(aTime
).GetTime());
132 else if ((nAnyMask
& DEFAULT_DATE
) == DEFAULT_DATE
)
135 OSL_VERIFY(m_aDefault
>>= aDate
);
136 _rxOutStream
->writeLong(::Date(aDate
).GetDate());
139 // since version 5 we write the help text
140 writeHelpTextCompatibly(_rxOutStream
);
141 // (that's potentially bad : at the time I added the above line we had two derived classes : OEditModel and
142 // OFormattedModel. The first one does not have an own version handling, so it can't write the help text itself,
143 // the second one does it's own writing (reading) after calling our method, so normally we shouldn't write any
144 // additional members as this is not compatible to older office versions.
145 // We decided to place the writing of the help text here as it seems the less worse alternative. There is no delivered
146 // office version including formatted controls (and thus the OFormattedModel), and the OFormattedModel::read seems
147 // robust against this change (as it will read a wrong and unknown file version and thus set it's members to defaults).
149 if ((nVersionId
& PF_HANDLE_COMMON_PROPS
) != 0)
150 writeCommonEditProperties(_rxOutStream
);
152 // !!! properties common to all OEditBaseModel derived classes should be written in writeCommonEditProperties !!!
156 sal_uInt16
OEditBaseModel::getPersistenceFlags() const
158 return PF_HANDLE_COMMON_PROPS
;
162 void OEditBaseModel::read(const Reference
<XObjectInputStream
>& _rxInStream
) throw ( ::com::sun::star::io::IOException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
164 OBoundControlModel::read(_rxInStream
);
165 ::osl::MutexGuard
aGuard(m_aMutex
);
167 // Version's own version number
168 sal_uInt16 nVersion
= _rxInStream
->readShort();
169 m_nLastReadVersion
= nVersion
;
171 bool bHandleCommonProps
= (nVersion
& PF_HANDLE_COMMON_PROPS
) != 0;
172 nVersion
= nVersion
& ~PF_SPECIAL_FLAGS
;
175 _rxInStream
->readShort();
177 _rxInStream
>> m_aDefaultText
;
179 if (nVersion
>= 0x0003)
181 m_bEmptyIsNull
= _rxInStream
->readBoolean();
183 sal_uInt16 nAnyMask
= _rxInStream
->readShort();
184 if ((nAnyMask
& DEFAULT_LONG
) == DEFAULT_LONG
)
186 sal_Int32 nValue
= _rxInStream
->readLong();
187 m_aDefault
<<= (sal_Int32
)nValue
;
189 else if ((nAnyMask
& DEFAULT_DOUBLE
) == DEFAULT_DOUBLE
)
191 double fValue
= _rxInStream
->readDouble();
192 m_aDefault
<<= (double)fValue
;
194 else if ((nAnyMask
& DEFAULT_TIME
) == DEFAULT_TIME
)
196 m_aDefault
<<= ::tools::Time(_rxInStream
->readHyper()).GetUNOTime();
198 else if ((nAnyMask
& DEFAULT_DATE
) == DEFAULT_DATE
)
200 m_aDefault
<<= ::Date(_rxInStream
->readLong()).GetUNODate();
203 if ((nAnyMask
& FILTERPROPOSAL
) == FILTERPROPOSAL
)
204 m_bFilterProposal
= true;
208 readHelpTextCompatibly(_rxInStream
);
210 if (bHandleCommonProps
)
211 readCommonEditProperties(_rxInStream
);
213 // After reading, display default values
214 if ( !getControlSource().isEmpty() )
215 // (not if we don't have a control source - the "State" property acts like it is persistent, then)
220 void OEditBaseModel::defaultCommonEditProperties()
222 OBoundControlModel::defaultCommonProperties();
223 // no own common properties at the moment
227 void OEditBaseModel::readCommonEditProperties(const Reference
<XObjectInputStream
>& _rxInStream
)
229 sal_Int32 nLen
= _rxInStream
->readLong();
231 Reference
<XMarkableStream
> xMark(_rxInStream
, UNO_QUERY
);
232 DBG_ASSERT(xMark
.is(), "OBoundControlModel::readCommonProperties : can only work with markable streams !");
233 sal_Int32 nMark
= xMark
->createMark();
235 // read properties common to all OBoundControlModels
236 OBoundControlModel::readCommonProperties(_rxInStream
);
238 // read properties common to all OEditBaseModels
240 // skip the remaining bytes
241 xMark
->jumpToMark(nMark
);
242 _rxInStream
->skipBytes(nLen
);
243 xMark
->deleteMark(nMark
);
247 void OEditBaseModel::writeCommonEditProperties(const Reference
<XObjectOutputStream
>& _rxOutStream
)
249 Reference
<XMarkableStream
> xMark(_rxOutStream
, UNO_QUERY
);
250 DBG_ASSERT(xMark
.is(), "OEditBaseModel::writeCommonProperties : can only work with markable streams !");
251 sal_Int32 nMark
= xMark
->createMark();
253 // a placeholder where we will write the overall length (later in this method)
255 _rxOutStream
->writeLong(nLen
);
257 // write properties common to all OBoundControlModels
258 OBoundControlModel::writeCommonProperties(_rxOutStream
);
260 // write properties common to all OEditBaseModels
262 // close the block - write the correct length at the beginning
263 nLen
= xMark
->offsetToMark(nMark
) - sizeof(nLen
);
264 xMark
->jumpToMark(nMark
);
265 _rxOutStream
->writeLong(nLen
);
266 xMark
->jumpToFurthest();
267 xMark
->deleteMark(nMark
);
271 void OEditBaseModel::getFastPropertyValue( Any
& rValue
, sal_Int32 nHandle
) const
275 case PROPERTY_ID_EMPTY_IS_NULL
:
276 rValue
<<= m_bEmptyIsNull
;
278 case PROPERTY_ID_FILTERPROPOSAL
:
279 rValue
<<= m_bFilterProposal
;
281 case PROPERTY_ID_DEFAULT_TEXT
:
282 rValue
<<= m_aDefaultText
;
284 case PROPERTY_ID_DEFAULT_VALUE
:
285 case PROPERTY_ID_DEFAULT_DATE
:
286 case PROPERTY_ID_DEFAULT_TIME
:
290 OBoundControlModel::getFastPropertyValue(rValue
, nHandle
);
295 sal_Bool
OEditBaseModel::convertFastPropertyValue( Any
& rConvertedValue
, Any
& rOldValue
,
296 sal_Int32 nHandle
, const Any
& rValue
) throw( IllegalArgumentException
)
298 bool bModified(false);
301 case PROPERTY_ID_EMPTY_IS_NULL
:
302 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_bEmptyIsNull
);
304 case PROPERTY_ID_FILTERPROPOSAL
:
305 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_bFilterProposal
);
307 case PROPERTY_ID_DEFAULT_TEXT
:
308 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_aDefaultText
);
310 case PROPERTY_ID_DEFAULT_VALUE
:
311 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_aDefault
, cppu::UnoType
<double>::get());
313 case PROPERTY_ID_DEFAULT_DATE
:
314 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_aDefault
, cppu::UnoType
<util::Date
>::get());
316 case PROPERTY_ID_DEFAULT_TIME
:
317 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_aDefault
, cppu::UnoType
<util::Time
>::get());
320 bModified
= OBoundControlModel::convertFastPropertyValue(
330 void OEditBaseModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle
, const Any
& rValue
) throw ( ::com::sun::star::uno::Exception
, std::exception
)
334 case PROPERTY_ID_EMPTY_IS_NULL
:
335 DBG_ASSERT(rValue
.getValueType().getTypeClass() == TypeClass_BOOLEAN
, "invalid type" );
336 m_bEmptyIsNull
= getBOOL(rValue
);
338 case PROPERTY_ID_FILTERPROPOSAL
:
339 DBG_ASSERT(rValue
.getValueType().getTypeClass() == TypeClass_BOOLEAN
, "invalid type" );
340 m_bFilterProposal
= getBOOL(rValue
);
342 // Changing the default values causes a reset
343 case PROPERTY_ID_DEFAULT_TEXT
:
344 DBG_ASSERT(rValue
.getValueType().getTypeClass() == TypeClass_STRING
, "invalid type" );
345 rValue
>>= m_aDefaultText
;
348 case PROPERTY_ID_DEFAULT_VALUE
:
349 case PROPERTY_ID_DEFAULT_DATE
:
350 case PROPERTY_ID_DEFAULT_TIME
:
355 OBoundControlModel::setFastPropertyValue_NoBroadcast(nHandle
, rValue
);
361 Any
OEditBaseModel::getPropertyDefaultByHandle( sal_Int32 nHandle
) const
365 case PROPERTY_ID_DEFAULT_TEXT
:
366 return makeAny(OUString());
367 case PROPERTY_ID_FILTERPROPOSAL
:
368 return makeAny(false);
369 case PROPERTY_ID_DEFAULT_VALUE
:
370 case PROPERTY_ID_DEFAULT_DATE
:
371 case PROPERTY_ID_DEFAULT_TIME
:
374 return OBoundControlModel::getPropertyDefaultByHandle(nHandle
);
382 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */