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