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 <tools/debug.hxx>
23 #include <comphelper/basicio.hxx>
24 #include <comphelper/property.hxx>
25 #include <comphelper/types.hxx>
26 #include <tools/time.hxx>
27 #include <tools/date.hxx>
28 #include <com/sun/star/io/XMarkableStream.hpp>
29 #include <com/sun/star/util/Time.hpp>
30 #include <com/sun/star/util/Date.hpp>
35 using namespace ::com::sun::star
;
36 using namespace ::com::sun::star::uno
;
37 using namespace ::com::sun::star::sdb
;
38 using namespace ::com::sun::star::sdbc
;
39 using namespace ::com::sun::star::io
;
40 using namespace ::com::sun::star::util
;
44 const sal_uInt16 DEFAULT_LONG
= 0x0001;
45 const sal_uInt16 DEFAULT_DOUBLE
= 0x0002;
46 const sal_uInt16 FILTERPROPOSAL
= 0x0004;
47 const sal_uInt16 DEFAULT_TIME
= 0x0008;
48 const sal_uInt16 DEFAULT_DATE
= 0x0010;
52 OEditBaseModel::OEditBaseModel( const Reference
< XComponentContext
>& _rxFactory
, const OUString
& rUnoControlModelName
,
53 const OUString
& rDefault
, const bool _bSupportExternalBinding
, const bool _bSupportsValidation
)
54 :OBoundControlModel( _rxFactory
, rUnoControlModelName
, rDefault
, true, _bSupportExternalBinding
, _bSupportsValidation
)
55 ,m_nLastReadVersion(0)
57 ,m_bFilterProposal(false)
62 OEditBaseModel::OEditBaseModel( const OEditBaseModel
* _pOriginal
, const Reference
< XComponentContext
>& _rxFactory
)
63 :OBoundControlModel( _pOriginal
, _rxFactory
)
64 ,m_nLastReadVersion(0)
67 m_bFilterProposal
= _pOriginal
->m_bFilterProposal
;
68 m_bEmptyIsNull
= _pOriginal
->m_bEmptyIsNull
;
69 m_aDefault
= _pOriginal
->m_aDefault
;
70 m_aDefaultText
= _pOriginal
->m_aDefaultText
;
74 OEditBaseModel::~OEditBaseModel( )
80 void OEditBaseModel::write(const Reference
<XObjectOutputStream
>& _rxOutStream
)
82 OBoundControlModel::write(_rxOutStream
);
85 sal_uInt16 nVersionId
= 0x0006;
86 DBG_ASSERT((getPersistenceFlags() & ~PF_SPECIAL_FLAGS
) == 0,
87 "OEditBaseModel::write : invalid special version flags !");
88 // please don't use other flags, older versions can't interpret them !
90 nVersionId
|= getPersistenceFlags();
91 _rxOutStream
->writeShort(nVersionId
);
94 _rxOutStream
->writeShort(0); // obsolete
95 _rxOutStream
<< m_aDefaultText
;
98 sal_uInt16 nAnyMask
= 0;
99 if (m_aDefault
.getValueTypeClass() == TypeClass_LONG
)
100 nAnyMask
|= DEFAULT_LONG
;
101 else if (m_aDefault
.getValueTypeClass() == TypeClass_DOUBLE
)
102 nAnyMask
|= DEFAULT_DOUBLE
;
103 else if (m_aDefault
.getValueType() == cppu::UnoType
<util::Time
>::get())
104 nAnyMask
|= DEFAULT_TIME
;
105 else if (m_aDefault
.getValueType() == cppu::UnoType
<util::Date
>::get())
106 nAnyMask
|= DEFAULT_DATE
;
108 if (m_bFilterProposal
) // Don't save a value, because it's boolean
109 nAnyMask
|= FILTERPROPOSAL
;
111 _rxOutStream
->writeBoolean(m_bEmptyIsNull
);
112 _rxOutStream
->writeShort(nAnyMask
);
114 if ((nAnyMask
& DEFAULT_LONG
) == DEFAULT_LONG
)
115 _rxOutStream
->writeLong(getINT32(m_aDefault
));
116 else if ((nAnyMask
& DEFAULT_DOUBLE
) == DEFAULT_DOUBLE
)
117 _rxOutStream
->writeDouble(getDouble(m_aDefault
));
118 else if ((nAnyMask
& DEFAULT_TIME
) == DEFAULT_TIME
)
121 OSL_VERIFY(m_aDefault
>>= aTime
);
122 _rxOutStream
->writeHyper(::tools::Time(aTime
).GetTime());
124 else if ((nAnyMask
& DEFAULT_DATE
) == DEFAULT_DATE
)
127 OSL_VERIFY(m_aDefault
>>= aDate
);
128 _rxOutStream
->writeLong(::Date(aDate
).GetDate());
131 // since version 5 we write the help text
132 writeHelpTextCompatibly(_rxOutStream
);
133 // (that's potentially bad : at the time I added the above line we had two derived classes : OEditModel and
134 // OFormattedModel. The first one does not have an own version handling, so it can't write the help text itself,
135 // the second one does its own writing (reading) after calling our method, so normally we shouldn't write any
136 // additional members as this is not compatible to older office versions.
137 // We decided to place the writing of the help text here as it seems the less worse alternative. There is no delivered
138 // office version including formatted controls (and thus the OFormattedModel), and the OFormattedModel::read seems
139 // robust against this change (as it will read a wrong and unknown file version and thus set its members to defaults).
141 if ((nVersionId
& PF_HANDLE_COMMON_PROPS
) != 0)
142 writeCommonEditProperties(_rxOutStream
);
144 // !!! properties common to all OEditBaseModel derived classes should be written in writeCommonEditProperties !!!
148 sal_uInt16
OEditBaseModel::getPersistenceFlags() const
150 return PF_HANDLE_COMMON_PROPS
;
154 void OEditBaseModel::read(const Reference
<XObjectInputStream
>& _rxInStream
)
156 OBoundControlModel::read(_rxInStream
);
157 ::osl::MutexGuard
aGuard(m_aMutex
);
159 // Version's own version number
160 sal_uInt16 nVersion
= _rxInStream
->readShort();
161 m_nLastReadVersion
= nVersion
;
163 bool bHandleCommonProps
= (nVersion
& PF_HANDLE_COMMON_PROPS
) != 0;
164 nVersion
= nVersion
& ~PF_SPECIAL_FLAGS
;
167 _rxInStream
->readShort();
169 _rxInStream
>> m_aDefaultText
;
171 if (nVersion
>= 0x0003)
173 m_bEmptyIsNull
= _rxInStream
->readBoolean();
175 sal_uInt16 nAnyMask
= _rxInStream
->readShort();
176 if ((nAnyMask
& DEFAULT_LONG
) == DEFAULT_LONG
)
178 sal_Int32 nValue
= _rxInStream
->readLong();
179 m_aDefault
<<= nValue
;
181 else if ((nAnyMask
& DEFAULT_DOUBLE
) == DEFAULT_DOUBLE
)
183 double fValue
= _rxInStream
->readDouble();
184 m_aDefault
<<= fValue
;
186 else if ((nAnyMask
& DEFAULT_TIME
) == DEFAULT_TIME
)
188 m_aDefault
<<= ::tools::Time::fromEncodedTime(_rxInStream
->readHyper()).GetUNOTime();
190 else if ((nAnyMask
& DEFAULT_DATE
) == DEFAULT_DATE
)
192 m_aDefault
<<= ::Date(_rxInStream
->readLong()).GetUNODate();
195 if ((nAnyMask
& FILTERPROPOSAL
) == FILTERPROPOSAL
)
196 m_bFilterProposal
= true;
200 readHelpTextCompatibly(_rxInStream
);
202 if (bHandleCommonProps
)
203 readCommonEditProperties(_rxInStream
);
205 // After reading, display default values
206 if ( !getControlSource().isEmpty() )
207 // (not if we don't have a control source - the "State" property acts like it is persistent, then)
212 void OEditBaseModel::defaultCommonEditProperties()
214 OBoundControlModel::defaultCommonProperties();
215 // no own common properties at the moment
219 void OEditBaseModel::readCommonEditProperties(const Reference
<XObjectInputStream
>& _rxInStream
)
221 sal_Int32 nLen
= _rxInStream
->readLong();
223 Reference
<XMarkableStream
> xMark(_rxInStream
, UNO_QUERY
);
224 DBG_ASSERT(xMark
.is(), "OBoundControlModel::readCommonProperties : can only work with markable streams !");
225 sal_Int32 nMark
= xMark
->createMark();
227 // read properties common to all OBoundControlModels
228 OBoundControlModel::readCommonProperties(_rxInStream
);
230 // read properties common to all OEditBaseModels
232 // skip the remaining bytes
233 xMark
->jumpToMark(nMark
);
234 _rxInStream
->skipBytes(nLen
);
235 xMark
->deleteMark(nMark
);
239 void OEditBaseModel::writeCommonEditProperties(const Reference
<XObjectOutputStream
>& _rxOutStream
)
241 Reference
<XMarkableStream
> xMark(_rxOutStream
, UNO_QUERY
);
242 DBG_ASSERT(xMark
.is(), "OEditBaseModel::writeCommonProperties : can only work with markable streams !");
243 sal_Int32 nMark
= xMark
->createMark();
245 // a placeholder where we will write the overall length (later in this method)
247 _rxOutStream
->writeLong(nLen
);
249 // write properties common to all OBoundControlModels
250 OBoundControlModel::writeCommonProperties(_rxOutStream
);
252 // write properties common to all OEditBaseModels
254 // close the block - write the correct length at the beginning
255 nLen
= xMark
->offsetToMark(nMark
) - sizeof(nLen
);
256 xMark
->jumpToMark(nMark
);
257 _rxOutStream
->writeLong(nLen
);
258 xMark
->jumpToFurthest();
259 xMark
->deleteMark(nMark
);
263 void OEditBaseModel::getFastPropertyValue( Any
& rValue
, sal_Int32 nHandle
) const
267 case PROPERTY_ID_EMPTY_IS_NULL
:
268 rValue
<<= m_bEmptyIsNull
;
270 case PROPERTY_ID_FILTERPROPOSAL
:
271 rValue
<<= m_bFilterProposal
;
273 case PROPERTY_ID_DEFAULT_TEXT
:
274 rValue
<<= m_aDefaultText
;
276 case PROPERTY_ID_DEFAULT_VALUE
:
277 case PROPERTY_ID_DEFAULT_DATE
:
278 case PROPERTY_ID_DEFAULT_TIME
:
282 OBoundControlModel::getFastPropertyValue(rValue
, nHandle
);
286 sal_Bool
OEditBaseModel::convertFastPropertyValue( Any
& rConvertedValue
, Any
& rOldValue
,
287 sal_Int32 nHandle
, const Any
& rValue
)
289 bool bModified(false);
292 case PROPERTY_ID_EMPTY_IS_NULL
:
293 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_bEmptyIsNull
);
295 case PROPERTY_ID_FILTERPROPOSAL
:
296 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_bFilterProposal
);
298 case PROPERTY_ID_DEFAULT_TEXT
:
299 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_aDefaultText
);
301 case PROPERTY_ID_DEFAULT_VALUE
:
302 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_aDefault
, cppu::UnoType
<double>::get());
304 case PROPERTY_ID_DEFAULT_DATE
:
305 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_aDefault
, cppu::UnoType
<util::Date
>::get());
307 case PROPERTY_ID_DEFAULT_TIME
:
308 bModified
= tryPropertyValue(rConvertedValue
, rOldValue
, rValue
, m_aDefault
, cppu::UnoType
<util::Time
>::get());
311 bModified
= OBoundControlModel::convertFastPropertyValue(
320 void OEditBaseModel::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle
, const Any
& rValue
)
324 case PROPERTY_ID_EMPTY_IS_NULL
:
325 DBG_ASSERT(rValue
.getValueTypeClass() == TypeClass_BOOLEAN
, "invalid type" );
326 m_bEmptyIsNull
= getBOOL(rValue
);
328 case PROPERTY_ID_FILTERPROPOSAL
:
329 DBG_ASSERT(rValue
.getValueTypeClass() == TypeClass_BOOLEAN
, "invalid type" );
330 m_bFilterProposal
= getBOOL(rValue
);
332 // Changing the default values causes a reset
333 case PROPERTY_ID_DEFAULT_TEXT
:
334 DBG_ASSERT(rValue
.getValueTypeClass() == TypeClass_STRING
, "invalid type" );
335 rValue
>>= m_aDefaultText
;
338 case PROPERTY_ID_DEFAULT_VALUE
:
339 case PROPERTY_ID_DEFAULT_DATE
:
340 case PROPERTY_ID_DEFAULT_TIME
:
345 OBoundControlModel::setFastPropertyValue_NoBroadcast(nHandle
, rValue
);
351 Any
OEditBaseModel::getPropertyDefaultByHandle( sal_Int32 nHandle
) const
355 case PROPERTY_ID_DEFAULT_TEXT
:
356 return Any(OUString());
357 case PROPERTY_ID_FILTERPROPOSAL
:
359 case PROPERTY_ID_DEFAULT_VALUE
:
360 case PROPERTY_ID_DEFAULT_DATE
:
361 case PROPERTY_ID_DEFAULT_TIME
:
364 return OBoundControlModel::getPropertyDefaultByHandle(nHandle
);
372 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */